cifs: don't bother with kmap on read_pages side
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 10 Jan 2016 00:54:50 +0000 (19:54 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 28 Mar 2016 18:05:52 +0000 (14:05 -0400)
just do ITER_BVEC recvmsg

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/file.c

index 7d5f53a0192285ff9c8fe4906730cf27164d02b8..0f9a6bc4ba43b27aaffe1f4a5c02429259b3847a 100644 (file)
@@ -179,10 +179,9 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
 
 extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
-                    unsigned int to_read);
-extern int cifs_readv_from_socket(struct TCP_Server_Info *server,
-               struct kvec *iov_orig, unsigned int nr_segs,
-               unsigned int to_read);
+                                unsigned int to_read);
+extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
+                                     struct page *page, unsigned int to_read);
 extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                               struct cifs_sb_info *cifs_sb);
 extern int cifs_match_super(struct super_block *, void *);
index eb426658566d319e878ab8c038b71067f79d7ece..e33c5e0ecfd0667fb0bf09ee5fcb83c2f631f6d8 100644 (file)
@@ -501,39 +501,34 @@ server_unresponsive(struct TCP_Server_Info *server)
        return false;
 }
 
-int
-cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
-                      unsigned int nr_segs, unsigned int to_read)
+static int
+cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 {
        int length = 0;
        int total_read;
-       struct msghdr smb_msg;
 
-       smb_msg.msg_control = NULL;
-       smb_msg.msg_controllen = 0;
-       iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC,
-                     iov_orig, nr_segs, to_read);
+       smb_msg->msg_control = NULL;
+       smb_msg->msg_controllen = 0;
 
-       for (total_read = 0; msg_data_left(&smb_msg); total_read += length) {
+       for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
                try_to_freeze();
 
-               if (server_unresponsive(server)) {
-                       total_read = -ECONNABORTED;
-                       break;
-               }
+               if (server_unresponsive(server))
+                       return -ECONNABORTED;
 
-               length = sock_recvmsg(server->ssocket, &smb_msg, 0);
+               length = sock_recvmsg(server->ssocket, smb_msg, 0);
 
-               if (server->tcpStatus == CifsExiting) {
-                       total_read = -ESHUTDOWN;
-                       break;
-               } else if (server->tcpStatus == CifsNeedReconnect) {
+               if (server->tcpStatus == CifsExiting)
+                       return -ESHUTDOWN;
+
+               if (server->tcpStatus == CifsNeedReconnect) {
                        cifs_reconnect(server);
-                       total_read = -ECONNABORTED;
-                       break;
-               } else if (length == -ERESTARTSYS ||
-                          length == -EAGAIN ||
-                          length == -EINTR) {
+                       return -ECONNABORTED;
+               }
+
+               if (length == -ERESTARTSYS ||
+                   length == -EAGAIN ||
+                   length == -EINTR) {
                        /*
                         * Minimum sleep to prevent looping, allowing socket
                         * to clear and app threads to set tcpStatus
@@ -542,11 +537,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
                        usleep_range(1000, 2000);
                        length = 0;
                        continue;
-               } else if (length <= 0) {
+               }
+
+               if (length <= 0) {
                        cifs_dbg(FYI, "Received no data or error: %d\n", length);
                        cifs_reconnect(server);
-                       total_read = -ECONNABORTED;
-                       break;
+                       return -ECONNABORTED;
                }
        }
        return total_read;
@@ -556,12 +552,21 @@ int
 cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
                      unsigned int to_read)
 {
-       struct kvec iov;
+       struct msghdr smb_msg;
+       struct kvec iov = {.iov_base = buf, .iov_len = to_read};
+       iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
 
-       iov.iov_base = buf;
-       iov.iov_len = to_read;
+       return cifs_readv_from_socket(server, &smb_msg);
+}
 
-       return cifs_readv_from_socket(server, &iov, 1, to_read);
+int
+cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
+                     unsigned int to_read)
+{
+       struct msghdr smb_msg;
+       struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
+       iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
+       return cifs_readv_from_socket(server, &smb_msg);
 }
 
 static bool
index ff882aeaccc67c404a289fff472a26d8537e1128..0f718679186e17577800404ba4bb2212b5d84c00 100644 (file)
@@ -2855,39 +2855,31 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
        int result = 0;
        unsigned int i;
        unsigned int nr_pages = rdata->nr_pages;
-       struct kvec iov;
 
        rdata->got_bytes = 0;
        rdata->tailsz = PAGE_SIZE;
        for (i = 0; i < nr_pages; i++) {
                struct page *page = rdata->pages[i];
+               size_t n;
 
-               if (len >= PAGE_SIZE) {
-                       /* enough data to fill the page */
-                       iov.iov_base = kmap(page);
-                       iov.iov_len = PAGE_SIZE;
-                       cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
-                                i, iov.iov_base, iov.iov_len);
-                       len -= PAGE_SIZE;
-               } else if (len > 0) {
-                       /* enough for partial page, fill and zero the rest */
-                       iov.iov_base = kmap(page);
-                       iov.iov_len = len;
-                       cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
-                                i, iov.iov_base, iov.iov_len);
-                       memset(iov.iov_base + len, '\0', PAGE_SIZE - len);
-                       rdata->tailsz = len;
-                       len = 0;
-               } else {
+               if (len <= 0) {
                        /* no need to hold page hostage */
                        rdata->pages[i] = NULL;
                        rdata->nr_pages--;
                        put_page(page);
                        continue;
                }
-
-               result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
-               kunmap(page);
+               n = len;
+               if (len >= PAGE_SIZE) {
+                       /* enough data to fill the page */
+                       n = PAGE_SIZE;
+                       len -= n;
+               } else {
+                       zero_user(page, len, PAGE_SIZE - len);
+                       rdata->tailsz = len;
+                       len = 0;
+               }
+               result = cifs_read_page_from_socket(server, page, n);
                if (result < 0)
                        break;
 
@@ -3303,7 +3295,6 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
        u64 eof;
        pgoff_t eof_index;
        unsigned int nr_pages = rdata->nr_pages;
-       struct kvec iov;
 
        /* determine the eof that the server (probably) has */
        eof = CIFS_I(rdata->mapping->host)->server_eof;
@@ -3314,23 +3305,14 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
        rdata->tailsz = PAGE_CACHE_SIZE;
        for (i = 0; i < nr_pages; i++) {
                struct page *page = rdata->pages[i];
+               size_t n = PAGE_CACHE_SIZE;
 
                if (len >= PAGE_CACHE_SIZE) {
-                       /* enough data to fill the page */
-                       iov.iov_base = kmap(page);
-                       iov.iov_len = PAGE_CACHE_SIZE;
-                       cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
-                                i, page->index, iov.iov_base, iov.iov_len);
                        len -= PAGE_CACHE_SIZE;
                } else if (len > 0) {
                        /* enough for partial page, fill and zero the rest */
-                       iov.iov_base = kmap(page);
-                       iov.iov_len = len;
-                       cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
-                                i, page->index, iov.iov_base, iov.iov_len);
-                       memset(iov.iov_base + len,
-                               '\0', PAGE_CACHE_SIZE - len);
-                       rdata->tailsz = len;
+                       zero_user(page, len, PAGE_CACHE_SIZE - len);
+                       n = rdata->tailsz = len;
                        len = 0;
                } else if (page->index > eof_index) {
                        /*
@@ -3360,8 +3342,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
                        continue;
                }
 
-               result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
-               kunmap(page);
+               result = cifs_read_page_from_socket(server, page, n);
                if (result < 0)
                        break;