| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/fs/9p/trans_fd.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 7 | 8 | * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> |
|---|
| 8 | 9 | * Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com> |
|---|
| 9 | 10 | * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | | - * it under the terms of the GNU General Public License version 2 |
|---|
| 13 | | - * as published by the Free Software Foundation. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | | - * |
|---|
| 20 | | - * You should have received a copy of the GNU General Public License |
|---|
| 21 | | - * along with this program; if not, write to: |
|---|
| 22 | | - * Free Software Foundation |
|---|
| 23 | | - * 51 Franklin Street, Fifth Floor |
|---|
| 24 | | - * Boston, MA 02111-1301 USA |
|---|
| 25 | | - * |
|---|
| 26 | 11 | */ |
|---|
| 27 | 12 | |
|---|
| 28 | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 133 | 118 | struct list_head unsent_req_list; |
|---|
| 134 | 119 | struct p9_req_t *rreq; |
|---|
| 135 | 120 | struct p9_req_t *wreq; |
|---|
| 136 | | - char tmp_buf[7]; |
|---|
| 121 | + char tmp_buf[P9_HDRSZ]; |
|---|
| 137 | 122 | struct p9_fcall rc; |
|---|
| 138 | 123 | int wpos; |
|---|
| 139 | 124 | int wsize; |
|---|
| .. | .. |
|---|
| 215 | 200 | |
|---|
| 216 | 201 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { |
|---|
| 217 | 202 | list_move(&req->req_list, &cancel_list); |
|---|
| 203 | + req->status = REQ_STATUS_ERROR; |
|---|
| 218 | 204 | } |
|---|
| 219 | 205 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { |
|---|
| 220 | 206 | list_move(&req->req_list, &cancel_list); |
|---|
| 207 | + req->status = REQ_STATUS_ERROR; |
|---|
| 221 | 208 | } |
|---|
| 209 | + |
|---|
| 210 | + spin_unlock(&m->client->lock); |
|---|
| 222 | 211 | |
|---|
| 223 | 212 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { |
|---|
| 224 | 213 | p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); |
|---|
| .. | .. |
|---|
| 227 | 216 | req->t_err = err; |
|---|
| 228 | 217 | p9_client_cb(m->client, req, REQ_STATUS_ERROR); |
|---|
| 229 | 218 | } |
|---|
| 230 | | - spin_unlock(&m->client->lock); |
|---|
| 231 | 219 | } |
|---|
| 232 | 220 | |
|---|
| 233 | 221 | static __poll_t |
|---|
| .. | .. |
|---|
| 303 | 291 | if (!m->rc.sdata) { |
|---|
| 304 | 292 | m->rc.sdata = m->tmp_buf; |
|---|
| 305 | 293 | m->rc.offset = 0; |
|---|
| 306 | | - m->rc.capacity = 7; /* start by reading header */ |
|---|
| 294 | + m->rc.capacity = P9_HDRSZ; /* start by reading header */ |
|---|
| 307 | 295 | } |
|---|
| 308 | 296 | |
|---|
| 309 | 297 | clear_bit(Rpending, &m->wsched); |
|---|
| .. | .. |
|---|
| 326 | 314 | p9_debug(P9_DEBUG_TRANS, "got new header\n"); |
|---|
| 327 | 315 | |
|---|
| 328 | 316 | /* Header size */ |
|---|
| 329 | | - m->rc.size = 7; |
|---|
| 317 | + m->rc.size = P9_HDRSZ; |
|---|
| 330 | 318 | err = p9_parse_header(&m->rc, &m->rc.size, NULL, NULL, 0); |
|---|
| 331 | 319 | if (err) { |
|---|
| 332 | 320 | p9_debug(P9_DEBUG_ERROR, |
|---|
| .. | .. |
|---|
| 835 | 823 | goto out_free_ts; |
|---|
| 836 | 824 | if (!(ts->rd->f_mode & FMODE_READ)) |
|---|
| 837 | 825 | goto out_put_rd; |
|---|
| 826 | + /* prevent workers from hanging on IO when fd is a pipe */ |
|---|
| 827 | + ts->rd->f_flags |= O_NONBLOCK; |
|---|
| 838 | 828 | ts->wr = fget(wfd); |
|---|
| 839 | 829 | if (!ts->wr) |
|---|
| 840 | 830 | goto out_put_rd; |
|---|
| 841 | 831 | if (!(ts->wr->f_mode & FMODE_WRITE)) |
|---|
| 842 | 832 | goto out_put_wr; |
|---|
| 833 | + ts->wr->f_flags |= O_NONBLOCK; |
|---|
| 843 | 834 | |
|---|
| 844 | 835 | client->trans = ts; |
|---|
| 845 | 836 | client->status = Connected; |
|---|
| .. | .. |
|---|
| 861 | 852 | struct file *file; |
|---|
| 862 | 853 | |
|---|
| 863 | 854 | p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); |
|---|
| 864 | | - if (!p) |
|---|
| 855 | + if (!p) { |
|---|
| 856 | + sock_release(csocket); |
|---|
| 865 | 857 | return -ENOMEM; |
|---|
| 858 | + } |
|---|
| 866 | 859 | |
|---|
| 867 | 860 | csocket->sk->sk_allocation = GFP_NOIO; |
|---|
| 868 | 861 | file = sock_alloc_file(csocket, 0, NULL); |
|---|
| .. | .. |
|---|
| 965 | 958 | |
|---|
| 966 | 959 | memset(&cl, 0, sizeof(cl)); |
|---|
| 967 | 960 | cl.sin_family = AF_INET; |
|---|
| 968 | | - cl.sin_addr.s_addr = INADDR_ANY; |
|---|
| 961 | + cl.sin_addr.s_addr = htonl(INADDR_ANY); |
|---|
| 969 | 962 | for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) { |
|---|
| 970 | 963 | cl.sin_port = htons((ushort)port); |
|---|
| 971 | 964 | err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl)); |
|---|