9p: switch p9_client_read() to passing struct iov_iter *
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 2 Apr 2015 03:42:28 +0000 (23:42 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Apr 2015 02:28:27 +0000 (22:28 -0400)
... and make it loop

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/9p/v9fs_vfs.h
fs/9p/vfs_addr.c
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/xattr.c
include/net/9p/client.h
net/9p/client.c

index cff1e61d93551a17c3f37837ada11a727919d271..5a0db6dec8d1fd4ad2673a03188a910606ae42b3 100644 (file)
@@ -68,8 +68,6 @@ int v9fs_file_open(struct inode *inode, struct file *file);
 void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
 int v9fs_uflags2omode(int uflags, int extended);
 
-ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
-ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
 void v9fs_blank_wstat(struct p9_wstat *wstat);
 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
index 402269c108cd865545fd3762ad1b3f28361b339f..afe3225aaf361e8efe57426cce8eb77739941bbf 100644 (file)
  */
 static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
 {
-       int retval;
-       loff_t offset;
-       char *buffer;
-       struct inode *inode;
+       struct inode *inode = page->mapping->host;
+       struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE};
+       struct iov_iter to;
+       int retval, err;
 
-       inode = page->mapping->host;
        p9_debug(P9_DEBUG_VFS, "\n");
 
        BUG_ON(!PageLocked(page));
@@ -65,16 +64,16 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
        if (retval == 0)
                return retval;
 
-       buffer = kmap(page);
-       offset = page_offset(page);
+       iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE);
 
-       retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset);
-       if (retval < 0) {
+       retval = p9_client_read(fid, page_offset(page), &to, &err);
+       if (err) {
                v9fs_uncache_page(inode, page);
+               retval = err;
                goto done;
        }
 
-       memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
+       zero_user(page, retval, PAGE_SIZE - retval);
        flush_dcache_page(page);
        SetPageUptodate(page);
 
@@ -82,7 +81,6 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
        retval = 0;
 
 done:
-       kunmap(page);
        unlock_page(page);
        return retval;
 }
index 4f1151088ebe8779da1af2173818c0088afb2cd0..76c3b1ab6361d69b12f069ed7e9d68b48751eb82 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/inet.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
+#include <linux/uio.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
@@ -115,6 +116,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
        int buflen;
        int reclen = 0;
        struct p9_rdir *rdir;
+       struct kvec kvec;
 
        p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
        fid = file->private_data;
@@ -124,16 +126,21 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
        rdir = v9fs_alloc_rdir_buf(file, buflen);
        if (!rdir)
                return -ENOMEM;
+       kvec.iov_base = rdir->buf;
+       kvec.iov_len = buflen;
 
        while (1) {
                if (rdir->tail == rdir->head) {
-                       err = v9fs_file_readn(file, rdir->buf, NULL,
-                                                       buflen, ctx->pos);
-                       if (err <= 0)
+                       struct iov_iter to;
+                       int n;
+                       iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen);
+                       n = p9_client_read(file->private_data, ctx->pos, &to,
+                                          &err);
+                       if (err)
                                return err;
 
                        rdir->head = 0;
-                       rdir->tail = err;
+                       rdir->tail = n;
                }
                while (rdir->head < rdir->tail) {
                        p9stat_init(&st);
index 1e4619693721b7d0401cd0f095e817261e12579e..069f70d3758fcca2f1fcf10405223575c591b6f4 100644 (file)
@@ -364,63 +364,6 @@ out_err:
        return ret;
 }
 
