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