xref: /qemu/nbd/common.c (revision cc75a50c)
1 /*
2  *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3  *
4  *  Network Block Device Common Code
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; under version 2 of the License.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "nbd-internal.h"
20 
21 ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
22 {
23     size_t offset = 0;
24     int err;
25 
26     if (qemu_in_coroutine()) {
27         if (do_read) {
28             return qemu_co_recv(fd, buffer, size);
29         } else {
30             return qemu_co_send(fd, buffer, size);
31         }
32     }
33 
34     while (offset < size) {
35         ssize_t len;
36 
37         if (do_read) {
38             len = qemu_recv(fd, buffer + offset, size - offset, 0);
39         } else {
40             len = send(fd, buffer + offset, size - offset, 0);
41         }
42 
43         if (len < 0) {
44             err = socket_error();
45 
46             /* recoverable error */
47             if (err == EINTR || (offset > 0 && (err == EAGAIN || err == EWOULDBLOCK))) {
48                 continue;
49             }
50 
51             /* unrecoverable error */
52             return -err;
53         }
54 
55         /* eof */
56         if (len == 0) {
57             break;
58         }
59 
60         offset += len;
61     }
62 
63     return offset;
64 }
65