Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

9p: switch p9_client_read() to passing struct iov_iter *

... and make it loop

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro e1200fe6 9565a544

+110 -185
-2
fs/9p/v9fs_vfs.h
··· 68 68 void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); 69 69 int v9fs_uflags2omode(int uflags, int extended); 70 70 71 - ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); 72 - ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64); 73 71 void v9fs_blank_wstat(struct p9_wstat *wstat); 74 72 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); 75 73 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
+9 -11
fs/9p/vfs_addr.c
··· 51 51 */ 52 52 static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) 53 53 { 54 - int retval; 55 - loff_t offset; 56 - char *buffer; 57 - struct inode *inode; 54 + struct inode *inode = page->mapping->host; 55 + struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE}; 56 + struct iov_iter to; 57 + int retval, err; 58 58 59 - inode = page->mapping->host; 60 59 p9_debug(P9_DEBUG_VFS, "\n"); 61 60 62 61 BUG_ON(!PageLocked(page)); ··· 64 65 if (retval == 0) 65 66 return retval; 66 67 67 - buffer = kmap(page); 68 - offset = page_offset(page); 68 + iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); 69 69 70 - retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); 71 - if (retval < 0) { 70 + retval = p9_client_read(fid, page_offset(page), &to, &err); 71 + if (err) { 72 72 v9fs_uncache_page(inode, page); 73 + retval = err; 73 74 goto done; 74 75 } 75 76 76 - memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); 77 + zero_user(page, retval, PAGE_SIZE - retval); 77 78 flush_dcache_page(page); 78 79 SetPageUptodate(page); 79 80 ··· 81 82 retval = 0; 82 83 83 84 done: 84 - kunmap(page); 85 85 unlock_page(page); 86 86 return retval; 87 87 }
+11 -4
fs/9p/vfs_dir.c
··· 33 33 #include <linux/inet.h> 34 34 #include <linux/idr.h> 35 35 #include <linux/slab.h> 36 + #include <linux/uio.h> 36 37 #include <net/9p/9p.h> 37 38 #include <net/9p/client.h> 38 39 ··· 116 115 int buflen; 117 116 int reclen = 0; 118 117 struct p9_rdir *rdir; 118 + struct kvec kvec; 119 119 120 120 p9_debug(P9_DEBUG_VFS, "name %pD\n", file); 121 121 fid = file->private_data; ··· 126 124 rdir = v9fs_alloc_rdir_buf(file, buflen); 127 125 if (!rdir) 128 126 return -ENOMEM; 127 + kvec.iov_base = rdir->buf; 128 + kvec.iov_len = buflen; 129 129 130 130 while (1) { 131 131 if (rdir->tail == rdir->head) { 132 - err = v9fs_file_readn(file, rdir->buf, NULL, 133 - buflen, ctx->pos); 134 - if (err <= 0) 132 + struct iov_iter to; 133 + int n; 134 + iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); 135 + n = p9_client_read(file->private_data, ctx->pos, &to, 136 + &err); 137 + if (err) 135 138 return err; 136 139 137 140 rdir->head = 0; 138 - rdir->tail = err; 141 + rdir->tail = n; 139 142 } 140 143 while (rdir->head < rdir->tail) { 141 144 p9stat_init(&st);
+10 -69
fs/9p/vfs_file.c
··· 365 365 } 366 366 367 367 /** 368 - * v9fs_fid_readn - read from a fid 369 - * @fid: fid to read 370 - * @data: data buffer to read data into 371 - * @udata: user data buffer to read data into 372 - * @count: size of buffer 373 - * @offset: offset at which to read data 374 - * 375 - */ 376 - ssize_t 377 - v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, 378 - u64 offset) 379 - { 380 - int n, total, size; 381 - 382 - p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", 383 - fid->fid, (long long unsigned)offset, count); 384 - n = 0; 385 - total = 0; 386 - size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 387 - do { 388 - n = p9_client_read(fid, data, udata, offset, count); 389 - if (n <= 0) 390 - break; 391 - 392 - if (data) 393 - data += n; 394 - if (udata) 395 - udata += n; 396 - 397 - offset += n; 398 - count -= n; 399 - total += n; 400 - } while (count > 0 && n == size); 401 - 402 - if (n < 0) 403 - total = n; 404 - 405 - return total; 406 - } 407 - 408 - /** 409 - * v9fs_file_readn - read from a file 410 - * @filp: file pointer to read 411 - * @data: data buffer to read data into 412 - * @udata: user data buffer to read data into 413 - * @count: size of buffer 414 - * @offset: offset at which to read data 415 - * 416 - */ 417 - ssize_t 418 - v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, 419 - u64 offset) 420 - { 421 - return v9fs_fid_readn(filp->private_data, data, udata, count, offset); 422 - } 423 - 424 - /** 425 368 * v9fs_file_read - read from a file 426 369 * @filp: file pointer to read 427 370 * @udata: user data buffer to read data into ··· 377 434 v9fs_file_read(struct file *filp, char __user *udata, size_t count, 378 435 loff_t * offset) 379 436 { 380 - int ret; 381 - struct p9_fid *fid; 382 - size_t size; 437 + struct p9_fid *fid = filp->private_data; 438 + struct iovec iov = {.iov_base = udata, .iov_len = count}; 439 + struct iov_iter to; 440 + int ret, err; 441 + 442 + iov_iter_init(&to, READ, &iov, 1, count); 383 443 384 444 p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); 385 - fid = filp->private_data; 386 445 387 - size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 388 - if (count > size) 389 - ret = v9fs_file_readn(filp, NULL, udata, count, *offset); 390 - else 391 - ret = p9_client_read(fid, NULL, udata, *offset, count); 446 + ret = p9_client_read(fid, *offset, &to, &err); 447 + if (!ret) 448 + return err; 392 449 393 - if (ret > 0) 394 - *offset += ret; 395 - 450 + *offset += ret; 396 451 return ret; 397 452 } 398 453
+16 -32
fs/9p/xattr.c
··· 26 26 void *buffer, size_t buffer_size) 27 27 { 28 28 ssize_t retval; 29 - int msize, read_count; 30 - u64 offset = 0, attr_size; 29 + u64 attr_size; 31 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); 32 36 33 37 attr_fid = p9_client_xattrwalk(fid, name, &attr_size); 34 38 if (IS_ERR(attr_fid)) { 35 39 retval = PTR_ERR(attr_fid); 36 40 p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", 37 41 retval); 38 - attr_fid = NULL; 39 - goto error; 40 - } 41 - if (!buffer_size) { 42 - /* request to get the attr_size */ 43 - retval = attr_size; 44 - goto error; 42 + return retval; 45 43 } 46 44 if (attr_size > buffer_size) { 47 - retval = -ERANGE; 48 - goto error; 49 - } 50 - msize = attr_fid->clnt->msize; 51 - while (attr_size) { 52 - if (attr_size > (msize - P9_IOHDRSZ)) 53 - read_count = msize - P9_IOHDRSZ; 45 + if (!buffer_size) /* request to get the attr_size */ 46 + retval = attr_size; 54 47 else 55 - read_count = attr_size; 56 - read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, 57 - NULL, offset, read_count); 58 - if (read_count < 0) { 59 - /* error in xattr read */ 60 - retval = read_count; 61 - goto error; 62 - } 63 - offset += read_count; 64 - attr_size -= read_count; 48 + retval = -ERANGE; 49 + } else { 50 + iov_iter_truncate(&to, attr_size); 51 + retval = p9_client_read(attr_fid, 0, &to, &err); 52 + if (err) 53 + retval = err; 65 54 } 66 - /* Total read xattr bytes */ 67 - retval = offset; 68 - error: 69 - if (attr_fid) 70 - p9_client_clunk(attr_fid); 55 + p9_client_clunk(attr_fid); 71 56 return retval; 72 - 73 57 } 74 58 75 59
+1 -2
include/net/9p/client.h
··· 238 238 int p9_client_fsync(struct p9_fid *fid, int datasync); 239 239 int p9_client_remove(struct p9_fid *fid); 240 240 int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags); 241 - int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, 242 - u64 offset, u32 count); 241 + int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err); 243 242 int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err); 244 243 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); 245 244 int p9dirent_read(struct p9_client *clnt, char *buf, int len,
+63 -65
net/9p/client.c
··· 1534 1534 EXPORT_SYMBOL(p9_client_unlinkat); 1535 1535 1536 1536 int 1537 - p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1538 - u32 count) 1537 + p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) 1539 1538 { 1540 - char *dataptr; 1539 + struct p9_client *clnt = fid->clnt; 1541 1540 struct p9_req_t *req; 1542 - struct p9_client *clnt; 1543 - int err, rsize, non_zc = 0; 1544 - struct iov_iter to; 1545 - union { 1546 - struct kvec kv; 1547 - struct iovec iov; 1548 - } v; 1549 - 1550 - if (data) { 1551 - v.kv.iov_base = data; 1552 - v.kv.iov_len = count; 1553 - iov_iter_kvec(&to, ITER_KVEC | READ, &v.kv, 1, count); 1554 - } else { 1555 - v.iov.iov_base = udata; 1556 - v.iov.iov_len = count; 1557 - iov_iter_init(&to, READ, &v.iov, 1, count); 1558 - } 1541 + int total = 0; 1559 1542 1560 1543 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", 1561 - fid->fid, (unsigned long long) offset, count); 1562 - err = 0; 1563 - clnt = fid->clnt; 1544 + fid->fid, (unsigned long long) offset, (int)iov_iter_count(to)); 1564 1545 1565 - rsize = fid->iounit; 1566 - if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1567 - rsize = clnt->msize - P9_IOHDRSZ; 1546 + while (iov_iter_count(to)) { 1547 + int count = iov_iter_count(to); 1548 + int rsize, non_zc = 0; 1549 + char *dataptr; 1550 + 1551 + rsize = fid->iounit; 1552 + if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1553 + rsize = clnt->msize - P9_IOHDRSZ; 1568 1554 1569 - if (count < rsize) 1570 - rsize = count; 1555 + if (count < rsize) 1556 + rsize = count; 1571 1557 1572 - /* Don't bother zerocopy for small IO (< 1024) */ 1573 - if (clnt->trans_mod->zc_request && rsize > 1024) { 1574 - /* 1575 - * response header len is 11 1576 - * PDU Header(7) + IO Size (4) 1577 - */ 1578 - req = p9_client_zc_rpc(clnt, P9_TREAD, &to, NULL, rsize, 0, 1579 - 11, "dqd", fid->fid, 1580 - offset, rsize); 1581 - } else { 1582 - non_zc = 1; 1583 - req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, 1584 - rsize); 1558 + /* Don't bother zerocopy for small IO (< 1024) */ 1559 + if (clnt->trans_mod->zc_request && rsize > 1024) { 1560 + /* 1561 + * response header len is 11 1562 + * PDU Header(7) + IO Size (4) 1563 + */ 1564 + req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize, 1565 + 0, 11, "dqd", fid->fid, 1566 + offset, rsize); 1567 + } else { 1568 + non_zc = 1; 1569 + req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, 1570 + rsize); 1571 + } 1572 + if (IS_ERR(req)) { 1573 + *err = PTR_ERR(req); 1574 + break; 1575 + } 1576 + 1577 + *err = p9pdu_readf(req->rc, clnt->proto_version, 1578 + "D", &count, &dataptr); 1579 + if (*err) { 1580 + trace_9p_protocol_dump(clnt, req->rc); 1581 + p9_free_req(clnt, req); 1582 + break; 1583 + } 1584 + 1585 + p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1586 + if (!count) { 1587 + p9_free_req(clnt, req); 1588 + break; 1589 + } 1590 + 1591 + if (non_zc) { 1592 + int n = copy_to_iter(dataptr, count, to); 1593 + total += n; 1594 + offset += n; 1595 + if (n != count) { 1596 + *err = -EFAULT; 1597 + p9_free_req(clnt, req); 1598 + break; 1599 + } 1600 + } else { 1601 + iov_iter_advance(to, count); 1602 + total += count; 1603 + offset += count; 1604 + } 1605 + p9_free_req(clnt, req); 1585 1606 } 1586 - if (IS_ERR(req)) { 1587 - err = PTR_ERR(req); 1588 - goto error; 1589 - } 1590 - 1591 - err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1592 - if (err) { 1593 - trace_9p_protocol_dump(clnt, req->rc); 1594 - goto free_and_error; 1595 - } 1596 - 1597 - p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1598 - 1599 - if (non_zc && copy_to_iter(dataptr, count, &to) != count) { 1600 - err = -EFAULT; 1601 - goto free_and_error; 1602 - } 1603 - p9_free_req(clnt, req); 1604 - return count; 1605 - 1606 - free_and_error: 1607 - p9_free_req(clnt, req); 1608 - error: 1609 - return err; 1607 + return total; 1610 1608 } 1611 1609 EXPORT_SYMBOL(p9_client_read); 1612 1610