Message ID | 20160409205304.GL25498@ZenIV.linux.org.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Sat, 2016-04-09 at 21:53 +0100, Al Viro wrote: > just do ITER_BVEC recvmsg > > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > --- > fs/cifs/cifsproto.h | 7 +++--- > fs/cifs/connect.c | 65 ++++++++++++++++++++++++++++------------------------- > fs/cifs/file.c | 53 ++++++++++++++----------------------------- > 3 files changed, 55 insertions(+), 70 deletions(-) > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index 7d5f53a..0f9a6bc 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -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 *); > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index eb42665..e33c5e0 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -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 > diff --git a/fs/cifs/file.c b/fs/cifs/file.c > index ff882ae..0f71867 100644 > --- a/fs/cifs/file.c > +++ b/fs/cifs/file.c > @@ -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; > Reviewed-by: Jeff Layton <jlayton@poochiereds.net> -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7d5f53a..0f9a6bc 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -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 *); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb42665..e33c5e0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -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 diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ff882ae..0f71867 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -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;
just do ITER_BVEC recvmsg Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/cifs/cifsproto.h | 7 +++--- fs/cifs/connect.c | 65 ++++++++++++++++++++++++++++------------------------- fs/cifs/file.c | 53 ++++++++++++++----------------------------- 3 files changed, 55 insertions(+), 70 deletions(-)