-/**
- * v9fs_fid_readn - read from a fid
- * @fid: fid to read
- * @data: data buffer to read data into
- * @udata: user data buffer to read data into
- * @count: size of buffer
- * @offset: offset at which to read data
- *
- */
-ssize_t
-v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
-              u64 offset)
-{
-       int n, total, size;
-
-       p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n",
-                fid->fid, (long long unsigned)offset, count);
-       n = 0;
-       total = 0;
-       size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
-       do {
-               n = p9_client_read(fid, data, udata, offset, count);
-               if (n <= 0)
-                       break;
-
-               if (data)
-                       data += n;
-               if (udata)
-                       udata += n;
-
-               offset += n;
-               count -= n;
-               total += n;
-       } while (count > 0 && n == size);
-
-       if (n < 0)
-               total = n;
-
-       return total;
-}
-
-/**
- * v9fs_file_readn - read from a file
- * @filp: file pointer to read
- * @data: data buffer to read data into
- * @udata: user data buffer to read data into
- * @count: size of buffer
- * @offset: offset at which to read data
- *
- */
-ssize_t
-v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
-              u64 offset)
-{
-       return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
-}
-
 /**
  * v9fs_file_read - read from a file
  * @filp: file pointer to read
@@ -434,22 +377,20 @@ static ssize_t
 v9fs_file_read(struct file *filp, char __user *udata, size_t count,
               loff_t * offset)
 {
-       int ret;
-       struct p9_fid *fid;
-       size_t size;
+       struct p9_fid *fid = filp->private_data;
+       struct iovec iov = {.iov_base = udata, .iov_len = count};
+       struct iov_iter to;
+       int ret, err;
 
-       p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset);
-       fid = filp->private_data;
+       iov_iter_init(&to, READ, &iov, 1, count);
 
-       size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
-       if (count > size)
-               ret = v9fs_file_readn(filp, NULL, udata, count, *offset);
-       else
-               ret = p9_client_read(fid, NULL, udata, *offset, count);
+       p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset);
 
-       if (ret > 0)
-               *offset += ret;
+       ret = p9_client_read(fid, *offset, &to, &err);
+       if (!ret)
+               return err;
 
+       *offset += ret;
        return ret;
 }
 
index d4cab07f668d145db022695d014b4ae7269717eb..0cf44b6cccd6ee7dd131033845c7619ad778ab89 100644 (file)
@@ -26,50 +26,34 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
                           void *buffer, size_t buffer_size)
 {
        ssize_t retval;
-       int msize, read_count;
-       u64 offset = 0, attr_size;
+       u64 attr_size;
        struct p9_fid *attr_fid;
+       struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size};
+       struct iov_iter to;
+       int err;
+
+       iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size);
 
        attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
        if (IS_ERR(attr_fid)) {
                retval = PTR_ERR(attr_fid);
                p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n",
                         retval);
-               attr_fid = NULL;
-               goto error;
-       }
-       if (!buffer_size) {
-               /* request to get the attr_size */
-               retval = attr_size;
-               goto error;
+               return retval;
        }
        if (attr_size > buffer_size) {
-               retval = -ERANGE;
-               goto error;
-       }
-       msize = attr_fid->clnt->msize;
-       while (attr_size) {
-               if (attr_size > (msize - P9_IOHDRSZ))
-                       read_count = msize - P9_IOHDRSZ;
+               if (!buffer_size) /* request to get the attr_size */
+                       retval = attr_size;
                else
-                       read_count = attr_size;
-               read_count = p9_client_read(attr_fid, ((char *)buffer)+offset,
-                                       NULL, offset, read_count);
-               if (read_count < 0) {
-                       /* error in xattr read */
-                       retval = read_count;
-                       goto error;
-               }
-               offset += read_count;
-               attr_size -= read_count;
+                       retval = -ERANGE;
+       } else {
+               iov_iter_truncate(&to, attr_size);
+               retval = p9_client_read(attr_fid, 0, &to, &err);
+               if (err)
+                       retval = err;
        }
-       /* Total read xattr bytes */
-       retval = offset;
-error:
-       if (attr_fid)
-               p9_client_clunk(attr_fid);
+       p9_client_clunk(attr_fid);
        return retval;
-
 }
 
 
index 63ae7653389d865c4990317e6321f99ae44a0e5b..c6b97e58cf8455c120c486192e9d38eb9834343a 100644 (file)
@@ -238,8 +238,7 @@ int p9_client_clunk(struct p9_fid *fid);
 int p9_client_fsync(struct p9_fid *fid, int datasync);
 int p9_client_remove(struct p9_fid *fid);
 int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
