Whamcloud - gitweb
import libsysio for b_newsysio
[fs/lustre-release.git] / libsysio / src / rw.c
1 /*
2  *    This Cplant(TM) source code is the property of Sandia National
3  *    Laboratories.
4  *
5  *    This Cplant(TM) source code is copyrighted by Sandia National
6  *    Laboratories.
7  *
8  *    The redistribution of this Cplant(TM) source code is subject to the
9  *    terms of the GNU Lesser General Public License
10  *    (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
11  *
12  *    Cplant(TM) Copyright 1998-2004 Sandia Corporation. 
13  *    Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
14  *    license for use of this work by or on behalf of the US Government.
15  *    Export of this program may require a license from the United States
16  *    Government.
17  */
18
19 /*
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  * 
25  * This library is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  * 
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33  *
34  * Questions or comments about this library should be sent to:
35  *
36  * Lee Ward
37  * Sandia National Laboratories, New Mexico
38  * P.O. Box 5800
39  * Albuquerque, NM 87185-1110
40  *
41  * lee@sandia.gov
42  */
43
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <errno.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <fcntl.h>
50 #include <sys/uio.h>
51 #include <sys/queue.h>
52
53 #include "xtio.h"
54 #include "sysio.h"
55 #include "file.h"
56 #include "inode.h"
57
58 #include "sysio-symbols.h"
59
60 #define IIOXOP_READ(ino)        (ino)->i_ops.inop_read, 0
61 #define IIOXOP_WRITE(ino)       (ino)->i_ops.inop_write, 1
62
63 /*
64  * Decoding the interface routine names:
65  *
66  * Much of this carries legacy from the POSIX world and the Intel ASCI
67  * Red programming environment. Routine names are composed of prefix,
68  * basic POSIX names, and postfix. The basic POSIX names are read and write.
69  * Prefixes, left-to-right:
70  *
71  *      - 'i' -- asynchronous operation (from ASCI Red)
72  *      - 'p' -- positional (POSIX)
73  * Posfixes, only one:
74  *      - 'v' -- vectored (POSIX)
75  *      - 'x' -- extent-based (new for Red Storm)
76  *
77  * All valid combinations are available and symmetric.
78  */
79
80 /*
81  * Post op using iovec with regions specified by the passed extent vector.
82  *
83  * NOTE: There are enough parameters that we should really consider
84  * passing them in a structure.
85  */
86 static int
87 _sysio_iiox(int (*f)(struct inode *, struct ioctx *),
88             int wr,
89             struct file *fil,
90             const struct iovec *iov,
91             size_t iov_count,
92             void (*iov_free)(struct ioctx *),
93             const struct intnl_xtvec *xtv,
94             size_t xtv_count,
95             void (*xtv_free)(struct ioctx *),
96             void (*completio)(struct ioctx *, void *),
97             struct ioctx **ioctxp)
98 {
99         struct inode *ino;
100         ssize_t cc;
101         struct ioctx *ioctx;
102         int     err;
103         struct ioctx_callback *cb;
104
105         /*
106          * Check that it was opened with flags supporting the operation.
107          */
108         if (!(wr
109                 ? (fil->f_flags & (O_RDWR | O_WRONLY))
110                 : !(fil->f_flags & O_WRONLY)))
111                 return -EBADF;
112
113         ino = fil->f_ino;
114         if (!ino) {
115                 /*
116                  * Huh? It's dead.
117                  */
118                 return -EBADF;
119         }
120         cc =
121             _sysio_validx(xtv, xtv_count,
122                           iov, iov_count,
123 #if _LARGEFILE64_SOURCE && defined(O_LARGEFILE)
124                           (fil->f_flags & O_LARGEFILE) == 0
125                             ? LONG_MAX
126                             :
127 #endif
128                           _SYSIO_OFF_T_MAX);
129         if (cc < 0)
130                 return cc;
131         ioctx = _sysio_ioctx_new(ino, wr, iov, iov_count, xtv, xtv_count);
132         if (!ioctx)
133                 return -ENOMEM;
134         if ((iov_free &&
135              (err = _sysio_ioctx_cb(ioctx,
136                                     (void (*)(struct ioctx *,
137                                               void *))iov_free,
138                                     NULL))) ||
139             (xtv_free &&
140              (err = _sysio_ioctx_cb(ioctx,
141                                     (void (*)(struct ioctx *,
142                                               void *))xtv_free,
143                                     NULL))) ||
144             (completio &&
145              (err = _sysio_ioctx_cb(ioctx,
146                                     (void (*)(struct ioctx *,
147                                               void *))completio,
148                                     fil))) ||
149             (err = (*f)(ino, ioctx))) {
150                 /*
151                  * Release the callback queue. Don't want it run after all.
152                  */
153                 while ((cb = ioctx->ioctx_cbq.tqh_first)) {
154                         TAILQ_REMOVE(&ioctx->ioctx_cbq,
155                                      cb,
156                                      iocb_next);
157                         _sysio_ioctx_cb_free(cb);
158                 }
159                 _sysio_ioctx_complete(ioctx);
160                 return err;
161         }
162         *ioctxp = ioctx;
163         return 0;
164 }
165
166 /*
167  * Sum iovec entries, returning total found or error if range of ssize_t would
168  * be exceeded.
169  */
170 static ssize_t
171 _sysio_sum_iovec(const struct iovec *iov, int count)
172 {
173         ssize_t tmp, cc;
174
175         if (count <= 0)
176                 return -EINVAL;
177
178         cc = 0;
179         while (count--) {
180                 tmp = cc;
181                 cc += iov->iov_len;
182                 if (tmp && iov->iov_len && cc <= tmp)
183                         return -EINVAL;
184                 iov++;
185         }
186         return cc;
187 }
188
189 /*
190  * Asynch IO from/to iovec from/to current file offset.
191  */
192 static int
193 _sysio_iiov(int (*f)(struct inode *, struct ioctx *),
194             int wr,
195             struct file *fil,
196             const struct iovec *iov,
197             int count,
198             void (*iov_free)(struct ioctx *),
199             struct intnl_xtvec *xtv,
200             void (*xtv_free)(struct ioctx *),
201             struct ioctx **ioctxp)
202 {
203         ssize_t cc;
204         _SYSIO_OFF_T off;
205         int     err;
206
207         cc = _sysio_sum_iovec(iov, count);
208         if (cc < 0)
209                 return (int )cc;
210         xtv->xtv_off = fil->f_pos;
211         xtv->xtv_len = cc;
212         off = xtv->xtv_off + xtv->xtv_len;
213         if (xtv->xtv_off && off <= xtv->xtv_off) {
214                 /*
215                  * Ouch! The IO vector specifies more bytes than
216                  * are addressable. Trim the region to limit how
217                  * much of the IO vector is finally transferred.
218                  */
219                 xtv->xtv_len = _SYSIO_OFF_T_MAX - xtv->xtv_off;
220         }
221         err =
222             _sysio_iiox(f,
223                         wr,
224                         fil,
225                         iov, count, iov_free,
226                         xtv, 1, xtv_free,
227                         (void (*)(struct ioctx *, void *))_sysio_fcompletio,
228                         ioctxp);
229         if (err)
230                 return err;
231         return 0;
232 }
233
234 static void
235 free_xtv(struct ioctx *ioctx)
236 {
237
238         free((struct iovec *)ioctx->ioctx_xtv);
239         ioctx->ioctx_iov = NULL;
240 }
241
242 ioid_t
243 SYSIO_INTERFACE_NAME(ireadv)(int fd, const struct iovec *iov, int count)
244 {
245         struct file *fil;
246         struct intnl_xtvec *xtv;
247         struct ioctx *ioctx;
248         int     err;
249         SYSIO_INTERFACE_DISPLAY_BLOCK;
250
251         SYSIO_INTERFACE_ENTER;
252         fil = _sysio_fd_find(fd);
253         if (!fil)
254                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
255
256         xtv = malloc(sizeof(struct intnl_xtvec));
257         if (!xtv)
258                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
259
260         err =
261             _sysio_iiov(IIOXOP_READ(fil->f_ino),
262                         fil,
263                         iov, count, NULL,
264                         xtv, free_xtv,
265                         &ioctx);
266         if (err) {
267                 free(xtv);
268                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
269         }
270         SYSIO_INTERFACE_RETURN(ioctx, 0);
271 }
272
273 ssize_t
274 SYSIO_INTERFACE_NAME(readv)(int fd, const struct iovec *iov, int count)
275 {
276         struct file *fil;
277         struct intnl_xtvec xtvector;
278         struct ioctx *ioctx;
279         int     err;
280         ssize_t cc;
281         SYSIO_INTERFACE_DISPLAY_BLOCK;
282
283         SYSIO_INTERFACE_ENTER;
284         fil = _sysio_fd_find(fd);
285         if (!fil)
286                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
287
288         err =
289             _sysio_iiov(IIOXOP_READ(fil->f_ino),
290                         fil,
291                         iov, count, NULL,
292                         &xtvector, NULL,
293                         &ioctx);
294         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
295                 err = (int )cc;
296
297         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
298 }
299
300 #if defined(__GLIBC__)
301 #undef __readv
302 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(readv), 
303                      PREPEND(__, SYSIO_INTERFACE_NAME(readv)))
304 #undef __libc_readv
305 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(readv),
306                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_readv)))
307 #endif
308
309 static void
310 free_iov(struct ioctx *ioctx)
311 {
312
313         free((struct iovec *)ioctx->ioctx_iov);
314         ioctx->ioctx_iov = NULL;
315 }
316
317 ioid_t
318 SYSIO_INTERFACE_NAME(iread)(int fd, void *buf, size_t count)
319 {
320         struct iovec *iov;
321         struct file *fil;
322         struct intnl_xtvec *xtv;
323         struct ioctx *ioctx;
324         int     err;
325         SYSIO_INTERFACE_DISPLAY_BLOCK;
326
327         SYSIO_INTERFACE_ENTER;
328         fil = _sysio_fd_find(fd);
329         if (!fil)
330                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
331
332         iov = malloc(sizeof(struct iovec));
333         if (!iov)
334                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
335
336         iov->iov_base = buf;
337         iov->iov_len = count;
338         xtv = malloc(sizeof(struct intnl_xtvec));
339         if (!xtv) {
340                 free(iov);
341                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
342         }
343         err =
344             _sysio_iiov(IIOXOP_READ(fil->f_ino),
345                         fil,
346                         iov, 1, free_iov,
347                         xtv, free_xtv,
348                         &ioctx);
349         if (err) {
350                 free(xtv);
351                 free(iov);
352                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
353         }
354         SYSIO_INTERFACE_RETURN(ioctx, 0);
355 }
356
357 ssize_t
358 SYSIO_INTERFACE_NAME(read)(int fd, void *buf, size_t count)
359 {
360         struct file *fil;
361         struct iovec iovector;
362         struct intnl_xtvec xtvector;
363         int     err;
364         struct ioctx *ioctx;
365         ssize_t cc;
366         SYSIO_INTERFACE_DISPLAY_BLOCK;
367
368         SYSIO_INTERFACE_ENTER;
369         fil = _sysio_fd_find(fd);
370         if (!fil)
371                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
372
373         iovector.iov_base = buf;
374         iovector.iov_len = count;
375         err =
376             _sysio_iiov(IIOXOP_READ(fil->f_ino),
377                         fil,
378                         &iovector, 1, NULL,
379                         &xtvector, NULL,
380                         &ioctx);
381         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
382                 err = (int )cc;
383         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
384 }
385
386 #ifdef __GLIBC__
387 #undef __read
388 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(read),
389                      PREPEND(__, SYSIO_INTERFACE_NAME(read)))
390 #undef __libc_read
391 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(read),
392                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_read)))
393 #endif
394
395 /*
396  * Asynch IO between iovec and data at the given offset.
397  */
398 static int
399 _sysio_ipiov(int (*f)(struct inode *, struct ioctx *),
400              int wr,
401              struct file *fil,
402              const struct iovec *iov,
403              int count,
404              void (*iov_free)(struct ioctx *),
405              _SYSIO_OFF_T off,
406              struct intnl_xtvec *xtv,
407              void (*xtv_free)(struct ioctx *),
408              struct ioctx **ioctxp)
409 {
410         ssize_t cc;
411         int     err;
412
413         SYSIO_ENTER;
414         cc = _sysio_sum_iovec(iov, count);
415         if (cc < 0) {
416                 SYSIO_LEAVE;
417                 return (int )cc;
418         }
419         xtv->xtv_off = off,
420         xtv->xtv_len = cc;
421         err =
422             _sysio_iiox(f,
423                         wr,
424                         fil,
425                         iov, count, iov_free,
426                         xtv, 1, xtv_free,
427                         NULL,
428                         ioctxp);
429         SYSIO_LEAVE;
430         if (err)
431                 return err;
432         return 0;
433 }
434
435 static ioid_t
436 PREPEND(_, SYSIO_INTERFACE_NAME(ipreadv))(int fd, 
437                                           const struct iovec *iov, 
438                                           size_t count, 
439                                           _SYSIO_OFF_T offset)
440 {
441         struct file *fil;
442         struct intnl_xtvec *xtv;
443         struct ioctx *ioctx;
444         int     err;
445         SYSIO_INTERFACE_DISPLAY_BLOCK;
446
447         SYSIO_INTERFACE_ENTER;
448         fil = _sysio_fd_find(fd);
449         if (!fil)
450                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
451
452         xtv = malloc(sizeof(struct intnl_xtvec));
453         if (!xtv)
454                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
455
456         err =
457             _sysio_ipiov(IIOXOP_READ(fil->f_ino),
458                          fil,
459                          iov, count, NULL,
460                          offset,
461                          xtv, free_xtv,
462                          &ioctx);
463         if (err) {
464                 free(xtv);
465                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
466         }
467         SYSIO_INTERFACE_RETURN(ioctx, 0);
468 }
469
470 #if _LARGEFILE64_SOURCE
471 #undef ipread64v
472 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipreadv)),
473                      SYSIO_INTERFACE_NAME(ipread64v))
474 #endif
475
476 ioid_t
477 SYSIO_INTERFACE_NAME(ipreadv)(int fd, 
478                               const struct iovec *iov, 
479                               size_t count, 
480                               off_t offset)
481 {
482
483         return PREPEND(_, SYSIO_INTERFACE_NAME(ipreadv))(fd, 
484                                                          iov, 
485                                                          count, 
486                                                          offset);
487 }
488
489 static ssize_t
490 PREPEND(_, SYSIO_INTERFACE_NAME(preadv))(int fd, 
491                                          const struct iovec *iov, 
492                                          size_t count, 
493                                          _SYSIO_OFF_T offset)
494 {
495         struct file *fil;
496         struct intnl_xtvec xtvector;
497         struct ioctx *ioctx;
498         int     err;
499         ssize_t cc;
500         SYSIO_INTERFACE_DISPLAY_BLOCK;
501
502         SYSIO_INTERFACE_ENTER;
503         fil = _sysio_fd_find(fd);
504         if (!fil)
505                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
506
507         err =
508             _sysio_ipiov(IIOXOP_READ(fil->f_ino),
509                          fil,
510                          iov, count, NULL,
511                          offset,
512                          &xtvector, NULL,
513                          &ioctx);
514         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
515                 err = (int )cc;
516
517         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
518 }
519
520 #if _LARGEFILE64_SOURCE
521 #undef pread64v
522 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(preadv)), 
523                      SYSIO_INTERFACE_NAME(pread64v))
524 #endif
525
526 ssize_t
527 SYSIO_INTERFACE_NAME(preadv)(int fd, 
528                              const struct iovec *iov, 
529                              size_t count, 
530                              off_t offset)
531 {
532
533         return PREPEND(_, SYSIO_INTERFACE_NAME(preadv))(fd, 
534                                                         iov, 
535                                                         count, 
536                                                         offset);
537 }
538
539 static ioid_t
540 PREPEND(_, SYSIO_INTERFACE_NAME(ipread))(int fd, 
541                                          void *buf, 
542                                          size_t count, 
543                                          _SYSIO_OFF_T offset)
544 {
545         struct file *fil;
546         struct intnl_xtvec *xtv;
547         struct iovec *iov;
548         struct ioctx *ioctx;
549         int     err;
550         SYSIO_INTERFACE_DISPLAY_BLOCK;
551
552         SYSIO_INTERFACE_ENTER;
553         fil = _sysio_fd_find(fd);
554         if (!fil)
555                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
556
557         xtv = malloc(sizeof(struct intnl_xtvec));
558         iov = malloc(sizeof(struct iovec));
559         if (!(xtv && iov)) {
560                 err = -ENOMEM;
561                 goto error;
562         }
563         xtv->xtv_off = offset;
564         iov->iov_base = buf;
565         xtv->xtv_len = iov->iov_len = count;
566         err =
567             _sysio_ipiov(IIOXOP_READ(fil->f_ino),
568                          fil,
569                          iov, 1, free_iov,
570                          offset,
571                          xtv, free_xtv,
572                          &ioctx);
573 error:
574         if (err) {
575                 if (iov)
576                         free(iov);
577                 if (xtv)
578                         free(xtv);
579                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
580         }
581         SYSIO_INTERFACE_RETURN(ioctx, 0);
582 }
583
584 #if _LARGEFILE64_SOURCE
585 #undef ipread64
586 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipread)),
587                      SYSIO_INTERFACE_NAME(ipread64))
588 #endif
589
590 ioid_t
591 SYSIO_INTERFACE_NAME(ipread)(int fd, 
592                              void *buf, 
593                              size_t count, 
594                              off_t offset)
595 {
596
597         return PREPEND(_, SYSIO_INTERFACE_NAME(ipread))(fd, 
598                                                         buf, 
599                                                         count, 
600                                                         offset);
601 }
602
603 ssize_t
604 PREPEND(_, SYSIO_INTERFACE_NAME(pread))(int fd, 
605                                         void *buf, 
606                                         size_t count, 
607                                         _SYSIO_OFF_T offset)
608 {
609         struct file *fil;
610         struct intnl_xtvec xtvec;
611         struct iovec iovec;
612         struct ioctx *ioctx;
613         int     err;
614         ssize_t cc;
615         SYSIO_INTERFACE_DISPLAY_BLOCK;
616
617         SYSIO_INTERFACE_ENTER;
618         fil = _sysio_fd_find(fd);
619         if (!fil)
620                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
621
622         xtvec.xtv_off = offset;
623         iovec.iov_base = buf;
624         xtvec.xtv_len = iovec.iov_len = count;
625         err =
626             _sysio_ipiov(IIOXOP_READ(fil->f_ino),
627                          fil,
628                          &iovec, 1, NULL,
629                          offset,
630                          &xtvec, NULL,
631                          &ioctx);
632         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
633                 err = (int )cc;
634
635         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
636 }
637
638 #if _LARGEFILE64_SOURCE
639 #undef pread64
640 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pread)),
641                      SYSIO_INTERFACE_NAME(pread64))
642 #if __GLIBC__
643 #undef __pread64
644 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pread)), 
645                      PREPEND(__, SYSIO_INTERFACE_NAME(pread64)))
646 #undef __libc_pread64
647 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pread)),
648                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pread64)))
649 #endif
650 #endif
651
652 ssize_t
653 SYSIO_INTERFACE_NAME(pread)(int fd, void *buf, size_t count, off_t offset)
654 {
655
656         return PREPEND(_, SYSIO_INTERFACE_NAME(pread))(fd, 
657                                                        buf, 
658                                                        count, 
659                                                        offset);
660 }
661
662 #if __GLIBC__
663 #undef __pread
664 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(pread), 
665                      PREPEND(__, SYSIO_INTERFACE_NAME(pread)))
666 #undef __libc_pread
667 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(pread),
668                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pread)))
669 #endif
670
671 static ioid_t
672 PREPEND(_, SYSIO_INTERFACE_NAME(ireadx))(int fd,
673                                          const struct iovec *iov, 
674                                          size_t iov_count, 
675                                          const struct intnl_xtvec *xtv, 
676                                          size_t xtv_count)
677 {
678         struct file *fil;
679         int     err;
680         struct ioctx *ioctx;
681         SYSIO_INTERFACE_DISPLAY_BLOCK;
682
683         SYSIO_INTERFACE_ENTER;
684         fil = _sysio_fd_find(fd);
685         if (!(fil && xtv_count))
686                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
687
688         err =
689             _sysio_iiox(IIOXOP_READ(fil->f_ino),
690                         fil,
691                         iov, iov_count, NULL,
692                         xtv, xtv_count, NULL,
693                         NULL,
694                         &ioctx);
695
696         SYSIO_INTERFACE_RETURN(err ? IOID_FAIL : ioctx, err);
697 }
698
699 #if _LARGEFILE64_SOURCE
700 #undef iread64x
701 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ireadx)),
702                      SYSIO_INTERFACE_NAME(iread64x))
703 #endif
704
705 #if _LARGEFILE64_SOURCE
706 ioid_t
707 SYSIO_INTERFACE_NAME(ireadx)(int fd,
708                              const struct iovec *iov, size_t iov_count,
709                              const struct xtvec *xtv, size_t xtv_count)
710 {
711         struct file *fil;
712         struct intnl_xtvec *ixtv, *ixtvent;
713         size_t  count;
714         int     err;
715         struct ioctx *ioctx;
716         SYSIO_INTERFACE_DISPLAY_BLOCK;
717
718         SYSIO_INTERFACE_ENTER;
719         fil = _sysio_fd_find(fd);
720         if (!(fil && xtv_count))
721                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
722
723         ixtv = ixtvent = malloc(xtv_count * sizeof(struct intnl_xtvec));
724         if (!ixtv)
725                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
726
727         count = xtv_count;
728         while (count--) {
729                 ixtvent->xtv_off = xtv->xtv_off;
730                 ixtvent->xtv_len = xtv->xtv_len;
731                 ixtvent++;
732                 xtv++;
733         }
734
735         err =
736             _sysio_iiox(IIOXOP_READ(fil->f_ino),
737                         fil,
738                         iov, iov_count, NULL,
739                         ixtv, xtv_count, free_xtv,
740                         NULL,
741                         &ioctx);
742         if (err) {
743                 free(ixtv);
744                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
745         }
746         SYSIO_INTERFACE_RETURN(ioctx, 0);
747 }
748 #else
749 #undef ireadx
750 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ireadx)),
751                      SYSIO_INTERFACE_NAME(ireadx))
752 #endif
753
754 ssize_t
755 SYSIO_INTERFACE_NAME(readx)(int fd,
756                             const struct iovec *iov, size_t iov_count,
757                             const struct xtvec *xtv, size_t xtv_count)
758 {
759         ioid_t  ioid;
760
761         if ((ioid = SYSIO_INTERFACE_NAME(ireadx)(fd, 
762                                                  iov, 
763                                                  iov_count, 
764                                                  xtv, 
765                                                  xtv_count)) == IOID_FAIL)
766                 return -1;
767         return iowait(ioid);
768 }
769
770 #if _LARGEFILE64_SOURCE
771 #undef iread64x
772 ssize_t
773 SYSIO_INTERFACE_NAME(read64x)(int fd,
774                               const struct iovec *iov, size_t iov_count,
775                               const struct xtvec64 *xtv, size_t xtv_count)
776 {
777         ioid_t  ioid;
778
779         if ((ioid = SYSIO_INTERFACE_NAME(iread64x)(fd, 
780                                                    iov, 
781                                                    iov_count, 
782                                                    xtv, 
783                                                    xtv_count)) == IOID_FAIL)
784                 return -1;
785         return iowait(ioid);
786 }
787 #endif
788
789 #ifdef notdef
790 int
791 read_list(int fd,
792           int mem_list_count,
793           char *mem_offsets[],
794           int mem_lengths[],
795           int file_list_count,
796           int64_t file_offsets[],
797           int32_t file_lengths[])
798 {
799         SYSIO_INTERFACE_DISPLAY_BLOCK;
800
801         SYSIO_INTERFACE_ENTER;
802         SYSIO_INTERFACE_RETURN(-1, -ENOSYS);
803 }
804 #endif
805
806 ioid_t
807 SYSIO_INTERFACE_NAME(iwritev)(int fd, 
808                               const struct iovec *iov, 
809                               int count)
810 {
811         struct file *fil;
812         struct intnl_xtvec *xtv;
813         struct ioctx *ioctx;
814         int     err;
815         SYSIO_INTERFACE_DISPLAY_BLOCK;
816
817         SYSIO_INTERFACE_ENTER;
818         fil = _sysio_fd_find(fd);
819         if (!fil)
820                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
821
822         xtv = malloc(sizeof(struct intnl_xtvec));
823         if (!xtv)
824                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
825
826         err =
827             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
828                         fil,
829                         iov, count, NULL,
830                         xtv, free_xtv,
831                         &ioctx);
832         if (err) {
833                 free(xtv);
834                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
835         }
836         SYSIO_INTERFACE_RETURN(ioctx, 0);
837 }
838
839 ssize_t
840 SYSIO_INTERFACE_NAME(writev)(int fd, const struct iovec *iov, int count)
841 {
842         struct file *fil;
843         struct intnl_xtvec xtvector;
844         struct ioctx *ioctx;
845         int     err;
846         ssize_t cc;
847         SYSIO_INTERFACE_DISPLAY_BLOCK;
848
849         SYSIO_INTERFACE_ENTER;
850         fil = _sysio_fd_find(fd);
851         if (!fil)
852                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
853
854         err =
855             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
856                         fil,
857                         iov, count, NULL,
858                         &xtvector, NULL,
859                         &ioctx);
860         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
861                 err = (int )cc;
862
863         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
864 }
865
866 #ifdef __GLIBC__
867 #undef __writev
868 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
869                      PREPEND(__, SYSIO_INTERFACE_NAME(writev)))
870 #undef __libc_writev
871 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
872                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_writev)))
873 #endif
874
875 ioid_t
876 SYSIO_INTERFACE_NAME(iwrite)(int fd, const void *buf, size_t count)
877 {
878         struct iovec *iov;
879         struct file *fil;
880         struct intnl_xtvec *xtv;
881         struct ioctx *ioctx;
882         int     err;
883         SYSIO_INTERFACE_DISPLAY_BLOCK;
884
885         SYSIO_INTERFACE_ENTER;
886         fil = _sysio_fd_find(fd);
887         if (!fil)
888                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
889
890         iov = malloc(sizeof(struct iovec));
891         if (!iov)
892                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
893
894         iov->iov_base = (void *)buf;
895         iov->iov_len = count;
896         xtv = malloc(sizeof(struct intnl_xtvec));
897         if (!xtv) {
898                 free(iov);
899                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
900         }
901         err =
902             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
903                         fil,
904                         iov, 1, free_iov,
905                         xtv, free_xtv,
906                         &ioctx);
907         if (err) {
908                 free(xtv);
909                 free(iov);
910                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
911         }
912         SYSIO_INTERFACE_RETURN(ioctx, 0);
913 }
914
915 ssize_t
916 SYSIO_INTERFACE_NAME(write)(int fd, const void *buf, size_t count)
917 {
918         struct file *fil;
919         struct iovec iovector;
920         struct intnl_xtvec xtvector;
921         int     err;
922         struct ioctx *ioctx;
923         ssize_t cc;
924         SYSIO_INTERFACE_DISPLAY_BLOCK;
925
926         SYSIO_INTERFACE_ENTER;
927         fil = _sysio_fd_find(fd);
928         if (!fil)
929                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
930
931         iovector.iov_base = (void *)buf;
932         iovector.iov_len = count;
933         err =
934             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
935                         fil,
936                         &iovector, 1, NULL,
937                         &xtvector, NULL,
938                         &ioctx);
939         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
940                 err = (int )cc;
941
942         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
943 }
944
945 #ifdef __GLIBC__
946 #undef __write
947 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
948                      PREPEND(__, SYSIO_INTERFACE_NAME(write)))
949 #undef __libc_write
950 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
951                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_write)))
952 #endif 
953
954 static ioid_t
955 PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(int fd, 
956                                            const struct iovec *iov, 
957                                            size_t count, 
958                                            _SYSIO_OFF_T offset)
959 {
960         struct file *fil;
961         struct intnl_xtvec *xtv;
962         struct ioctx *ioctx;
963         int     err;
964         SYSIO_INTERFACE_DISPLAY_BLOCK;
965
966         SYSIO_INTERFACE_ENTER;
967         fil = _sysio_fd_find(fd);
968         if (!fil)
969                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
970
971         xtv = malloc(sizeof(struct intnl_xtvec));
972         if (!xtv)
973                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
974
975         err =
976             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
977                          fil,
978                          iov, count, NULL,
979                          offset,
980                          xtv, free_xtv,
981                          &ioctx);
982         if (err) {
983                 free(xtv);
984                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
985         }
986         SYSIO_INTERFACE_RETURN(ioctx, 0);
987 }
988
989 #if _LARGEFILE64_SOURCE
990 #undef ipwrite64v
991 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev)),
992                      SYSIO_INTERFACE_NAME(ipwrite64v))
993 #endif
994
995 ioid_t
996 SYSIO_INTERFACE_NAME(ipwritev)(int fd, 
997                                const struct iovec *iov, 
998                                size_t count, 
999                                off_t offset)
1000 {
1001
1002         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(fd, 
1003                                                           iov, 
1004                                                           count, 
1005                                                           offset);
1006 }
1007
1008 static ssize_t
1009 PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(int fd, 
1010                                           const struct iovec *iov, 
1011                                           size_t count, 
1012                                           _SYSIO_OFF_T offset)
1013 {
1014         struct file *fil;
1015         struct intnl_xtvec xtvector;
1016         struct ioctx *ioctx;
1017         int     err;
1018         ssize_t cc;
1019         SYSIO_INTERFACE_DISPLAY_BLOCK;
1020
1021         SYSIO_INTERFACE_ENTER;
1022         fil = _sysio_fd_find(fd);
1023         if (!fil)
1024                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1025
1026         err =
1027             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1028                          fil,
1029                          iov, count, NULL,
1030                          offset,
1031                          &xtvector, NULL,
1032                          &ioctx);
1033         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1034                 err = (int )cc;
1035
1036         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1037 }
1038
1039 #if _LARGEFILE64_SOURCE
1040 #undef pwrite64v
1041 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwritev)),
1042                      SYSIO_INTERFACE_NAME(pwrite64v))
1043 #endif
1044
1045 ssize_t
1046 SYSIO_INTERFACE_NAME(pwritev)(int fd, 
1047                               const struct iovec *iov, 
1048                               size_t count, 
1049                               off_t offset)
1050 {
1051
1052         return PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(fd, 
1053                                                          iov, 
1054                                                          count, 
1055                                                          offset);
1056 }
1057
1058 static ioid_t
1059 PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(int fd, 
1060                                           const void *buf, 
1061                                           size_t count, 
1062                                           _SYSIO_OFF_T offset)
1063 {
1064         struct file *fil;
1065         struct intnl_xtvec *xtv;
1066         struct iovec *iov;
1067         struct ioctx *ioctx;
1068         int     err;
1069         SYSIO_INTERFACE_DISPLAY_BLOCK;
1070
1071         SYSIO_INTERFACE_ENTER;
1072         fil = _sysio_fd_find(fd);
1073         if (!fil)
1074                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1075
1076         xtv = malloc(sizeof(struct intnl_xtvec));
1077         iov = malloc(sizeof(struct iovec));
1078         if (!(xtv && iov)) {
1079                 err = -errno;
1080                 goto error;
1081         }
1082         xtv->xtv_off = offset;
1083         iov->iov_base = (void *)buf;
1084         xtv->xtv_len = iov->iov_len = count;
1085         err =
1086             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1087                          fil,
1088                          iov, 1, free_iov,
1089                          offset,
1090                          xtv, free_xtv,
1091                          &ioctx);
1092 error:
1093         if (err) {
1094                 if (iov)
1095                         free(iov);
1096                 if (xtv)
1097                         free(xtv);
1098                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1099         }
1100         SYSIO_INTERFACE_RETURN(ioctx, 0);
1101 }
1102
1103 #if _LARGEFILE64_SOURCE
1104 #undef ipwrite64
1105 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite)),
1106                      SYSIO_INTERFACE_NAME(ipwrite64))
1107 #endif
1108
1109 ioid_t
1110 SYSIO_INTERFACE_NAME(ipwrite)(int fd, 
1111                               const void *buf, 
1112                               size_t count, 
1113                               off_t offset)
1114 {
1115
1116         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(fd, 
1117                                                          buf, 
1118                                                          count, 
1119                                                          offset);
1120 }
1121
1122 ssize_t
1123 PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(int fd, 
1124                                          const void *buf, 
1125                                          size_t count, 
1126                                          _SYSIO_OFF_T offset)
1127 {
1128         struct file *fil;
1129         struct intnl_xtvec xtvec;
1130         struct iovec iovec;
1131         struct ioctx *ioctx;
1132         int     err;
1133         ssize_t cc;
1134         SYSIO_INTERFACE_DISPLAY_BLOCK;
1135
1136         SYSIO_INTERFACE_ENTER;
1137         fil = _sysio_fd_find(fd);
1138         if (!fil)
1139                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1140
1141         xtvec.xtv_off = offset;
1142         iovec.iov_base = (void *)buf;
1143         xtvec.xtv_len = iovec.iov_len = count;
1144         err =
1145             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1146                          fil,
1147                          &iovec, 1, NULL,
1148                          offset,
1149                          &xtvec, NULL,
1150                          &ioctx);
1151         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1152                 err = (int )cc;
1153
1154         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1155 }
1156
1157 #if _LARGEFILE64_SOURCE
1158 #undef pwrite64
1159 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1160                      SYSIO_INTERFACE_NAME(pwrite64))
1161 #ifdef __GLIBC
1162 #undef __pwrite64
1163 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1164                      PREPEND(__, SYSIO_INTERFACE_NAME(pwrite64)))
1165 #undef __libc_pwrite64
1166 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1167                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite64)))
1168 #endif
1169 #endif
1170
1171 ssize_t
1172 SYSIO_INTERFACE_NAME(pwrite)(int fd, 
1173                              const void *buf, 
1174                              size_t count, 
1175                              off_t offset)
1176 {
1177
1178         return PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(fd, 
1179                                                         buf, 
1180                                                         count, 
1181                                                         offset);
1182 }
1183
1184 #ifdef __GLIBC
1185 #undef __libc_pwrite
1186 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(pwrite), __libc_pwrite)
1187                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite)))
1188 #endif
1189
1190 static ioid_t
1191 PREPEND(_, SYSIO_INTERFACE_NAME(iwritex))(int fd,
1192                                           const struct iovec *iov, 
1193                                           size_t iov_count, 
1194                                           const struct intnl_xtvec *xtv, 
1195                                           size_t xtv_count)
1196 {
1197         struct file *fil;
1198         int     err;
1199         struct ioctx *ioctx;
1200         SYSIO_INTERFACE_DISPLAY_BLOCK;
1201
1202         SYSIO_INTERFACE_ENTER;
1203         fil = _sysio_fd_find(fd);
1204         if (!(fil && xtv_count))
1205                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1206
1207         err =
1208             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1209                         fil,
1210                         iov, iov_count, NULL,
1211                         xtv, xtv_count, NULL,
1212                         NULL,
1213                         &ioctx);
1214
1215         SYSIO_INTERFACE_RETURN(err ? IOID_FAIL : ioctx, err);
1216 }
1217
1218 #if _LARGEFILE64_SOURCE
1219 #undef iwrite64x
1220 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1221                      SYSIO_INTERFACE_NAME(iwrite64x))
1222 #endif
1223
1224 #if _LARGEFILE64_SOURCE
1225 ioid_t
1226 SYSIO_INTERFACE_NAME(iwritex)(int fd,
1227                               const struct iovec *iov, size_t iov_count,
1228                               const struct xtvec *xtv, size_t xtv_count)
1229 {
1230         struct file *fil;
1231         struct intnl_xtvec *ixtv, *ixtvent;
1232         size_t  count;
1233         int     err;
1234         struct ioctx *ioctx;
1235         SYSIO_INTERFACE_DISPLAY_BLOCK;
1236
1237         SYSIO_INTERFACE_ENTER;
1238         fil = _sysio_fd_find(fd);
1239         if (!(fil && xtv_count))
1240                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1241
1242         ixtv = ixtvent = malloc(xtv_count * sizeof(struct intnl_xtvec));
1243         if (!ixtv)
1244                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
1245
1246         count = xtv_count;
1247         while (count--) {
1248                 ixtvent->xtv_off = xtv->xtv_off;
1249                 ixtvent->xtv_len = xtv->xtv_len;
1250                 ixtvent++;
1251                 xtv++;
1252         }
1253
1254         err =
1255             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1256                         fil,
1257                         iov, iov_count, NULL,
1258                         ixtv, xtv_count, free_xtv,
1259                         NULL,
1260                         &ioctx);
1261         if (err) {
1262                 free(ixtv);
1263                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1264         }
1265         SYSIO_INTERFACE_RETURN(ioctx, 0);
1266 }
1267 #else
1268 #undef iwritex
1269 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1270                      SYSIO_INTERFACE_NAME(iwritex))
1271 #endif
1272
1273 #undef writex
1274 ssize_t
1275 SYSIO_INTERFACE_NAME(writex)(int fd,
1276                              const struct iovec *iov, size_t iov_count,
1277                              const struct xtvec *xtv, size_t xtv_count)
1278 {
1279         ioid_t  ioid;
1280
1281         if ((ioid = 
1282              SYSIO_INTERFACE_NAME(iwritex)(fd, 
1283                                            iov, 
1284                                            iov_count, 
1285                                            xtv, 
1286                                            xtv_count)) == IOID_FAIL)
1287                 return -1;
1288         return iowait(ioid);
1289 }
1290
1291 #if _LARGEFILE64_SOURCE
1292 #undef write64x
1293 ssize_t
1294 SYSIO_INTERFACE_NAME(write64x)(int fd,
1295          const struct iovec *iov, size_t iov_count,
1296          const struct xtvec64 *xtv, size_t xtv_count)
1297 {
1298         ioid_t  ioid;
1299
1300         if ((ioid = SYSIO_INTERFACE_NAME(iwrite64x)(fd, 
1301                                                     iov, 
1302                                                     iov_count, 
1303                                                     xtv, 
1304                                                     xtv_count)) == IOID_FAIL)
1305                 return -1;
1306         return iowait(ioid);
1307 }
1308 #endif
1309
1310 #ifdef notdef
1311 int
1312 write_list(int fd,
1313            int mem_list_count,
1314            char *mem_offsets[],
1315            int mem_lengths[],
1316            int file_list_count,
1317            int64_t file_offsets[],
1318            int32_t file_lengths[])
1319 {
1320         SYSIO_INTERFACE_DISPLAY_BLOCK;
1321
1322         SYSIO_INTERFACE_ENTER;
1323         SYSIO_INTERFACE_RETURN(-1, -ENOSYS);
1324 }
1325 #endif