diff options
| -rw-r--r-- | fs/ncpfs/sock.c | 111 |
1 files changed, 41 insertions, 70 deletions
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index f32f272ee501..f013c92bb5d8 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c | |||
| @@ -40,19 +40,12 @@ static int _recv(struct socket *sock, void *buf, int size, unsigned flags) | |||
| 40 | return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); | 40 | return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static inline int do_send(struct socket *sock, struct kvec *vec, int count, | ||
| 44 | int len, unsigned flags) | ||
| 45 | { | ||
| 46 | struct msghdr msg = { .msg_flags = flags }; | ||
| 47 | return kernel_sendmsg(sock, &msg, vec, count, len); | ||
| 48 | } | ||
| 49 | |||
| 50 | static int _send(struct socket *sock, const void *buff, int len) | 43 | static int _send(struct socket *sock, const void *buff, int len) |
| 51 | { | 44 | { |
| 52 | struct kvec vec; | 45 | struct msghdr msg = { .msg_flags = 0 }; |
| 53 | vec.iov_base = (void *) buff; | 46 | struct kvec vec = {.iov_base = (void *)buff, .iov_len = len}; |
| 54 | vec.iov_len = len; | 47 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len); |
| 55 | return do_send(sock, &vec, 1, len, 0); | 48 | return sock_sendmsg(sock, &msg); |
| 56 | } | 49 | } |
| 57 | 50 | ||
| 58 | struct ncp_request_reply { | 51 | struct ncp_request_reply { |
| @@ -63,9 +56,7 @@ struct ncp_request_reply { | |||
| 63 | size_t datalen; | 56 | size_t datalen; |
| 64 | int result; | 57 | int result; |
| 65 | enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; | 58 | enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; |
| 66 | struct kvec* tx_ciov; | 59 | struct iov_iter from; |
| 67 | size_t tx_totallen; | ||
| 68 | size_t tx_iovlen; | ||
| 69 | struct kvec tx_iov[3]; | 60 | struct kvec tx_iov[3]; |
| 70 | u_int16_t tx_type; | 61 | u_int16_t tx_type; |
| 71 | u_int32_t sign[6]; | 62 | u_int32_t sign[6]; |
| @@ -205,28 +196,22 @@ static inline void __ncptcp_abort(struct ncp_server *server) | |||
| 205 | 196 | ||
| 206 | static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) | 197 | static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) |
| 207 | { | 198 | { |
| 208 | struct kvec vec[3]; | 199 | struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT }; |
| 209 | /* sock_sendmsg updates iov pointers for us :-( */ | 200 | return sock_sendmsg(sock, &msg); |
| 210 | memcpy(vec, req->tx_ciov, req->tx_iovlen * sizeof(vec[0])); | ||
| 211 | return do_send(sock, vec, req->tx_iovlen, | ||
| 212 | req->tx_totallen, MSG_DONTWAIT); | ||
| 213 | } | 201 | } |
| 214 | 202 | ||
| 215 | static void __ncptcp_try_send(struct ncp_server *server) | 203 | static void __ncptcp_try_send(struct ncp_server *server) |
| 216 | { | 204 | { |
| 217 | struct ncp_request_reply *rq; | 205 | struct ncp_request_reply *rq; |
| 218 | struct kvec *iov; | 206 | struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT }; |
| 219 | struct kvec iovc[3]; | ||
| 220 | int result; | 207 | int result; |
| 221 | 208 | ||
| 222 | rq = server->tx.creq; | 209 | rq = server->tx.creq; |
| 223 | if (!rq) | 210 | if (!rq) |
| 224 | return; | 211 | return; |
| 225 | 212 | ||
| 226 | /* sock_sendmsg updates iov pointers for us :-( */ | 213 | msg.msg_iter = rq->from; |
| 227 | memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0])); | 214 | result = sock_sendmsg(server->ncp_sock, &msg); |
| 228 | result = do_send(server->ncp_sock, iovc, rq->tx_iovlen, | ||
| 229 | rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT); | ||
| 230 | 215 | ||
| 231 | if (result == -EAGAIN) | 216 | if (result == -EAGAIN) |
| 232 | return; | 217 | return; |
| @@ -236,21 +221,12 @@ static void __ncptcp_try_send(struct ncp_server *server) | |||
| 236 | __ncp_abort_request(server, rq, result); | 221 | __ncp_abort_request(server, rq, result); |
| 237 | return; | 222 | return; |
| 238 | } | 223 | } |
| 239 | if (result >= rq->tx_totallen) { | 224 | if (!msg_data_left(&msg)) { |
| 240 | server->rcv.creq = rq; | 225 | server->rcv.creq = rq; |
| 241 | server->tx.creq = NULL; | 226 | server->tx.creq = NULL; |
| 242 | return; | 227 | return; |
| 243 | } | 228 | } |
| 244 | rq->tx_totallen -= result; | 229 | rq->from = msg.msg_iter; |
| 245 | iov = rq->tx_ciov; | ||
| 246 | while (iov->iov_len <= result) { | ||
| 247 | result -= iov->iov_len; | ||
| 248 | iov++; | ||
| 249 | rq->tx_iovlen--; | ||
| 250 | } | ||
| 251 | iov->iov_base += result; | ||
| 252 | iov->iov_len -= result; | ||
| 253 | rq->tx_ciov = iov; | ||
| 254 | } | 230 | } |
| 255 | 231 | ||
| 256 | static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) | 232 | static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) |
| @@ -263,22 +239,21 @@ static inline void ncp_init_header(struct ncp_server *server, struct ncp_request | |||
| 263 | 239 | ||
| 264 | static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) | 240 | static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) |
| 265 | { | 241 | { |
| 266 | size_t signlen; | 242 | size_t signlen, len = req->tx_iov[1].iov_len; |
| 267 | struct ncp_request_header* h; | 243 | struct ncp_request_header *h = req->tx_iov[1].iov_base; |
| 268 | 244 | ||
| 269 | req->tx_ciov = req->tx_iov + 1; | ||
| 270 | |||
| 271 | h = req->tx_iov[1].iov_base; | ||
| 272 | ncp_init_header(server, req, h); | 245 | ncp_init_header(server, req, h); |
| 273 | signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, | 246 | signlen = sign_packet(server, |
| 274 | req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, | 247 | req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, |
| 275 | cpu_to_le32(req->tx_totallen), req->sign); | 248 | len - sizeof(struct ncp_request_header) + 1, |
| 249 | cpu_to_le32(len), req->sign); | ||
| 276 | if (signlen) { | 250 | if (signlen) { |
| 277 | req->tx_ciov[1].iov_base = req->sign; | 251 | /* NCP over UDP appends signature */ |
| 278 | req->tx_ciov[1].iov_len = signlen; | 252 | req->tx_iov[2].iov_base = req->sign; |
| 279 | req->tx_iovlen += 1; | 253 | req->tx_iov[2].iov_len = signlen; |
| 280 | req->tx_totallen += signlen; | ||
| 281 | } | 254 | } |
| 255 | iov_iter_kvec(&req->from, WRITE | ITER_KVEC, | ||
| 256 | req->tx_iov + 1, signlen ? 2 : 1, len + signlen); | ||
| 282 | server->rcv.creq = req; | 257 | server->rcv.creq = req; |
| 283 | server->timeout_last = server->m.time_out; | 258 | server->timeout_last = server->m.time_out; |
| 284 | server->timeout_retries = server->m.retry_count; | 259 | server->timeout_retries = server->m.retry_count; |
| @@ -292,24 +267,23 @@ static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request | |||
| 292 | 267 | ||
| 293 | static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) | 268 | static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) |
| 294 | { | 269 | { |
| 295 | size_t signlen; | 270 | size_t signlen, len = req->tx_iov[1].iov_len; |
| 296 | struct ncp_request_header* h; | 271 | struct ncp_request_header *h = req->tx_iov[1].iov_base; |
| 297 | 272 | ||
| 298 | req->tx_ciov = req->tx_iov; | ||
| 299 | h = req->tx_iov[1].iov_base; | ||
| 300 | ncp_init_header(server, req, h); | 273 | ncp_init_header(server, req, h); |
| 301 | signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, | 274 | signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, |
| 302 | req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, | 275 | len - sizeof(struct ncp_request_header) + 1, |
| 303 | cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16; | 276 | cpu_to_be32(len + 24), req->sign + 4) + 16; |
| 304 | 277 | ||
| 305 | req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); | 278 | req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); |
| 306 | req->sign[1] = htonl(req->tx_totallen + signlen); | 279 | req->sign[1] = htonl(len + signlen); |
| 307 | req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); | 280 | req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); |
| 308 | req->sign[3] = htonl(req->datalen + 8); | 281 | req->sign[3] = htonl(req->datalen + 8); |
| 282 | /* NCP over TCP prepends signature */ | ||
| 309 | req->tx_iov[0].iov_base = req->sign; | 283 | req->tx_iov[0].iov_base = req->sign; |
| 310 | req->tx_iov[0].iov_len = signlen; | 284 | req->tx_iov[0].iov_len = signlen; |
| 311 | req->tx_iovlen += 1; | 285 | iov_iter_kvec(&req->from, WRITE | ITER_KVEC, |
| 312 | req->tx_totallen += signlen; | 286 | req->tx_iov, 2, len + signlen); |
| 313 | 287 | ||
| 314 | server->tx.creq = req; | 288 | server->tx.creq = req; |
| 315 | __ncptcp_try_send(server); | 289 | __ncptcp_try_send(server); |
| @@ -364,18 +338,17 @@ static void __ncp_next_request(struct ncp_server *server) | |||
| 364 | static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) | 338 | static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) |
| 365 | { | 339 | { |
| 366 | if (server->info_sock) { | 340 | if (server->info_sock) { |
| 367 | struct kvec iov[2]; | 341 | struct msghdr msg = { .msg_flags = MSG_NOSIGNAL }; |
| 368 | __be32 hdr[2]; | 342 | __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)}; |
| 369 | 343 | struct kvec iov[2] = { | |
| 370 | hdr[0] = cpu_to_be32(len + 8); | 344 | {.iov_base = hdr, .iov_len = 8}, |
| 371 | hdr[1] = cpu_to_be32(id); | 345 | {.iov_base = (void *)data, .iov_len = len}, |
| 372 | 346 | }; | |
| 373 | iov[0].iov_base = hdr; | 347 | |
| 374 | iov[0].iov_len = 8; | 348 | iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE, |
| 375 | iov[1].iov_base = (void *) data; | 349 | iov, 2, len + 8); |
| 376 | iov[1].iov_len = len; | ||
| 377 | 350 | ||
| 378 | do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL); | 351 | sock_sendmsg(server->info_sock, &msg); |
| 379 | } | 352 | } |
| 380 | } | 353 | } |
| 381 | 354 | ||
| @@ -711,8 +684,6 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size, | |||
| 711 | req->datalen = max_reply_size; | 684 | req->datalen = max_reply_size; |
| 712 | req->tx_iov[1].iov_base = server->packet; | 685 | req->tx_iov[1].iov_base = server->packet; |
| 713 | req->tx_iov[1].iov_len = size; | 686 | req->tx_iov[1].iov_len = size; |
| 714 | req->tx_iovlen = 1; | ||
| 715 | req->tx_totallen = size; | ||
| 716 | req->tx_type = *(u_int16_t*)server->packet; | 687 | req->tx_type = *(u_int16_t*)server->packet; |
| 717 | 688 | ||
| 718 | result = ncp_add_request(server, req); | 689 | result = ncp_add_request(server, req); |
