/[hurd]/hurd/libstore/nbd.c
ViewVC logotype

Diff of /hurd/libstore/nbd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.12 by roland, Sun Dec 30 03:09:40 2001 UTC revision 1.13 by roland, Mon Dec 31 07:24:30 2001 UTC
# Line 165  nbd_write (struct store *store, Line 165  nbd_write (struct store *store,
165    
166  static error_t  static error_t
167  nbd_read (struct store *store,  nbd_read (struct store *store,
168            store_offset_t addr, size_t index, size_t amount, void **buf,            store_offset_t addr, size_t index, size_t amount,
169            size_t *len)            void **buf, size_t *len)
170  {  {
171    struct nbd_request req =    struct nbd_request req =
172    {    {
# Line 174  nbd_read (struct store *store, Line 174  nbd_read (struct store *store,
174      type: htonl (0),            /* READ */      type: htonl (0),            /* READ */
175    };    };
176    error_t err;    error_t err;
177    mach_msg_type_number_t cc;    size_t ofs, chunk;
178      char *databuf, *piecebuf;
179    if (amount > NBD_IO_MAX)    size_t databuflen, piecelen;
180      amount = NBD_IO_MAX;  
181      /* Send a request for the largest possible piece of remaining data and
182         read the first piece of its reply into PIECEBUF, PIECELEN.  The amount
183         requested can be found in CHUNK.  */
184      inline error_t request_chunk (char **buf, size_t *len)
185        {
186          mach_msg_type_number_t cc;
187    
188          chunk = (amount - ofs) < NBD_IO_MAX ? (amount - ofs) : NBD_IO_MAX;
189    
190          req.from = htonll (addr);
191          req.len = htonl (chunk);
192    
193          /* Advance ADDR immediately, so it always points past what we've
194             already requested.  */
195          addr += chunk;
196    
197          return (io_write (store->port, (char *) &req, sizeof req, -1, &cc) ?
198                  : cc != sizeof req ? EIO
199                  : read_reply (store, req.handle) ?
200                  : io_read (store->port, buf, len, (off_t) -1, chunk));
201        }
202    
203    addr <<= store->log2_block_size;    addr <<= store->log2_block_size;
204    
205    req.from = htonll (addr);    /* Read the first piece, which can go directly into the caller's buffer.  */
206    req.len = htonl (amount);    databuf = *buf;
207      databuflen = *len;
208    err = io_write (store->port, (char *) &req, sizeof req, -1, &cc);    err = request_chunk (&databuf, &piecelen);
209    if (err)    if (err)
210      return err;      return err;
211    if (cc != sizeof req)    if (databuflen >= amount)
212      return EIO;      {
213          /* That got it all.  We're done.  */
214          *buf = databuf;
215          *len = piecelen;
216          return 0;
217        }
218    
219      /* We haven't read the entire amount yet.  */
220      ofs = 0;
221      do
222        {
223          /* Account for what we just read.  */
224          ofs += piecelen;
225          chunk -= piecelen;
226          if (ofs == amount)
227            {
228              /* That got it all.  We're done.  */
229              *buf = databuf;
230              *len = ofs;
231              return 0;
232            }
233    
234          /* Now we'll read another piece of the data, hopefully
235             into the latter part of the existing buffer.  */
236          piecebuf = databuf + ofs;
237          piecelen = databuflen - ofs;
238    
239          if (chunk > 0)
240            /* We haven't finishing reading the last chunk we requested.  */
241            err = io_read (store->port, &piecebuf, &piecelen,
242                           (off_t) -1, chunk);
243          else
244            /* Request the next chunk from the server.  */
245            err = request_chunk (&piecebuf, &piecelen);
246    
247          if (!err && piecebuf != databuf + ofs)
248            {
249              /* Now we have two discontiguous pieces of the buffer.  */
250              size_t newbuflen = round_page (databuflen + piecelen);
251              char *newbuf = mmap (0, newbuflen,
252                                   PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
253              if (newbuf == MAP_FAILED)
254                {
255                  err = errno;
256                  break;
257                }
258              memcpy (newbuf, databuf, ofs);
259              memcpy (newbuf + ofs, piecebuf, piecelen);
260              if (databuf != *buf)
261                munmap (databuf, databuflen);
262              databuf = newbuf;
263              databuflen = newbuflen;
264            }
265        } while (! err);
266    
267    err = read_reply (store, req.handle);    if (databuf != *buf)
268    if (err == 0)      munmap (databuf, databuflen);
     err = io_read (store->port, (char **) buf, len, (off_t) -1, amount);  
269    return err;    return err;
270  }  }
271    

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26