xref: /qemu/nbd/common.c (revision 7a4e543d)
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 "qemu/osdep.h"
20 #include "nbd-internal.h"
21 
22 ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
23 {
24     size_t offset = 0;
25     int err;
26 
27     if (qemu_in_coroutine()) {
28         if (do_read) {
29             return qemu_co_recv(fd, buffer, size);
30         } else {
31             return qemu_co_send(fd, buffer, size);
32         }
33     }
34 
35     while (offset < size) {
36         ssize_t len;
37 
38         if (do_read) {
39             len = qemu_recv(fd, buffer + offset, size - offset, 0);
40         } else {
41             len = send(fd, buffer + offset, size - offset, 0);
42         }
43 
44         if (len < 0) {
45             err = socket_error();
46 
47             /* recoverable error */
48             if (err == EINTR || (offset > 0 && (err == EAGAIN || err == EWOULDBLOCK))) {
49                 continue;
50             }
51 
52             /* unrecoverable error */
53             return -err;
54         }
55 
56         /* eof */
57         if (len == 0) {
58             break;
59         }
60 
61         offset += len;
62     }
63 
64     return offset;
65 }
66