-int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
-                                                       u64 offset, u32 count);
+int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
 int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
 int p9dirent_read(struct p9_client *clnt, char *buf, int len,
index aa38cfeb8615cd71bae662633c36a16d6abac847..18583bb89db664bc6d432d365da084d53c4d92a3 100644 (file)
@@ -1534,79 +1534,77 @@ error:
 EXPORT_SYMBOL(p9_client_unlinkat);
 
 int
-p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
-                                                               u32 count)
+p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
 {
-       char *dataptr;
+       struct p9_client *clnt = fid->clnt;
        struct p9_req_t *req;
-       struct p9_client *clnt;
-       int err, rsize, non_zc = 0;
-       struct iov_iter to;
-       union {
-               struct kvec kv;
-               struct iovec iov;
-       } v;
-
-       if (data) {
-               v.kv.iov_base = data;
-               v.kv.iov_len = count;
-               iov_iter_kvec(&to, ITER_KVEC | READ, &v.kv, 1, count);
-       } else {
-               v.iov.iov_base = udata;
-               v.iov.iov_len = count;
-               iov_iter_init(&to, READ, &v.iov, 1, count);
-       }
+       int total = 0;
 
        p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
-                  fid->fid, (unsigned long long) offset, count);
-       err = 0;
-       clnt = fid->clnt;
-
-       rsize = fid->iounit;
-       if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
-               rsize = clnt->msize - P9_IOHDRSZ;
+                  fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
+
+       while (iov_iter_count(to)) {
+               int count = iov_iter_count(to);
+               int rsize, non_zc = 0;
+               char *dataptr;
+                       
+               rsize = fid->iounit;
+               if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+                       rsize = clnt->msize - P9_IOHDRSZ;
 
-       if (count < rsize)
-               rsize = count;
+               if (count < rsize)
+                       rsize = count;
 
-       /* Don't bother zerocopy for small IO (< 1024) */
-       if (clnt->trans_mod->zc_request && rsize > 1024) {
-               /*
-                * response header len is 11
-                * PDU Header(7) + IO Size (4)
-                */
-               req = p9_client_zc_rpc(clnt, P9_TREAD, &to, NULL, rsize, 0,
-                                      11, "dqd", fid->fid,
-                                      offset, rsize);
-       } else {
-               non_zc = 1;
-               req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
-                                   rsize);
-       }
-       if (IS_ERR(req)) {
-               err = PTR_ERR(req);
-               goto error;
-       }
+               /* Don't bother zerocopy for small IO (< 1024) */
+               if (clnt->trans_mod->zc_request && rsize > 1024) {
+                       /*
+                        * response header len is 11
+                        * PDU Header(7) + IO Size (4)
+                        */
+                       req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
+                                              0, 11, "dqd", fid->fid,
+                                              offset, rsize);
+               } else {
+                       non_zc = 1;
+                       req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
+                                           rsize);
+               }
+               if (IS_ERR(req)) {
+                       *err = PTR_ERR(req);
+                       break;
+               }
 
-       err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
-       if (err) {
-               trace_9p_protocol_dump(clnt, req->rc);
-               goto free_and_error;
-       }
+               *err = p9pdu_readf(req->rc, clnt->proto_version,
+                                  "D", &count, &dataptr);
+               if (*err) {
+                       trace_9p_protocol_dump(clnt, req->rc);
+                       p9_free_req(clnt, req);
+                       break;
+               }
 
-       p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
+               p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
+               if (!count) {
+                       p9_free_req(clnt, req);
+                       break;
+               }
 
-       if (non_zc && copy_to_iter(dataptr, count, &to) != count) {
-               err = -EFAULT;
-               goto free_and_error;
+               if (non_zc) {
+                       int n = copy_to_iter(dataptr, count, to);
+                       total += n;
+                       offset += n;
+                       if (n != count) {
+                               *err = -EFAULT;
+                               p9_free_req(clnt, req);
+                               break;
+                       }
+               } else {
+                       iov_iter_advance(to, count);
+                       total += count;
+                       offset += count;
+               }
+               p9_free_req(clnt, req);
        }
-       p9_free_req(clnt, req);
-       return count;
-
-free_and_error:
-       p9_free_req(clnt, req);
-error:
-       return err;
+       return total;
 }
 EXPORT_SYMBOL(p9_client_read);