aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:28:58 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:28:58 -0400
commitc48722c6364ec94738afa42e48b1e1f8f20e3192 (patch)
treeb2abd188e9d7dac738e7d5ddad6b0bc022cd1db8
parent34d0640e268923bb1fb9d244a047cdfcd3f77909 (diff)
parentdcdbd7b269003bec7d729ca3fd143f93cf98f56e (diff)
Merge branch '9p-iov_iter' into for-next
-rw-r--r--fs/9p/v9fs_vfs.h4
-rw-r--r--fs/9p/vfs_addr.c80
-rw-r--r--fs/9p/vfs_dir.c15
-rw-r--r--fs/9p/vfs_file.c326
-rw-r--r--fs/9p/xattr.c80
-rw-r--r--include/net/9p/client.h8
-rw-r--r--include/net/9p/transport.h2
-rw-r--r--net/9p/client.c262
-rw-r--r--net/9p/protocol.c24
-rw-r--r--net/9p/trans_common.c42
-rw-r--r--net/9p/trans_common.h2
-rw-r--r--net/9p/trans_virtio.c137
12 files changed, 355 insertions, 627 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index b83ebfbf3fdc..5a0db6dec8d1 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -68,14 +68,10 @@ int v9fs_file_open(struct inode *inode, struct file *file);
68void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); 68void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
69int v9fs_uflags2omode(int uflags, int extended); 69int v9fs_uflags2omode(int uflags, int extended);
70 70
71ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
72ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
73void v9fs_blank_wstat(struct p9_wstat *wstat); 71void v9fs_blank_wstat(struct p9_wstat *wstat);
74int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); 72int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
75int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, 73int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
76 int datasync); 74 int datasync);
77ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *,
78 const char __user *, size_t, loff_t *, int);
79int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); 75int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
80int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); 76int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode);
81static inline void v9fs_invalidate_inode_attr(struct inode *inode) 77static inline void v9fs_invalidate_inode_attr(struct inode *inode)
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index ff1a5bac4200..2e38f9a5b472 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -51,12 +51,11 @@
51 */ 51 */
52static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) 52static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
53{ 53{
54 int retval; 54 struct inode *inode = page->mapping->host;
55 loff_t offset; 55 struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE};
56 char *buffer; 56 struct iov_iter to;
57 struct inode *inode; 57 int retval, err;
58 58
59 inode = page->mapping->host;
60 p9_debug(P9_DEBUG_VFS, "\n"); 59 p9_debug(P9_DEBUG_VFS, "\n");
61 60
62 BUG_ON(!PageLocked(page)); 61 BUG_ON(!PageLocked(page));
@@ -65,16 +64,16 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
65 if (retval == 0) 64 if (retval == 0)
66 return retval; 65 return retval;
67 66
68 buffer = kmap(page); 67 iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE);
69 offset = page_offset(page);
70 68
71 retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); 69 retval = p9_client_read(fid, page_offset(page), &to, &err);
72 if (retval < 0) { 70 if (err) {
73 v9fs_uncache_page(inode, page); 71 v9fs_uncache_page(inode, page);
72 retval = err;
74 goto done; 73 goto done;
75 } 74 }
76 75
77 memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); 76 zero_user(page, retval, PAGE_SIZE - retval);
78 flush_dcache_page(page); 77 flush_dcache_page(page);
79 SetPageUptodate(page); 78 SetPageUptodate(page);
80 79
@@ -82,7 +81,6 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
82 retval = 0; 81 retval = 0;
83 82
84done: 83done:
85 kunmap(page);
86 unlock_page(page); 84 unlock_page(page);
87 return retval; 85 return retval;
88} 86}
@@ -161,41 +159,32 @@ static void v9fs_invalidate_page(struct page *page, unsigned int offset,
161 159
162static int v9fs_vfs_writepage_locked(struct page *page) 160static int v9fs_vfs_writepage_locked(struct page *page)
163{ 161{
164 char *buffer;
165 int retval, len;
166 loff_t offset, size;
167 mm_segment_t old_fs;
168 struct v9fs_inode *v9inode;
169 struct inode *inode = page->mapping->host; 162 struct inode *inode = page->mapping->host;
163 struct v9fs_inode *v9inode = V9FS_I(inode);
164 loff_t size = i_size_read(inode);
165 struct iov_iter from;
166 struct bio_vec bvec;
167 int err, len;
170 168
171 v9inode = V9FS_I(inode);
172 size = i_size_read(inode);
173 if (page->index == size >> PAGE_CACHE_SHIFT) 169 if (page->index == size >> PAGE_CACHE_SHIFT)
174 len = size & ~PAGE_CACHE_MASK; 170 len = size & ~PAGE_CACHE_MASK;
175 else 171 else
176 len = PAGE_CACHE_SIZE; 172 len = PAGE_CACHE_SIZE;
177 173
178 set_page_writeback(page); 174 bvec.bv_page = page;
179 175 bvec.bv_offset = 0;
180 buffer = kmap(page); 176 bvec.bv_len = len;
181 offset = page_offset(page); 177 iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len);
182 178
183 old_fs = get_fs();
184 set_fs(get_ds());
185 /* We should have writeback_fid always set */ 179 /* We should have writeback_fid always set */
186 BUG_ON(!v9inode->writeback_fid); 180 BUG_ON(!v9inode->writeback_fid);
187 181
188 retval = v9fs_file_write_internal(inode, 182 set_page_writeback(page);
189 v9inode->writeback_fid, 183
190 (__force const char __user *)buffer, 184 p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err);
191 len, &offset, 0);
192 if (retval > 0)
193 retval = 0;
194 185
195 set_fs(old_fs);
196 kunmap(page);
197 end_page_writeback(page); 186 end_page_writeback(page);
198 return retval; 187 return err;
199} 188}
200 189
201static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) 190static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
@@ -261,16 +250,21 @@ static int v9fs_launder_page(struct page *page)
261static ssize_t 250static ssize_t
262v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) 251v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
263{ 252{
264 /* 253 struct file *file = iocb->ki_filp;
265 * FIXME 254 ssize_t n;
266 * Now that we do caching with cache mode enabled, We need 255 int err = 0;
267 * to support direct IO 256 if (rw & WRITE) {
268 */ 257 n = p9_client_write(file->private_data, pos, iter, &err);
269 p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%pD) off/no(%lld/%lu) EINVAL\n", 258 if (n) {
270 iocb->ki_filp, 259 struct inode *inode = file_inode(file);
271 (long long)pos, iter->nr_segs); 260 loff_t i_size = i_size_read(inode);
272 261 if (pos + n > i_size)
273 return -EINVAL; 262 inode_add_bytes(inode, pos + n - i_size);
263 }
264 } else {
265 n = p9_client_read(file->private_data, pos, iter, &err);
266 }
267 return n ? n : err;
274} 268}
275 269
276static int v9fs_write_begin(struct file *filp, struct address_space *mapping, 270static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 4f1151088ebe..76c3b1ab6361 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -33,6 +33,7 @@
33#include <linux/inet.h> 33#include <linux/inet.h>
34#include <linux/idr.h> 34#include <linux/idr.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/uio.h>
36#include <net/9p/9p.h> 37#include <net/9p/9p.h>
37#include <net/9p/client.h> 38#include <net/9p/client.h>
38 39
@@ -115,6 +116,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
115 int buflen; 116 int buflen;
116 int reclen = 0; 117 int reclen = 0;
117 struct p9_rdir *rdir; 118 struct p9_rdir *rdir;
119 struct kvec kvec;
118 120
119 p9_debug(P9_DEBUG_VFS, "name %pD\n", file); 121 p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
120 fid = file->private_data; 122 fid = file->private_data;
@@ -124,16 +126,21 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
124 rdir = v9fs_alloc_rdir_buf(file, buflen); 126 rdir = v9fs_alloc_rdir_buf(file, buflen);
125 if (!rdir) 127 if (!rdir)
126 return -ENOMEM; 128 return -ENOMEM;
129 kvec.iov_base = rdir->buf;
130 kvec.iov_len = buflen;
127 131
128 while (1) { 132 while (1) {
129 if (rdir->tail == rdir->head) { 133 if (rdir->tail == rdir->head) {
130 err = v9fs_file_readn(file, rdir->buf, NULL, 134 struct iov_iter to;
131 buflen, ctx->pos); 135 int n;
132 if (err <= 0) 136 iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen);
137 n = p9_client_read(file->private_data, ctx->pos, &to,
138 &err);
139 if (err)
133 return err; 140 return err;
134 141
135 rdir->head = 0; 142 rdir->head = 0;
136 rdir->tail = err; 143 rdir->tail = n;
137 } 144 }
138 while (rdir->head < rdir->tail) { 145 while (rdir->head < rdir->tail) {
139 p9stat_init(&st); 146 p9stat_init(&st);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index b40133796b87..55cc9c80e187 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -36,6 +36,8 @@
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>
40#include <linux/slab.h>
39#include <net/9p/9p.h> 41#include <net/9p/9p.h>
40#include <net/9p/client.h> 42#include <net/9p/client.h>
41 43
@@ -285,6 +287,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
285 fl->fl_end = glock.start + glock.length - 1; 287 fl->fl_end = glock.start + glock.length - 1;
286 fl->fl_pid = glock.proc_id; 288 fl->fl_pid = glock.proc_id;
287 } 289 }
290 kfree(glock.client_id);
288 return res; 291 return res;
289} 292}
290 293
@@ -364,63 +367,6 @@ out_err:
364} 367}
365 368
366/** 369/**
367 * v9fs_fid_readn - read from a fid
368 * @fid: fid to read
369 * @data: data buffer to read data into
370 * @udata: user data buffer to read data into
371 * @count: size of buffer
372 * @offset: offset at which to read data
373 *
374 */
375ssize_t
376v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
377 u64 offset)
378{
379 int n, total, size;
380
381 p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n",
382 fid->fid, (long long unsigned)offset, count);
383 n = 0;
384 total = 0;
385 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
386 do {
387 n = p9_client_read(fid, data, udata, offset, count);
388 if (n <= 0)
389 break;
390
391 if (data)
392 data += n;
393 if (udata)
394 udata += n;
395
396 offset += n;
397 count -= n;
398 total += n;
399 } while (count > 0 && n == size);
400
401 if (n < 0)
402 total = n;
403
404 return total;
405}
406
407/**
408 * v9fs_file_readn - read from a file
409 * @filp: file pointer to read
410 * @data: data buffer to read data into
411 * @udata: user data buffer to read data into
412 * @count: size of buffer
413 * @offset: offset at which to read data
414 *
415 */
416ssize_t
417v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
418 u64 offset)
419{
420 return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
421}
422
423/**
424 * v9fs_file_read - read from a file 370 * v9fs_file_read - read from a file
425 * @filp: file pointer to read 371 * @filp: file pointer to read
426 * @udata: user data buffer to read data into 372 * @udata: user data buffer to read data into
@@ -430,69 +376,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
430 */ 376 */
431 377
432static ssize_t 378static ssize_t
433v9fs_file_read(struct file *filp, char __user *udata, size_t count, 379v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
434 loff_t * offset)
435{ 380{
436 int ret; 381 struct p9_fid *fid = iocb->ki_filp->private_data;
437 struct p9_fid *fid; 382 int ret, err;
438 size_t size;
439 383
440 p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); 384 p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n",
441 fid = filp->private_data; 385 iov_iter_count(to), iocb->ki_pos);
442 386
443 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 387 ret = p9_client_read(fid, iocb->ki_pos, to, &err);
444 if (count > size) 388 if (!ret)
445 ret = v9fs_file_readn(filp, NULL, udata, count, *offset); 389 return err;
446 else
447 ret = p9_client_read(fid, NULL, udata, *offset, count);
448
449 if (ret > 0)
450 *offset += ret;
451 390
391 iocb->ki_pos += ret;
452 return ret; 392 return ret;
453} 393}
454 394
455ssize_t
456v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
457 const char __user *data, size_t count,
458 loff_t *offset, int invalidate)
459{
460 int n;
461 loff_t i_size;
462 size_t total = 0;
463 loff_t origin = *offset;
464 unsigned long pg_start, pg_end;
465
466 p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n",
467 data, (int)count, (int)*offset);
468
469 do {
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
477 if (invalidate && (total > 0)) {
478 pg_start = origin >> PAGE_CACHE_SHIFT;
479 pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
480 if (inode->i_mapping && inode->i_mapping->nrpages)
481 invalidate_inode_pages2_range(inode->i_mapping,
482 pg_start, pg_end);
483 *offset += total;
484 i_size = i_size_read(inode);
485 if (*offset > i_size) {
486 inode_add_bytes(inode, *offset - i_size);
487 i_size_write(inode, *offset);
488 }
489 }
490 if (n < 0)
491 return n;
492
493 return total;
494}
495
496/** 395/**
497 * v9fs_file_write - write to a file 396 * v9fs_file_write - write to a file
498 * @filp: file pointer to write 397 * @filp: file pointer to write
@@ -502,35 +401,45 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
502 * 401 *
503 */ 402 */
504static ssize_t 403static ssize_t
505v9fs_file_write(struct file *filp, const char __user * data, 404v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
506 size_t count, loff_t *offset)
507{ 405{
406 struct file *file = iocb->ki_filp;
508 ssize_t retval = 0; 407 ssize_t retval = 0;
509 loff_t origin = *offset; 408 loff_t origin = iocb->ki_pos;
409 size_t count = iov_iter_count(from);
410 int err = 0;
510 411
511 412 retval = generic_write_checks(file, &origin, &count, 0);
512 retval = generic_write_checks(filp, &origin, &count, 0);
513 if (retval) 413 if (retval)
514 goto out; 414 return retval;
415
416 iov_iter_truncate(from, count);
515 417
516 retval = -EINVAL;
517 if ((ssize_t) count < 0)
518 goto out;
519 retval = 0;
520 if (!count) 418 if (!count)
521 goto out; 419 return 0;
522 420
523 retval = v9fs_file_write_internal(file_inode(filp), 421 retval = p9_client_write(file->private_data, origin, from, &err);
524 filp->private_data, 422 if (retval > 0) {
525 data, count, &origin, 1); 423 struct inode *inode = file_inode(file);
526 /* update offset on successful write */ 424 loff_t i_size;
527 if (retval > 0) 425 unsigned long pg_start, pg_end;
528 *offset = origin; 426 pg_start = origin >> PAGE_CACHE_SHIFT;
529out: 427 pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT;
530 return retval; 428 if (inode->i_mapping && inode->i_mapping->nrpages)
429 invalidate_inode_pages2_range(inode->i_mapping,
430 pg_start, pg_end);
431 origin += retval;
432 i_size = i_size_read(inode);
433 iocb->ki_pos = origin;
434 if (origin > i_size) {
435 inode_add_bytes(inode, origin - i_size);
436 i_size_write(inode, origin);
437 }
438 return retval;
439 }
440 return err;
531} 441}
532 442
533
534static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, 443static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
535 int datasync) 444 int datasync)
536{ 445{
@@ -657,44 +566,6 @@ out_unlock:
657 return VM_FAULT_NOPAGE; 566 return VM_FAULT_NOPAGE;
658} 567}
659 568
660static ssize_t
661v9fs_direct_read(struct file *filp, char __user *udata, size_t count,
662 loff_t *offsetp)
663{
664 loff_t size, offset;
665 struct inode *inode;
666 struct address_space *mapping;
667
668 offset = *offsetp;
669 mapping = filp->f_mapping;
670 inode = mapping->host;
671 if (!count)
672 return 0;
673 size = i_size_read(inode);
674 if (offset < size)
675 filemap_write_and_wait_range(mapping, offset,
676 offset + count - 1);
677
678 return v9fs_file_read(filp, udata, count, offsetp);
679}
680
681/**
682 * v9fs_cached_file_read - read from a file
683 * @filp: file pointer to read
684 * @data: user data buffer to read data into
685 * @count: size of buffer
686 * @offset: offset at which to read data
687 *
688 */
689static ssize_t
690v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
691 loff_t *offset)
692{
693 if (filp->f_flags & O_DIRECT)
694 return v9fs_direct_read(filp, data, count, offset);
695 return new_sync_read(filp, data, count, offset);
696}
697
698/** 569/**
699 * v9fs_mmap_file_read - read from a file 570 * v9fs_mmap_file_read - read from a file
700 * @filp: file pointer to read 571 * @filp: file pointer to read
@@ -704,84 +575,12 @@ v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
704 * 575 *
705 */ 576 */
706static ssize_t 577static ssize_t
707v9fs_mmap_file_read(struct file *filp, char __user *data, size_t count, 578v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
708 loff_t *offset)
709{ 579{
710 /* TODO: Check if there are dirty pages */ 580 /* TODO: Check if there are dirty pages */
711 return v9fs_file_read(filp, data, count, offset); 581 return v9fs_file_read_iter(iocb, to);
712} 582}
713 583
714static ssize_t
715v9fs_direct_write(struct file *filp, const char __user * data,
716 size_t count, loff_t *offsetp)
717{
718 loff_t offset;
719 ssize_t retval;
720 struct inode *inode;
721 struct address_space *mapping;
722
723 offset = *offsetp;
724 mapping = filp->f_mapping;
725 inode = mapping->host;
726 if (!count)
727 return 0;
728
729 mutex_lock(&inode->i_mutex);
730 retval = filemap_write_and_wait_range(mapping, offset,
731 offset + count - 1);
732 if (retval)
733 goto err_out;
734 /*
735 * After a write we want buffered reads to be sure to go to disk to get
736 * the new data. We invalidate clean cached page from the region we're
737 * about to write. We do this *before* the write so that if we fail
738 * here we fall back to buffered write
739 */
740 if (mapping->nrpages) {
741 pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT;
742 pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
743
744 retval = invalidate_inode_pages2_range(mapping,
745 pg_start, pg_end);
746 /*
747 * If a page can not be invalidated, fall back
748 * to buffered write.
749 */
750 if (retval) {
751 if (retval == -EBUSY)
752 goto buff_write;
753 goto err_out;
754 }
755 }
756 retval = v9fs_file_write(filp, data, count, offsetp);
757err_out:
758 mutex_unlock(&inode->i_mutex);
759 return retval;
760
761buff_write:
762 mutex_unlock(&inode->i_mutex);
763 return new_sync_write(filp, data, count, offsetp);
764}
765
766/**
767 * v9fs_cached_file_write - write to a file
768 * @filp: file pointer to write
769 * @data: data buffer to write data from
770 * @count: size of buffer
771 * @offset: offset at which to write data
772 *
773 */
774static ssize_t
775v9fs_cached_file_write(struct file *filp, const char __user * data,
776 size_t count, loff_t *offset)
777{
778
779 if (filp->f_flags & O_DIRECT)
780 return v9fs_direct_write(filp, data, count, offset);
781 return new_sync_write(filp, data, count, offset);
782}
783
784
785/** 584/**
786 * v9fs_mmap_file_write - write to a file 585 * v9fs_mmap_file_write - write to a file
787 * @filp: file pointer to write 586 * @filp: file pointer to write
@@ -791,14 +590,13 @@ v9fs_cached_file_write(struct file *filp, const char __user * data,
791 * 590 *
792 */ 591 */
793static ssize_t 592static ssize_t
794v9fs_mmap_file_write(struct file *filp, const char __user *data, 593v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
795 size_t count, loff_t *offset)
796{ 594{
797 /* 595 /*
798 * TODO: invalidate mmaps on filp's inode between 596 * TODO: invalidate mmaps on filp's inode between
799 * offset and offset+count 597 * offset and offset+count
800 */ 598 */
801 return v9fs_file_write(filp, data, count, offset); 599 return v9fs_file_write_iter(iocb, from);
802} 600}
803 601
804static void v9fs_mmap_vm_close(struct vm_area_struct *vma) 602static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
@@ -843,8 +641,8 @@ static const struct vm_operations_struct v9fs_mmap_file_vm_ops = {
843 641
844const struct file_operations v9fs_cached_file_operations = { 642const struct file_operations v9fs_cached_file_operations = {
845 .llseek = generic_file_llseek, 643 .llseek = generic_file_llseek,
846 .read = v9fs_cached_file_read, 644 .read = new_sync_read,
847 .write = v9fs_cached_file_write, 645 .write = new_sync_write,
848 .read_iter = generic_file_read_iter, 646 .read_iter = generic_file_read_iter,
849 .write_iter = generic_file_write_iter, 647 .write_iter = generic_file_write_iter,
850 .open = v9fs_file_open, 648 .open = v9fs_file_open,
@@ -856,8 +654,8 @@ const struct file_operations v9fs_cached_file_operations = {
856 654
857const struct file_operations v9fs_cached_file_operations_dotl = { 655const struct file_operations v9fs_cached_file_operations_dotl = {
858 .llseek = generic_file_llseek, 656 .llseek = generic_file_llseek,
859 .read = v9fs_cached_file_read, 657 .read = new_sync_read,
860 .write = v9fs_cached_file_write, 658 .write = new_sync_write,
861 .read_iter = generic_file_read_iter, 659 .read_iter = generic_file_read_iter,
862 .write_iter = generic_file_write_iter, 660 .write_iter = generic_file_write_iter,
863 .open = v9fs_file_open, 661 .open = v9fs_file_open,
@@ -870,8 +668,10 @@ const struct file_operations v9fs_cached_file_operations_dotl = {
870 668
871const struct file_operations v9fs_file_operations = { 669const struct file_operations v9fs_file_operations = {
872 .llseek = generic_file_llseek, 670 .llseek = generic_file_llseek,
873 .read = v9fs_file_read, 671 .read = new_sync_read,
874 .write = v9fs_file_write, 672 .write = new_sync_write,
673 .read_iter = v9fs_file_read_iter,
674 .write_iter = v9fs_file_write_iter,
875 .open = v9fs_file_open, 675 .open = v9fs_file_open,
876 .release = v9fs_dir_release, 676 .release = v9fs_dir_release,
877 .lock = v9fs_file_lock, 677 .lock = v9fs_file_lock,
@@ -881,8 +681,10 @@ const struct file_operations v9fs_file_operations = {
881 681
882const struct file_operations v9fs_file_operations_dotl = { 682const struct file_operations v9fs_file_operations_dotl = {
883 .llseek = generic_file_llseek, 683 .llseek = generic_file_llseek,
884 .read = v9fs_file_read, 684 .read = new_sync_read,
885 .write = v9fs_file_write, 685 .write = new_sync_write,
686 .read_iter = v9fs_file_read_iter,
687 .write_iter = v9fs_file_write_iter,
886 .open = v9fs_file_open, 688 .open = v9fs_file_open,
887 .release = v9fs_dir_release, 689 .release = v9fs_dir_release,
888 .lock = v9fs_file_lock_dotl, 690 .lock = v9fs_file_lock_dotl,
@@ -893,8 +695,10 @@ const struct file_operations v9fs_file_operations_dotl = {
893 695
894const struct file_operations v9fs_mmap_file_operations = { 696const struct file_operations v9fs_mmap_file_operations = {
895 .llseek = generic_file_llseek, 697 .llseek = generic_file_llseek,
896 .read = v9fs_mmap_file_read, 698 .read = new_sync_read,
897 .write = v9fs_mmap_file_write, 699 .write = new_sync_write,
700 .read_iter = v9fs_mmap_file_read_iter,
701 .write_iter = v9fs_mmap_file_write_iter,
898 .open = v9fs_file_open, 702 .open = v9fs_file_open,
899 .release = v9fs_dir_release, 703 .release = v9fs_dir_release,
900 .lock = v9fs_file_lock, 704 .lock = v9fs_file_lock,
@@ -904,8 +708,10 @@ const struct file_operations v9fs_mmap_file_operations = {
904 708
905const struct file_operations v9fs_mmap_file_operations_dotl = { 709const struct file_operations v9fs_mmap_file_operations_dotl = {
906 .llseek = generic_file_llseek, 710 .llseek = generic_file_llseek,
907 .read = v9fs_mmap_file_read, 711 .read = new_sync_read,
908 .write = v9fs_mmap_file_write, 712 .write = new_sync_write,
713 .read_iter = v9fs_mmap_file_read_iter,
714 .write_iter = v9fs_mmap_file_write_iter,
909 .open = v9fs_file_open, 715 .open = v9fs_file_open,
910 .release = v9fs_dir_release, 716 .release = v9fs_dir_release,
911 .lock = v9fs_file_lock_dotl, 717 .lock = v9fs_file_lock_dotl,
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index f95e01e058e4..0cf44b6cccd6 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
@@ -25,50 +26,34 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
25 void *buffer, size_t buffer_size) 26 void *buffer, size_t buffer_size)
26{ 27{
27 ssize_t retval; 28 ssize_t retval;
28 int msize, read_count; 29 u64 attr_size;
29 u64 offset = 0, attr_size;
30 struct p9_fid *attr_fid; 30 struct p9_fid *attr_fid;
31 struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size};
32 struct iov_iter to;
33 int err;
34
35 iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size);
31 36
32 attr_fid = p9_client_xattrwalk(fid, name, &attr_size); 37 attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
33 if (IS_ERR(attr_fid)) { 38 if (IS_ERR(attr_fid)) {
34 retval = PTR_ERR(attr_fid); 39 retval = PTR_ERR(attr_fid);
35 p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", 40 p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n",
36 retval); 41 retval);
37 attr_fid = NULL; 42 return retval;
38 goto error;
39 }
40 if (!buffer_size) {
41 /* request to get the attr_size */
42 retval = attr_size;
43 goto error;
44 } 43 }
45 if (attr_size > buffer_size) { 44 if (attr_size > buffer_size) {
46 retval = -ERANGE; 45 if (!buffer_size) /* request to get the attr_size */
47 goto error; 46 retval = attr_size;
48 }
49 msize = attr_fid->clnt->msize;
50 while (attr_size) {
51 if (attr_size > (msize - P9_IOHDRSZ))
52 read_count = msize - P9_IOHDRSZ;
53 else 47 else
54 read_count = attr_size; 48 retval = -ERANGE;
55 read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, 49 } else {
56 NULL, offset, read_count); 50 iov_iter_truncate(&to, attr_size);
57 if (read_count < 0) { 51 retval = p9_client_read(attr_fid, 0, &to, &err);
58 /* error in xattr read */ 52 if (err)
59 retval = read_count; 53 retval = err;
60 goto error;
61 }
62 offset += read_count;
63 attr_size -= read_count;
64 } 54 }
65 /* Total read xattr bytes */ 55 p9_client_clunk(attr_fid);
66 retval = offset;
67error:
68 if (attr_fid)
69 p9_client_clunk(attr_fid);
70 return retval; 56 return retval;
71
72} 57}
73 58
74 59
@@ -120,8 +105,11 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
120int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, 105int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
121 const void *value, size_t value_len, int flags) 106 const void *value, size_t value_len, int flags)
122{ 107{
123 u64 offset = 0; 108 struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len};
124 int retval, msize, write_count; 109 struct iov_iter from;
110 int retval;
111
112 iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len);
125 113
126 p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", 114 p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n",
127 name, value_len, flags); 115 name, value_len, flags);
@@ -135,29 +123,11 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
135 * On success fid points to xattr 123 * On success fid points to xattr
136 */ 124 */
137 retval = p9_client_xattrcreate(fid, name, value_len, flags); 125 retval = p9_client_xattrcreate(fid, name, value_len, flags);
138 if (retval < 0) { 126 if (retval < 0)
139 p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", 127 p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n",
140 retval); 128 retval);
141 goto err; 129 else
142 } 130 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;
160err:
161 p9_client_clunk(fid); 131 p9_client_clunk(fid);
162 return retval; 132 return retval;
163} 133}
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 6fab66c5c5af..c6b97e58cf84 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
214struct iov_iter;
215
214int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); 216int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
215int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, 217int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
216 const char *name); 218 const char *name);
@@ -236,10 +238,8 @@ int p9_client_clunk(struct p9_fid *fid);
236int p9_client_fsync(struct p9_fid *fid, int datasync); 238int p9_client_fsync(struct p9_fid *fid, int datasync);
237int p9_client_remove(struct p9_fid *fid); 239int p9_client_remove(struct p9_fid *fid);
238int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags); 240int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
239int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, 241int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
240 u64 offset, u32 count); 242int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
241int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
242 u64 offset, u32 count);
243int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); 243int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
244int p9dirent_read(struct p9_client *clnt, char *buf, int len, 244int p9dirent_read(struct p9_client *clnt, char *buf, int len,
245 struct p9_dirent *dirent); 245 struct p9_dirent *dirent);
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 2a25dec30211..5122b5e40f78 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -61,7 +61,7 @@ struct p9_trans_module {
61 int (*cancel) (struct p9_client *, struct p9_req_t *req); 61 int (*cancel) (struct p9_client *, struct p9_req_t *req);
62 int (*cancelled)(struct p9_client *, struct p9_req_t *req); 62 int (*cancelled)(struct p9_client *, struct p9_req_t *req);
63 int (*zc_request)(struct p9_client *, struct p9_req_t *, 63 int (*zc_request)(struct p9_client *, struct p9_req_t *,
64 char *, char *, int , int, int, int); 64 struct iov_iter *, struct iov_iter *, int , int, int);
65}; 65};
66 66
67void v9fs_register_trans(struct p9_trans_module *m); 67void v9fs_register_trans(struct p9_trans_module *m);
diff --git a/net/9p/client.c b/net/9p/client.c
index e86a9bea1d16..6f4c4c88db84 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/uaccess.h> 36#include <linux/uaccess.h>
37#include <linux/uio.h>
37#include <net/9p/9p.h> 38#include <net/9p/9p.h>
38#include <linux/parser.h> 39#include <linux/parser.h>
39#include <net/9p/client.h> 40#include <net/9p/client.h>
@@ -555,7 +556,7 @@ out_err:
555 */ 556 */
556 557
557static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, 558static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
558 char *uidata, int in_hdrlen, int kern_buf) 559 struct iov_iter *uidata, int in_hdrlen)
559{ 560{
560 int err; 561 int err;
561 int ecode; 562 int ecode;
@@ -591,16 +592,11 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
591 ename = &req->rc->sdata[req->rc->offset]; 592 ename = &req->rc->sdata[req->rc->offset];
592 if (len > inline_len) { 593 if (len > inline_len) {
593 /* We have error in external buffer */ 594 /* We have error in external buffer */
594 if (kern_buf) { 595 err = copy_from_iter(ename + inline_len,
595 memcpy(ename + inline_len, uidata, 596 len - inline_len, uidata);
596 len - inline_len); 597 if (err != len - inline_len) {
597 } else { 598 err = -EFAULT;
598 err = copy_from_user(ename + inline_len, 599 goto out_err;
599 uidata, len - inline_len);
600 if (err) {
601 err = -EFAULT;
602 goto out_err;
603 }
604 } 600 }
605 } 601 }
606 ename = NULL; 602 ename = NULL;
@@ -806,8 +802,8 @@ reterr:
806 * p9_client_zc_rpc - issue a request and wait for a response 802 * p9_client_zc_rpc - issue a request and wait for a response
807 * @c: client session 803 * @c: client session
808 * @type: type of request 804 * @type: type of request
809 * @uidata: user bffer that should be ued for zero copy read 805 * @uidata: destination for zero copy read
810 * @uodata: user buffer that shoud be user for zero copy write 806 * @uodata: source for zero copy write
811 * @inlen: read buffer size 807 * @inlen: read buffer size
812 * @olen: write buffer size 808 * @olen: write buffer size
813 * @hdrlen: reader header size, This is the size of response protocol data 809 * @hdrlen: reader header size, This is the size of response protocol data
@@ -816,9 +812,10 @@ reterr:
816 * Returns request structure (which client must free using p9_free_req) 812 * Returns request structure (which client must free using p9_free_req)
817 */ 813 */
818static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, 814static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
819 char *uidata, char *uodata, 815 struct iov_iter *uidata,
816 struct iov_iter *uodata,
820 int inlen, int olen, int in_hdrlen, 817 int inlen, int olen, int in_hdrlen,
821 int kern_buf, const char *fmt, ...) 818 const char *fmt, ...)
822{ 819{
823 va_list ap; 820 va_list ap;
824 int sigpending, err; 821 int sigpending, err;
@@ -841,12 +838,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
841 } else 838 } else
842 sigpending = 0; 839 sigpending = 0;
843 840
844 /* If we are called with KERNEL_DS force kern_buf */
845 if (segment_eq(get_fs(), KERNEL_DS))
846 kern_buf = 1;
847
848 err = c->trans_mod->zc_request(c, req, uidata, uodata, 841 err = c->trans_mod->zc_request(c, req, uidata, uodata,
849 inlen, olen, in_hdrlen, kern_buf); 842 inlen, olen, in_hdrlen);
850 if (err < 0) { 843 if (err < 0) {
851 if (err == -EIO) 844 if (err == -EIO)
852 c->status = Disconnected; 845 c->status = Disconnected;
@@ -876,7 +869,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
876 if (err < 0) 869 if (err < 0)
877 goto reterr; 870 goto reterr;
878 871
879 err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf); 872 err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
880 trace_9p_client_res(c, type, req->rc->tag, err); 873 trace_9p_client_res(c, type, req->rc->tag, err);
881 if (!err) 874 if (!err)
882 return req; 875 return req;
@@ -1123,6 +1116,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
1123 fid = NULL; 1116 fid = NULL;
1124 goto error; 1117 goto error;
1125 } 1118 }
1119 fid->uid = n_uname;
1126 1120
1127 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid, 1121 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid,
1128 afid ? afid->fid : P9_NOFID, uname, aname, n_uname); 1122 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
@@ -1541,142 +1535,128 @@ error:
1541EXPORT_SYMBOL(p9_client_unlinkat); 1535EXPORT_SYMBOL(p9_client_unlinkat);
1542 1536
1543int 1537int
1544p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1538p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
1545 u32 count)
1546{ 1539{
1547 char *dataptr; 1540 struct p9_client *clnt = fid->clnt;
1548 int kernel_buf = 0;
1549 struct p9_req_t *req; 1541 struct p9_req_t *req;
1550 struct p9_client *clnt; 1542 int total = 0;
1551 int err, rsize, non_zc = 0;
1552
1553 1543
1554 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", 1544 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
1555 fid->fid, (unsigned long long) offset, count); 1545 fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
1556 err = 0; 1546
1557 clnt = fid->clnt; 1547 while (iov_iter_count(to)) {
1558 1548 int count = iov_iter_count(to);
1559 rsize = fid->iounit; 1549 int rsize, non_zc = 0;
1560 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1550 char *dataptr;
1561 rsize = clnt->msize - P9_IOHDRSZ; 1551
1562 1552 rsize = fid->iounit;
1563 if (count < rsize) 1553 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1564 rsize = count; 1554 rsize = clnt->msize - P9_IOHDRSZ;
1565 1555
1566 /* Don't bother zerocopy for small IO (< 1024) */ 1556 if (count < rsize)
1567 if (clnt->trans_mod->zc_request && rsize > 1024) { 1557 rsize = count;
1568 char *indata; 1558
1569 if (data) { 1559 /* Don't bother zerocopy for small IO (< 1024) */
1570 kernel_buf = 1; 1560 if (clnt->trans_mod->zc_request && rsize > 1024) {
1571 indata = data; 1561 /*
1572 } else 1562 * response header len is 11
1573 indata = (__force char *)udata; 1563 * PDU Header(7) + IO Size (4)
1574 /* 1564 */
1575 * response header len is 11 1565 req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
1576 * PDU Header(7) + IO Size (4) 1566 0, 11, "dqd", fid->fid,
1577 */ 1567 offset, rsize);
1578 req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0, 1568 } else {
1579 11, kernel_buf, "dqd", fid->fid, 1569 non_zc = 1;
1580 offset, rsize); 1570 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
1581 } else { 1571 rsize);
1582 non_zc = 1; 1572 }
1583 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, 1573 if (IS_ERR(req)) {
1584 rsize); 1574 *err = PTR_ERR(req);
1585 } 1575 break;
1586 if (IS_ERR(req)) { 1576 }
1587 err = PTR_ERR(req);
1588 goto error;
1589 }
1590 1577
1591 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1578 *err = p9pdu_readf(req->rc, clnt->proto_version,
1592 if (err) { 1579 "D", &count, &dataptr);
1593 trace_9p_protocol_dump(clnt, req->rc); 1580 if (*err) {
1594 goto free_and_error; 1581 trace_9p_protocol_dump(clnt, req->rc);
1595 } 1582 p9_free_req(clnt, req);
1583 break;
1584 }
1596 1585
1597 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1586 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1587 if (!count) {
1588 p9_free_req(clnt, req);
1589 break;
1590 }
1598 1591
1599 if (non_zc) { 1592 if (non_zc) {
1600 if (data) { 1593 int n = copy_to_iter(dataptr, count, to);
1601 memmove(data, dataptr, count); 1594 total += n;
1602 } else { 1595 offset += n;
1603 err = copy_to_user(udata, dataptr, count); 1596 if (n != count) {
1604 if (err) { 1597 *err = -EFAULT;
1605 err = -EFAULT; 1598 p9_free_req(clnt, req);
1606 goto free_and_error; 1599 break;
1607 } 1600 }
1601 } else {
1602 iov_iter_advance(to, count);
1603 total += count;
1604 offset += count;
1608 } 1605 }
1606 p9_free_req(clnt, req);
1609 } 1607 }
1610 p9_free_req(clnt, req); 1608 return total;
1611 return count;
1612
1613free_and_error:
1614 p9_free_req(clnt, req);
1615error:
1616 return err;
1617} 1609}
1618EXPORT_SYMBOL(p9_client_read); 1610EXPORT_SYMBOL(p9_client_read);
1619 1611
1620int 1612int
1621p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 1613p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
1622 u64 offset, u32 count)
1623{ 1614{
1624 int err, rsize; 1615 struct p9_client *clnt = fid->clnt;
1625 int kernel_buf = 0;
1626 struct p9_client *clnt;
1627 struct p9_req_t *req; 1616 struct p9_req_t *req;
1617 int total = 0;
1618
1619 p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
1620 fid->fid, (unsigned long long) offset,
1621 iov_iter_count(from));
1622
1623 while (iov_iter_count(from)) {
1624 int count = iov_iter_count(from);
1625 int rsize = fid->iounit;
1626 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1627 rsize = clnt->msize - P9_IOHDRSZ;
1628
1629 if (count < rsize)
1630 rsize = count;
1631
1632 /* Don't bother zerocopy for small IO (< 1024) */
1633 if (clnt->trans_mod->zc_request && rsize > 1024) {
1634 req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0,
1635 rsize, P9_ZC_HDR_SZ, "dqd",
1636 fid->fid, offset, rsize);
1637 } else {
1638 req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid,
1639 offset, rsize, from);
1640 }
1641 if (IS_ERR(req)) {
1642 *err = PTR_ERR(req);
1643 break;
1644 }
1628 1645
1629 p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", 1646 *err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
1630 fid->fid, (unsigned long long) offset, count); 1647 if (*err) {
1631 err = 0; 1648 trace_9p_protocol_dump(clnt, req->rc);
1632 clnt = fid->clnt; 1649 p9_free_req(clnt, req);
1633 1650 }
1634 rsize = fid->iounit;
1635 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1636 rsize = clnt->msize - P9_IOHDRSZ;
1637 1651
1638 if (count < rsize) 1652 p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1639 rsize = count;
1640 1653
1641 /* Don't bother zerocopy for small IO (< 1024) */ 1654 p9_free_req(clnt, req);
1642 if (clnt->trans_mod->zc_request && rsize > 1024) { 1655 iov_iter_advance(from, count);
1643 char *odata; 1656 total += count;
1644 if (data) { 1657 offset += count;
1645 kernel_buf = 1;
1646 odata = data;
1647 } else
1648 odata = (char *)udata;
1649 req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize,
1650 P9_ZC_HDR_SZ, kernel_buf, "dqd",
1651 fid->fid, offset, rsize);
1652 } else {
1653 if (data)
1654 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid,
1655 offset, rsize, data);
1656 else
1657 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
1658 offset, rsize, udata);
1659 }
1660 if (IS_ERR(req)) {
1661 err = PTR_ERR(req);
1662 goto error;
1663 }
1664
1665 err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
1666 if (err) {
1667 trace_9p_protocol_dump(clnt, req->rc);
1668 goto free_and_error;
1669 } 1658 }
1670 1659 return total;
1671 p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1672
1673 p9_free_req(clnt, req);
1674 return count;
1675
1676free_and_error:
1677 p9_free_req(clnt, req);
1678error:
1679 return err;
1680} 1660}
1681EXPORT_SYMBOL(p9_client_write); 1661EXPORT_SYMBOL(p9_client_write);
1682 1662
@@ -2068,6 +2048,10 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
2068 struct p9_client *clnt; 2048 struct p9_client *clnt;
2069 struct p9_req_t *req; 2049 struct p9_req_t *req;
2070 char *dataptr; 2050 char *dataptr;
2051 struct kvec kv = {.iov_base = data, .iov_len = count};
2052 struct iov_iter to;
2053
2054 iov_iter_kvec(&to, READ | ITER_KVEC, &kv, 1, count);
2071 2055
2072 p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", 2056 p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
2073 fid->fid, (unsigned long long) offset, count); 2057 fid->fid, (unsigned long long) offset, count);
@@ -2088,8 +2072,8 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
2088 * response header len is 11 2072 * response header len is 11
2089 * PDU Header(7) + IO Size (4) 2073 * PDU Header(7) + IO Size (4)
2090 */ 2074 */
2091 req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0, 2075 req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0,
2092 11, 1, "dqd", fid->fid, offset, rsize); 2076 11, "dqd", fid->fid, offset, rsize);
2093 } else { 2077 } else {
2094 non_zc = 1; 2078 non_zc = 1;
2095 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, 2079 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index ab9127ec5b7a..e9d0f0c1a048 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -33,6 +33,7 @@
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/stddef.h> 34#include <linux/stddef.h>
35#include <linux/types.h> 35#include <linux/types.h>
36#include <linux/uio.h>
36#include <net/9p/9p.h> 37#include <net/9p/9p.h>
37#include <net/9p/client.h> 38#include <net/9p/client.h>
38#include "protocol.h" 39#include "protocol.h"
@@ -69,10 +70,11 @@ static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
69} 70}
70 71
71static size_t 72static size_t
72pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) 73pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size)
73{ 74{
74 size_t len = min(pdu->capacity - pdu->size, size); 75 size_t len = min(pdu->capacity - pdu->size, size);
75 if (copy_from_user(&pdu->sdata[pdu->size], udata, len)) 76 struct iov_iter i = *from;
77 if (copy_from_iter(&pdu->sdata[pdu->size], len, &i) != len)
76 len = 0; 78 len = 0;
77 79
78 pdu->size += len; 80 pdu->size += len;
@@ -437,23 +439,13 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
437 stbuf->extension, stbuf->n_uid, 439 stbuf->extension, stbuf->n_uid,
438 stbuf->n_gid, stbuf->n_muid); 440 stbuf->n_gid, stbuf->n_muid);
439 } break; 441 } break;
440 case 'D':{ 442 case 'V':{
441 uint32_t count = va_arg(ap, uint32_t);
442 const void *data = va_arg(ap, const void *);
443
444 errcode = p9pdu_writef(pdu, proto_version, "d",
445 count);
446 if (!errcode && pdu_write(pdu, data, count))
447 errcode = -EFAULT;
448 }
449 break;
450 case 'U':{
451 int32_t count = va_arg(ap, int32_t); 443 int32_t count = va_arg(ap, int32_t);
452 const char __user *udata = 444 struct iov_iter *from =
453 va_arg(ap, const void __user *); 445 va_arg(ap, struct iov_iter *);
454 errcode = p9pdu_writef(pdu, proto_version, "d", 446 errcode = p9pdu_writef(pdu, proto_version, "d",
455 count); 447 count);
456 if (!errcode && pdu_write_u(pdu, udata, count)) 448 if (!errcode && pdu_write_u(pdu, from, count))
457 errcode = -EFAULT; 449 errcode = -EFAULT;
458 } 450 }
459 break; 451 break;
diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c
index 2ee3879161b1..38aa6345bdfa 100644
--- a/net/9p/trans_common.c
+++ b/net/9p/trans_common.c
@@ -12,12 +12,8 @@
12 * 12 *
13 */ 13 */
14 14
15#include <linux/slab.h> 15#include <linux/mm.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <net/9p/9p.h>
18#include <net/9p/client.h>
19#include <linux/scatterlist.h>
20#include "trans_common.h"
21 17
22/** 18/**
23 * p9_release_req_pages - Release pages after the transaction. 19 * p9_release_req_pages - Release pages after the transaction.
@@ -31,39 +27,3 @@ void p9_release_pages(struct page **pages, int nr_pages)
31 put_page(pages[i]); 27 put_page(pages[i]);
32} 28}
33EXPORT_SYMBOL(p9_release_pages); 29EXPORT_SYMBOL(p9_release_pages);
34
35/**
36 * p9_nr_pages - Return number of pages needed to accommodate the payload.
37 */
38int p9_nr_pages(char *data, int len)
39{
40 unsigned long start_page, end_page;
41 start_page = (unsigned long)data >> PAGE_SHIFT;
42 end_page = ((unsigned long)data + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
43 return end_page - start_page;
44}
45EXPORT_SYMBOL(p9_nr_pages);
46
47/**
48 * payload_gup - Translates user buffer into kernel pages and
49 * pins them either for read/write through get_user_pages_fast().
50 * @req: Request to be sent to server.
51 * @pdata_off: data offset into the first page after translation (gup).
52 * @pdata_len: Total length of the IO. gup may not return requested # of pages.
53 * @nr_pages: number of pages to accommodate the payload
54 * @rw: Indicates if the pages are for read or write.
55 */
56
57int p9_payload_gup(char *data, int *nr_pages, struct page **pages, int write)
58{
59 int nr_mapped_pages;
60
61 nr_mapped_pages = get_user_pages_fast((unsigned long)data,
62 *nr_pages, write, pages);
63 if (nr_mapped_pages <= 0)
64 return nr_mapped_pages;
65
66 *nr_pages = nr_mapped_pages;
67 return 0;
68}
69EXPORT_SYMBOL(p9_payload_gup);
diff --git a/net/9p/trans_common.h b/net/9p/trans_common.h
index 173bb550a9eb..c43babb3f635 100644
--- a/net/9p/trans_common.h
+++ b/net/9p/trans_common.h
@@ -13,5 +13,3 @@
13 */ 13 */
14 14
15void p9_release_pages(struct page **, int); 15void p9_release_pages(struct page **, int);
16int p9_payload_gup(char *, int *, struct page **, int);
17int p9_nr_pages(char *, int);
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 36a1a739ad68..e62bcbbabb5e 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -217,15 +217,15 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
217 * @start: which segment of the sg_list to start at 217 * @start: which segment of the sg_list to start at
218 * @pdata: a list of pages to add into sg. 218 * @pdata: a list of pages to add into sg.
219 * @nr_pages: number of pages to pack into the scatter/gather list 219 * @nr_pages: number of pages to pack into the scatter/gather list
220 * @data: data to pack into scatter/gather list 220 * @offs: amount of data in the beginning of first page _not_ to pack
221 * @count: amount of data to pack into the scatter/gather list 221 * @count: amount of data to pack into the scatter/gather list
222 */ 222 */
223static int 223static int
224pack_sg_list_p(struct scatterlist *sg, int start, int limit, 224pack_sg_list_p(struct scatterlist *sg, int start, int limit,
225 struct page **pdata, int nr_pages, char *data, int count) 225 struct page **pdata, int nr_pages, size_t offs, int count)
226{ 226{
227 int i = 0, s; 227 int i = 0, s;
228 int data_off; 228 int data_off = offs;
229 int index = start; 229 int index = start;
230 230
231 BUG_ON(nr_pages > (limit - start)); 231 BUG_ON(nr_pages > (limit - start));
@@ -233,16 +233,14 @@ pack_sg_list_p(struct scatterlist *sg, int start, int limit,
233 * if the first page doesn't start at 233 * if the first page doesn't start at
234 * page boundary find the offset 234 * page boundary find the offset
235 */ 235 */
236 data_off = offset_in_page(data);
237 while (nr_pages) { 236 while (nr_pages) {
238 s = rest_of_page(data); 237 s = PAGE_SIZE - data_off;
239 if (s > count) 238 if (s > count)
240 s = count; 239 s = count;
241 /* Make sure we don't terminate early. */ 240 /* Make sure we don't terminate early. */
242 sg_unmark_end(&sg[index]); 241 sg_unmark_end(&sg[index]);
243 sg_set_page(&sg[index++], pdata[i++], s, data_off); 242 sg_set_page(&sg[index++], pdata[i++], s, data_off);
244 data_off = 0; 243 data_off = 0;
245 data += s;
246 count -= s; 244 count -= s;
247 nr_pages--; 245 nr_pages--;
248 } 246 }
@@ -314,11 +312,20 @@ req_retry:
314} 312}
315 313
316static int p9_get_mapped_pages(struct virtio_chan *chan, 314static int p9_get_mapped_pages(struct virtio_chan *chan,
317 struct page **pages, char *data, 315 struct page ***pages,
318 int nr_pages, int write, int kern_buf) 316 struct iov_iter *data,
317 int count,
318 size_t *offs,
319 int *need_drop)
319{ 320{
321 int nr_pages;
320 int err; 322 int err;
321 if (!kern_buf) { 323
324 if (!iov_iter_count(data))
325 return 0;
326
327 if (!(data->type & ITER_KVEC)) {
328 int n;
322 /* 329 /*
323 * We allow only p9_max_pages pinned. We wait for the 330 * We allow only p9_max_pages pinned. We wait for the
324 * Other zc request to finish here 331 * Other zc request to finish here
@@ -329,26 +336,49 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
329 if (err == -ERESTARTSYS) 336 if (err == -ERESTARTSYS)
330 return err; 337 return err;
331 } 338 }
332 err = p9_payload_gup(data, &nr_pages, pages, write); 339 n = iov_iter_get_pages_alloc(data, pages, count, offs);
333 if (err < 0) 340 if (n < 0)
334 return err; 341 return n;
342 *need_drop = 1;
343 nr_pages = DIV_ROUND_UP(n + *offs, PAGE_SIZE);
335 atomic_add(nr_pages, &vp_pinned); 344 atomic_add(nr_pages, &vp_pinned);
345 return n;
336 } else { 346 } else {
337 /* kernel buffer, no need to pin pages */ 347 /* kernel buffer, no need to pin pages */
338 int s, index = 0; 348 int index;
339 int count = nr_pages; 349 size_t len;
340 while (nr_pages) { 350 void *p;
341 s = rest_of_page(data); 351
342 if (is_vmalloc_addr(data)) 352 /* we'd already checked that it's non-empty */
343 pages[index++] = vmalloc_to_page(data); 353 while (1) {
354 len = iov_iter_single_seg_count(data);
355 if (likely(len)) {
356 p = data->kvec->iov_base + data->iov_offset;
357 break;
358 }
359 iov_iter_advance(data, 0);
360 }
361 if (len > count)
362 len = count;
363
364 nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) -
365 (unsigned long)p / PAGE_SIZE;
366
367 *pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
368 if (!*pages)
369 return -ENOMEM;
370
371 *need_drop = 0;
372 p -= (*offs = (unsigned long)p % PAGE_SIZE);
373 for (index = 0; index < nr_pages; index++) {
374 if (is_vmalloc_addr(p))
375 (*pages)[index] = vmalloc_to_page(p);
344 else 376 else
345 pages[index++] = kmap_to_page(data); 377 (*pages)[index] = kmap_to_page(p);
346 data += s; 378 p += PAGE_SIZE;
347 nr_pages--;
348 } 379 }
349 nr_pages = count; 380 return len;
350 } 381 }
351 return nr_pages;
352} 382}
353 383
354/** 384/**
@@ -364,8 +394,8 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
364 */ 394 */
365static int 395static int
366p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, 396p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
367 char *uidata, char *uodata, int inlen, 397 struct iov_iter *uidata, struct iov_iter *uodata,
368 int outlen, int in_hdr_len, int kern_buf) 398 int inlen, int outlen, int in_hdr_len)
369{ 399{
370 int in, out, err, out_sgs, in_sgs; 400 int in, out, err, out_sgs, in_sgs;
371 unsigned long flags; 401 unsigned long flags;
@@ -373,41 +403,32 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
373 struct page **in_pages = NULL, **out_pages = NULL; 403 struct page **in_pages = NULL, **out_pages = NULL;
374 struct virtio_chan *chan = client->trans; 404 struct virtio_chan *chan = client->trans;
375 struct scatterlist *sgs[4]; 405 struct scatterlist *sgs[4];
406 size_t offs;
407 int need_drop = 0;
376 408
377 p9_debug(P9_DEBUG_TRANS, "virtio request\n"); 409 p9_debug(P9_DEBUG_TRANS, "virtio request\n");
378 410
379 if (uodata) { 411 if (uodata) {
380 out_nr_pages = p9_nr_pages(uodata, outlen); 412 int n = p9_get_mapped_pages(chan, &out_pages, uodata,
381 out_pages = kmalloc(sizeof(struct page *) * out_nr_pages, 413 outlen, &offs, &need_drop);
382 GFP_NOFS); 414 if (n < 0)
383 if (!out_pages) { 415 return n;
384 err = -ENOMEM; 416 out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
385 goto err_out; 417 if (n != outlen) {
386 } 418 __le32 v = cpu_to_le32(n);
387 out_nr_pages = p9_get_mapped_pages(chan, out_pages, uodata, 419 memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
388 out_nr_pages, 0, kern_buf); 420 outlen = n;
389 if (out_nr_pages < 0) {
390 err = out_nr_pages;
391 kfree(out_pages);
392 out_pages = NULL;
393 goto err_out;
394 } 421 }
395 } 422 } else if (uidata) {
396 if (uidata) { 423 int n = p9_get_mapped_pages(chan, &in_pages, uidata,
397 in_nr_pages = p9_nr_pages(uidata, inlen); 424 inlen, &offs, &need_drop);
398 in_pages = kmalloc(sizeof(struct page *) * in_nr_pages, 425 if (n < 0)
399 GFP_NOFS); 426 return n;
400 if (!in_pages) { 427 in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE);
401 err = -ENOMEM; 428 if (n != inlen) {
402 goto err_out; 429 __le32 v = cpu_to_le32(n);
403 } 430 memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
404 in_nr_pages = p9_get_mapped_pages(chan, in_pages, uidata, 431 inlen = n;
405 in_nr_pages, 1, kern_buf);
406 if (in_nr_pages < 0) {
407 err = in_nr_pages;
408 kfree(in_pages);
409 in_pages = NULL;
410 goto err_out;
411 } 432 }
412 } 433 }
413 req->status = REQ_STATUS_SENT; 434 req->status = REQ_STATUS_SENT;
@@ -426,7 +447,7 @@ req_retry_pinned:
426 if (out_pages) { 447 if (out_pages) {
427 sgs[out_sgs++] = chan->sg + out; 448 sgs[out_sgs++] = chan->sg + out;
428 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, 449 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
429 out_pages, out_nr_pages, uodata, outlen); 450 out_pages, out_nr_pages, offs, outlen);
430 } 451 }
431 452
432 /* 453 /*
@@ -444,7 +465,7 @@ req_retry_pinned:
444 if (in_pages) { 465 if (in_pages) {
445 sgs[out_sgs + in_sgs++] = chan->sg + out + in; 466 sgs[out_sgs + in_sgs++] = chan->sg + out + in;
446 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, 467 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
447 in_pages, in_nr_pages, uidata, inlen); 468 in_pages, in_nr_pages, offs, inlen);
448 } 469 }
449 470
450 BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); 471 BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs));
@@ -478,7 +499,7 @@ req_retry_pinned:
478 * Non kernel buffers are pinned, unpin them 499 * Non kernel buffers are pinned, unpin them
479 */ 500 */
480err_out: 501err_out:
481 if (!kern_buf) { 502 if (need_drop) {
482 if (in_pages) { 503 if (in_pages) {
483 p9_release_pages(in_pages, in_nr_pages); 504 p9_release_pages(in_pages, in_nr_pages);
484 atomic_sub(in_nr_pages, &vp_pinned); 505 atomic_sub(in_nr_pages, &vp_pinned);