Loading fs/cifs/cifsproto.h +0 −2 Original line number Diff line number Diff line Loading @@ -37,8 +37,6 @@ extern void cifs_buf_release(void *); extern struct smb_hdr *cifs_small_buf_get(void); extern void cifs_small_buf_release(void *); extern void free_rsp_buf(int, void *); extern void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, struct kvec *iov); extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, unsigned int /* length */); extern unsigned int _get_xid(void); Loading fs/cifs/transport.c +41 −100 Original line number Diff line number Diff line Loading @@ -124,41 +124,32 @@ cifs_delete_mid(struct mid_q_entry *mid) /* * smb_send_kvec - send an array of kvecs to the server * @server: Server to send the data to * @iov: Pointer to array of kvecs * @n_vec: length of kvec array * @smb_msg: Message to send * @sent: amount of data sent on socket is stored here * * Our basic "send data to server" function. Should be called with srv_mutex * held. The caller is responsible for handling the results. */ static int smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, size_t *sent) { int rc = 0; int i = 0; struct msghdr smb_msg; unsigned int remaining; size_t first_vec = 0; int retries = 0; struct socket *ssocket = server->ssocket; *sent = 0; smb_msg.msg_name = (struct sockaddr *) &server->dstaddr; smb_msg.msg_namelen = sizeof(struct sockaddr); smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; smb_msg->msg_name = (struct sockaddr *) &server->dstaddr; smb_msg->msg_namelen = sizeof(struct sockaddr); smb_msg->msg_control = NULL; smb_msg->msg_controllen = 0; if (server->noblocksnd) smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; else smb_msg.msg_flags = MSG_NOSIGNAL; remaining = 0; for (i = 0; i < n_vec; i++) remaining += iov[i].iov_len; smb_msg->msg_flags = MSG_NOSIGNAL; i = 0; while (remaining) { while (msg_data_left(smb_msg)) { /* * If blocking send, we try 3 times, since each can block * for 5 seconds. For nonblocking we have to try more Loading @@ -177,35 +168,21 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, * after the retries we will kill the socket and * reconnect which may clear the network problem. */ rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], n_vec - first_vec, remaining); rc = sock_sendmsg(ssocket, smb_msg); if (rc == -EAGAIN) { i++; if (i >= 14 || (!server->noblocksnd && (i > 2))) { retries++; if (retries >= 14 || (!server->noblocksnd && (retries > 2))) { cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", ssocket); rc = -EAGAIN; break; return -EAGAIN; } msleep(1 << i); msleep(1 << retries); continue; } if (rc < 0) break; /* send was at least partially successful */ *sent += rc; if (rc == remaining) { remaining = 0; break; } if (rc > remaining) { cifs_dbg(VFS, "sent %d requested %d\n", rc, remaining); break; } return rc; if (rc == 0) { /* should never happen, letting socket clear before Loading @@ -215,59 +192,11 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, continue; } remaining -= rc; /* the line below resets i */ for (i = first_vec; i < n_vec; i++) { if (iov[i].iov_len) { if (rc > iov[i].iov_len) { rc -= iov[i].iov_len; iov[i].iov_len = 0; } else { iov[i].iov_base += rc; iov[i].iov_len -= rc; first_vec = i; break; } } } i = 0; /* in case we get ENOSPC on the next send */ rc = 0; } return rc; /* send was at least partially successful */ *sent += rc; retries = 0; /* in case we get ENOSPC on the next send */ } /** * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec * @rqst: pointer to smb_rqst * @idx: index into the array of the page * @iov: pointer to struct kvec that will hold the result * * Helper function to convert a slot in the rqst->rq_pages array into a kvec. * The page will be kmapped and the address placed into iov_base. The length * will then be adjusted according to the ptailoff. */ void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, struct kvec *iov) { /* * FIXME: We could avoid this kmap altogether if we used * kernel_sendpage instead of kernel_sendmsg. That will only * work if signing is disabled though as sendpage inlines the * page directly into the fraglist. If userspace modifies the * page after we calculate the signature, then the server will * reject it and may break the connection. kernel_sendmsg does * an extra copy of the data and avoids that issue. */ iov->iov_base = kmap(rqst->rq_pages[idx]); /* if last page, don't send beyond this offset into page */ if (idx == (rqst->rq_npages - 1)) iov->iov_len = rqst->rq_tailsz; else iov->iov_len = rqst->rq_pagesz; return 0; } static unsigned long Loading Loading @@ -299,8 +228,9 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); unsigned long send_length; unsigned int i; size_t total_len = 0, sent; size_t total_len = 0, sent, size; struct socket *ssocket = server->ssocket; struct msghdr smb_msg; int val = 1; if (ssocket == NULL) Loading @@ -321,7 +251,13 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, (char *)&val, sizeof(val)); rc = smb_send_kvec(server, iov, n_vec, &sent); size = 0; for (i = 0; i < n_vec; i++) size += iov[i].iov_len; iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size); rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) goto uncork; Loading @@ -329,11 +265,16 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) /* now walk the page array and send each page in it */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); rc = smb_send_kvec(server, &p_iov, 1, &sent); kunmap(rqst->rq_pages[i]); size_t len = i == rqst->rq_npages - 1 ? rqst->rq_tailsz : rqst->rq_pagesz; struct bio_vec bvec = { .bv_page = rqst->rq_pages[i], .bv_len = len }; iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC, &bvec, 1, len); rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) break; Loading Loading
fs/cifs/cifsproto.h +0 −2 Original line number Diff line number Diff line Loading @@ -37,8 +37,6 @@ extern void cifs_buf_release(void *); extern struct smb_hdr *cifs_small_buf_get(void); extern void cifs_small_buf_release(void *); extern void free_rsp_buf(int, void *); extern void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, struct kvec *iov); extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, unsigned int /* length */); extern unsigned int _get_xid(void); Loading
fs/cifs/transport.c +41 −100 Original line number Diff line number Diff line Loading @@ -124,41 +124,32 @@ cifs_delete_mid(struct mid_q_entry *mid) /* * smb_send_kvec - send an array of kvecs to the server * @server: Server to send the data to * @iov: Pointer to array of kvecs * @n_vec: length of kvec array * @smb_msg: Message to send * @sent: amount of data sent on socket is stored here * * Our basic "send data to server" function. Should be called with srv_mutex * held. The caller is responsible for handling the results. */ static int smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, size_t *sent) { int rc = 0; int i = 0; struct msghdr smb_msg; unsigned int remaining; size_t first_vec = 0; int retries = 0; struct socket *ssocket = server->ssocket; *sent = 0; smb_msg.msg_name = (struct sockaddr *) &server->dstaddr; smb_msg.msg_namelen = sizeof(struct sockaddr); smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; smb_msg->msg_name = (struct sockaddr *) &server->dstaddr; smb_msg->msg_namelen = sizeof(struct sockaddr); smb_msg->msg_control = NULL; smb_msg->msg_controllen = 0; if (server->noblocksnd) smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; else smb_msg.msg_flags = MSG_NOSIGNAL; remaining = 0; for (i = 0; i < n_vec; i++) remaining += iov[i].iov_len; smb_msg->msg_flags = MSG_NOSIGNAL; i = 0; while (remaining) { while (msg_data_left(smb_msg)) { /* * If blocking send, we try 3 times, since each can block * for 5 seconds. For nonblocking we have to try more Loading @@ -177,35 +168,21 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, * after the retries we will kill the socket and * reconnect which may clear the network problem. */ rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], n_vec - first_vec, remaining); rc = sock_sendmsg(ssocket, smb_msg); if (rc == -EAGAIN) { i++; if (i >= 14 || (!server->noblocksnd && (i > 2))) { retries++; if (retries >= 14 || (!server->noblocksnd && (retries > 2))) { cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", ssocket); rc = -EAGAIN; break; return -EAGAIN; } msleep(1 << i); msleep(1 << retries); continue; } if (rc < 0) break; /* send was at least partially successful */ *sent += rc; if (rc == remaining) { remaining = 0; break; } if (rc > remaining) { cifs_dbg(VFS, "sent %d requested %d\n", rc, remaining); break; } return rc; if (rc == 0) { /* should never happen, letting socket clear before Loading @@ -215,59 +192,11 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec, continue; } remaining -= rc; /* the line below resets i */ for (i = first_vec; i < n_vec; i++) { if (iov[i].iov_len) { if (rc > iov[i].iov_len) { rc -= iov[i].iov_len; iov[i].iov_len = 0; } else { iov[i].iov_base += rc; iov[i].iov_len -= rc; first_vec = i; break; } } } i = 0; /* in case we get ENOSPC on the next send */ rc = 0; } return rc; /* send was at least partially successful */ *sent += rc; retries = 0; /* in case we get ENOSPC on the next send */ } /** * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec * @rqst: pointer to smb_rqst * @idx: index into the array of the page * @iov: pointer to struct kvec that will hold the result * * Helper function to convert a slot in the rqst->rq_pages array into a kvec. * The page will be kmapped and the address placed into iov_base. The length * will then be adjusted according to the ptailoff. */ void cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx, struct kvec *iov) { /* * FIXME: We could avoid this kmap altogether if we used * kernel_sendpage instead of kernel_sendmsg. That will only * work if signing is disabled though as sendpage inlines the * page directly into the fraglist. If userspace modifies the * page after we calculate the signature, then the server will * reject it and may break the connection. kernel_sendmsg does * an extra copy of the data and avoids that issue. */ iov->iov_base = kmap(rqst->rq_pages[idx]); /* if last page, don't send beyond this offset into page */ if (idx == (rqst->rq_npages - 1)) iov->iov_len = rqst->rq_tailsz; else iov->iov_len = rqst->rq_pagesz; return 0; } static unsigned long Loading Loading @@ -299,8 +228,9 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); unsigned long send_length; unsigned int i; size_t total_len = 0, sent; size_t total_len = 0, sent, size; struct socket *ssocket = server->ssocket; struct msghdr smb_msg; int val = 1; if (ssocket == NULL) Loading @@ -321,7 +251,13 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, (char *)&val, sizeof(val)); rc = smb_send_kvec(server, iov, n_vec, &sent); size = 0; for (i = 0; i < n_vec; i++) size += iov[i].iov_len; iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size); rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) goto uncork; Loading @@ -329,11 +265,16 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) /* now walk the page array and send each page in it */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); rc = smb_send_kvec(server, &p_iov, 1, &sent); kunmap(rqst->rq_pages[i]); size_t len = i == rqst->rq_npages - 1 ? rqst->rq_tailsz : rqst->rq_pagesz; struct bio_vec bvec = { .bv_page = rqst->rq_pages[i], .bv_len = len }; iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC, &bvec, 1, len); rc = smb_send_kvec(server, &smb_msg, &sent); if (rc < 0) break; Loading