Whamcloud - gitweb
Land b_release_1_4_6 onto HEAD (20060223_1455)
[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 (!(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)
686                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
687
688         /* Perform a check on the iov_count and xtv_count */
689         if ((iov_count == 0) || (xtv_count == 0))
690                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EINVAL);
691
692         err =
693             _sysio_iiox(IIOXOP_READ(fil->f_ino),
694                         fil,
695                         iov, iov_count, NULL,
696                         xtv, xtv_count, NULL,
697                         NULL,
698                         &ioctx);
699
700         SYSIO_INTERFACE_RETURN(err ? IOID_FAIL : ioctx, err);
701 }
702
703 #if _LARGEFILE64_SOURCE
704 #undef iread64x
705 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ireadx)),
706                      SYSIO_INTERFACE_NAME(iread64x))
707 #endif
708
709 #if _LARGEFILE64_SOURCE
710 ioid_t
711 SYSIO_INTERFACE_NAME(ireadx)(int fd,
712                              const struct iovec *iov, size_t iov_count,
713                              const struct xtvec *xtv, size_t xtv_count)
714 {
715         struct file *fil;
716         struct intnl_xtvec *ixtv, *ixtvent;
717         size_t  count;
718         int     err;
719         struct ioctx *ioctx;
720         SYSIO_INTERFACE_DISPLAY_BLOCK;
721
722         SYSIO_INTERFACE_ENTER;
723         fil = _sysio_fd_find(fd);
724         if (!fil)
725                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
726
727
728         /* Perform a check on the iov_count and xtv_count */
729         if ((iov_count == 0) || (xtv_count == 0))
730                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EINVAL);
731
732         ixtv = ixtvent = malloc(xtv_count * sizeof(struct intnl_xtvec));
733         if (!ixtv)
734                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
735
736         count = xtv_count;
737         while (count--) {
738                 ixtvent->xtv_off = xtv->xtv_off;
739                 ixtvent->xtv_len = xtv->xtv_len;
740                 ixtvent++;
741                 xtv++;
742         }
743
744         err =
745             _sysio_iiox(IIOXOP_READ(fil->f_ino),
746                         fil,
747                         iov, iov_count, NULL,
748                         ixtv, xtv_count, free_xtv,
749                         NULL,
750                         &ioctx);
751         if (err) {
752                 free(ixtv);
753                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
754         }
755         SYSIO_INTERFACE_RETURN(ioctx, 0);
756 }
757 #else
758 #undef ireadx
759 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ireadx)),
760                      SYSIO_INTERFACE_NAME(ireadx))
761 #endif
762
763 ssize_t
764 SYSIO_INTERFACE_NAME(readx)(int fd,
765                             const struct iovec *iov, size_t iov_count,
766                             const struct xtvec *xtv, size_t xtv_count)
767 {
768         ioid_t  ioid;
769
770         if ((ioid = SYSIO_INTERFACE_NAME(ireadx)(fd, 
771                                                  iov, 
772                                                  iov_count, 
773                                                  xtv, 
774                                                  xtv_count)) == IOID_FAIL)
775                 return -1;
776         return SYSIO_INTERFACE_NAME(iowait)(ioid);
777 }
778
779 #if _LARGEFILE64_SOURCE
780 #undef iread64x
781 ssize_t
782 SYSIO_INTERFACE_NAME(read64x)(int fd,
783                               const struct iovec *iov, size_t iov_count,
784                               const struct xtvec64 *xtv, size_t xtv_count)
785 {
786         ioid_t  ioid;
787
788         if ((ioid = SYSIO_INTERFACE_NAME(iread64x)(fd, 
789                                                    iov, 
790                                                    iov_count, 
791                                                    xtv, 
792                                                    xtv_count)) == IOID_FAIL)
793                 return -1;
794         return SYSIO_INTERFACE_NAME(iowait)(ioid);
795 }
796 #endif
797
798 #ifdef notdef
799 int
800 read_list(int fd,
801           int mem_list_count,
802           char *mem_offsets[],
803           int mem_lengths[],
804           int file_list_count,
805           int64_t file_offsets[],
806           int32_t file_lengths[])
807 {
808         SYSIO_INTERFACE_DISPLAY_BLOCK;
809
810         SYSIO_INTERFACE_ENTER;
811         SYSIO_INTERFACE_RETURN(-1, -ENOSYS);
812 }
813 #endif
814
815 ioid_t
816 SYSIO_INTERFACE_NAME(iwritev)(int fd, 
817                               const struct iovec *iov, 
818                               int count)
819 {
820         struct file *fil;
821         struct intnl_xtvec *xtv;
822         struct ioctx *ioctx;
823         int     err;
824         SYSIO_INTERFACE_DISPLAY_BLOCK;
825
826         SYSIO_INTERFACE_ENTER;
827         fil = _sysio_fd_find(fd);
828         if (!fil)
829                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
830
831         xtv = malloc(sizeof(struct intnl_xtvec));
832         if (!xtv)
833                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
834
835         err =
836             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
837                         fil,
838                         iov, count, NULL,
839                         xtv, free_xtv,
840                         &ioctx);
841         if (err) {
842                 free(xtv);
843                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
844         }
845         SYSIO_INTERFACE_RETURN(ioctx, 0);
846 }
847
848 ssize_t
849 SYSIO_INTERFACE_NAME(writev)(int fd, const struct iovec *iov, int count)
850 {
851         struct file *fil;
852         struct intnl_xtvec xtvector;
853         struct ioctx *ioctx;
854         int     err;
855         ssize_t cc;
856         SYSIO_INTERFACE_DISPLAY_BLOCK;
857
858         SYSIO_INTERFACE_ENTER;
859         fil = _sysio_fd_find(fd);
860         if (!fil)
861                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
862
863         err =
864             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
865                         fil,
866                         iov, count, NULL,
867                         &xtvector, NULL,
868                         &ioctx);
869         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
870                 err = (int )cc;
871
872         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
873 }
874
875 #ifdef __GLIBC__
876 #undef __writev
877 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
878                      PREPEND(__, SYSIO_INTERFACE_NAME(writev)))
879 #undef __libc_writev
880 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
881                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_writev)))
882 #endif
883
884 ioid_t
885 SYSIO_INTERFACE_NAME(iwrite)(int fd, const void *buf, size_t count)
886 {
887         struct iovec *iov;
888         struct file *fil;
889         struct intnl_xtvec *xtv;
890         struct ioctx *ioctx;
891         int     err;
892         SYSIO_INTERFACE_DISPLAY_BLOCK;
893
894         SYSIO_INTERFACE_ENTER;
895         fil = _sysio_fd_find(fd);
896         if (!fil)
897                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
898
899         iov = malloc(sizeof(struct iovec));
900         if (!iov)
901                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
902
903         iov->iov_base = (void *)buf;
904         iov->iov_len = count;
905         xtv = malloc(sizeof(struct intnl_xtvec));
906         if (!xtv) {
907                 free(iov);
908                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
909         }
910         err =
911             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
912                         fil,
913                         iov, 1, free_iov,
914                         xtv, free_xtv,
915                         &ioctx);
916         if (err) {
917                 free(xtv);
918                 free(iov);
919                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
920         }
921         SYSIO_INTERFACE_RETURN(ioctx, 0);
922 }
923
924 ssize_t
925 SYSIO_INTERFACE_NAME(write)(int fd, const void *buf, size_t count)
926 {
927         struct file *fil;
928         struct iovec iovector;
929         struct intnl_xtvec xtvector;
930         int     err;
931         struct ioctx *ioctx;
932         ssize_t cc;
933         SYSIO_INTERFACE_DISPLAY_BLOCK;
934
935         SYSIO_INTERFACE_ENTER;
936         fil = _sysio_fd_find(fd);
937         if (!fil)
938                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
939
940         iovector.iov_base = (void *)buf;
941         iovector.iov_len = count;
942         err =
943             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
944                         fil,
945                         &iovector, 1, NULL,
946                         &xtvector, NULL,
947                         &ioctx);
948         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
949                 err = (int )cc;
950
951         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
952 }
953
954 #ifdef __GLIBC__
955 #undef __write
956 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
957                      PREPEND(__, SYSIO_INTERFACE_NAME(write)))
958 #undef __libc_write
959 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
960                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_write)))
961 #endif 
962
963 static ioid_t
964 PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(int fd, 
965                                            const struct iovec *iov, 
966                                            size_t count, 
967                                            _SYSIO_OFF_T offset)
968 {
969         struct file *fil;
970         struct intnl_xtvec *xtv;
971         struct ioctx *ioctx;
972         int     err;
973         SYSIO_INTERFACE_DISPLAY_BLOCK;
974
975         SYSIO_INTERFACE_ENTER;
976         fil = _sysio_fd_find(fd);
977         if (!fil)
978                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
979
980         xtv = malloc(sizeof(struct intnl_xtvec));
981         if (!xtv)
982                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
983
984         err =
985             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
986                          fil,
987                          iov, count, NULL,
988                          offset,
989                          xtv, free_xtv,
990                          &ioctx);
991         if (err) {
992                 free(xtv);
993                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
994         }
995         SYSIO_INTERFACE_RETURN(ioctx, 0);
996 }
997
998 #if _LARGEFILE64_SOURCE
999 #undef ipwrite64v
1000 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev)),
1001                      SYSIO_INTERFACE_NAME(ipwrite64v))
1002 #endif
1003
1004 ioid_t
1005 SYSIO_INTERFACE_NAME(ipwritev)(int fd, 
1006                                const struct iovec *iov, 
1007                                size_t count, 
1008                                off_t offset)
1009 {
1010
1011         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(fd, 
1012                                                           iov, 
1013                                                           count, 
1014                                                           offset);
1015 }
1016
1017 static ssize_t
1018 PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(int fd, 
1019                                           const struct iovec *iov, 
1020                                           size_t count, 
1021                                           _SYSIO_OFF_T offset)
1022 {
1023         struct file *fil;
1024         struct intnl_xtvec xtvector;
1025         struct ioctx *ioctx;
1026         int     err;
1027         ssize_t cc;
1028         SYSIO_INTERFACE_DISPLAY_BLOCK;
1029
1030         SYSIO_INTERFACE_ENTER;
1031         fil = _sysio_fd_find(fd);
1032         if (!fil)
1033                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1034
1035         err =
1036             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1037                          fil,
1038                          iov, count, NULL,
1039                          offset,
1040                          &xtvector, NULL,
1041                          &ioctx);
1042         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1043                 err = (int )cc;
1044
1045         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1046 }
1047
1048 #if _LARGEFILE64_SOURCE
1049 #undef pwrite64v
1050 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwritev)),
1051                      SYSIO_INTERFACE_NAME(pwrite64v))
1052 #endif
1053
1054 ssize_t
1055 SYSIO_INTERFACE_NAME(pwritev)(int fd, 
1056                               const struct iovec *iov, 
1057                               size_t count, 
1058                               off_t offset)
1059 {
1060
1061         return PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(fd, 
1062                                                          iov, 
1063                                                          count, 
1064                                                          offset);
1065 }
1066
1067 static ioid_t
1068 PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(int fd, 
1069                                           const void *buf, 
1070                                           size_t count, 
1071                                           _SYSIO_OFF_T offset)
1072 {
1073         struct file *fil;
1074         struct intnl_xtvec *xtv;
1075         struct iovec *iov;
1076         struct ioctx *ioctx;
1077         int     err;
1078         SYSIO_INTERFACE_DISPLAY_BLOCK;
1079
1080         SYSIO_INTERFACE_ENTER;
1081         fil = _sysio_fd_find(fd);
1082         if (!fil)
1083                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1084
1085         xtv = malloc(sizeof(struct intnl_xtvec));
1086         iov = malloc(sizeof(struct iovec));
1087         if (!(xtv && iov)) {
1088                 err = -errno;
1089                 goto error;
1090         }
1091         xtv->xtv_off = offset;
1092         iov->iov_base = (void *)buf;
1093         xtv->xtv_len = iov->iov_len = count;
1094         err =
1095             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1096                          fil,
1097                          iov, 1, free_iov,
1098                          offset,
1099                          xtv, free_xtv,
1100                          &ioctx);
1101 error:
1102         if (err) {
1103                 if (iov)
1104                         free(iov);
1105                 if (xtv)
1106                         free(xtv);
1107                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1108         }
1109         SYSIO_INTERFACE_RETURN(ioctx, 0);
1110 }
1111
1112 #if _LARGEFILE64_SOURCE
1113 #undef ipwrite64
1114 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite)),
1115                      SYSIO_INTERFACE_NAME(ipwrite64))
1116 #endif
1117
1118 ioid_t
1119 SYSIO_INTERFACE_NAME(ipwrite)(int fd, 
1120                               const void *buf, 
1121                               size_t count, 
1122                               off_t offset)
1123 {
1124
1125         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(fd, 
1126                                                          buf, 
1127                                                          count, 
1128                                                          offset);
1129 }
1130
1131 ssize_t
1132 PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(int fd, 
1133                                          const void *buf, 
1134                                          size_t count, 
1135                                          _SYSIO_OFF_T offset)
1136 {
1137         struct file *fil;
1138         struct intnl_xtvec xtvec;
1139         struct iovec iovec;
1140         struct ioctx *ioctx;
1141         int     err;
1142         ssize_t cc;
1143         SYSIO_INTERFACE_DISPLAY_BLOCK;
1144
1145         SYSIO_INTERFACE_ENTER;
1146         fil = _sysio_fd_find(fd);
1147         if (!fil)
1148                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1149
1150         xtvec.xtv_off = offset;
1151         iovec.iov_base = (void *)buf;
1152         xtvec.xtv_len = iovec.iov_len = count;
1153         err =
1154             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1155                          fil,
1156                          &iovec, 1, NULL,
1157                          offset,
1158                          &xtvec, NULL,
1159                          &ioctx);
1160         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1161                 err = (int )cc;
1162
1163         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1164 }
1165
1166 #if _LARGEFILE64_SOURCE
1167 #undef pwrite64
1168 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1169                      SYSIO_INTERFACE_NAME(pwrite64))
1170 #ifdef __GLIBC
1171 #undef __pwrite64
1172 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1173                      PREPEND(__, SYSIO_INTERFACE_NAME(pwrite64)))
1174 #undef __libc_pwrite64
1175 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1176                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite64)))
1177 #endif
1178 #endif
1179
1180 ssize_t
1181 SYSIO_INTERFACE_NAME(pwrite)(int fd, 
1182                              const void *buf, 
1183                              size_t count, 
1184                              off_t offset)
1185 {
1186
1187         return PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(fd, 
1188                                                         buf, 
1189                                                         count, 
1190                                                         offset);
1191 }
1192
1193 #ifdef __GLIBC
1194 #undef __libc_pwrite
1195 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(pwrite), __libc_pwrite)
1196                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite)))
1197 #endif
1198
1199 static ioid_t
1200 PREPEND(_, SYSIO_INTERFACE_NAME(iwritex))(int fd,
1201                                           const struct iovec *iov, 
1202                                           size_t iov_count, 
1203                                           const struct intnl_xtvec *xtv, 
1204                                           size_t xtv_count)
1205 {
1206         struct file *fil;
1207         int     err;
1208         struct ioctx *ioctx;
1209         SYSIO_INTERFACE_DISPLAY_BLOCK;
1210
1211         SYSIO_INTERFACE_ENTER;
1212         fil = _sysio_fd_find(fd);
1213         if (!(fil && xtv_count))
1214                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1215
1216         err =
1217             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1218                         fil,
1219                         iov, iov_count, NULL,
1220                         xtv, xtv_count, NULL,
1221                         NULL,
1222                         &ioctx);
1223
1224         SYSIO_INTERFACE_RETURN(err ? IOID_FAIL : ioctx, err);
1225 }
1226
1227 #if _LARGEFILE64_SOURCE
1228 #undef iwrite64x
1229 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1230                      SYSIO_INTERFACE_NAME(iwrite64x))
1231 #endif
1232
1233 #if _LARGEFILE64_SOURCE
1234 ioid_t
1235 SYSIO_INTERFACE_NAME(iwritex)(int fd,
1236                               const struct iovec *iov, size_t iov_count,
1237                               const struct xtvec *xtv, size_t xtv_count)
1238 {
1239         struct file *fil;
1240         struct intnl_xtvec *ixtv, *ixtvent;
1241         size_t  count;
1242         int     err;
1243         struct ioctx *ioctx;
1244         SYSIO_INTERFACE_DISPLAY_BLOCK;
1245
1246         SYSIO_INTERFACE_ENTER;
1247         fil = _sysio_fd_find(fd);
1248         if (!fil)
1249                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1250
1251         /* Perform a check on the iov_count and xtv_count */
1252         if ((iov_count == 0) || (xtv_count == 0))
1253                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EINVAL);
1254
1255         ixtv = ixtvent = malloc(xtv_count * sizeof(struct intnl_xtvec));
1256         if (!ixtv)
1257                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
1258
1259         count = xtv_count;
1260         while (count--) {
1261                 ixtvent->xtv_off = xtv->xtv_off;
1262                 ixtvent->xtv_len = xtv->xtv_len;
1263                 ixtvent++;
1264                 xtv++;
1265         }
1266
1267         err =
1268             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1269                         fil,
1270                         iov, iov_count, NULL,
1271                         ixtv, xtv_count, free_xtv,
1272                         NULL,
1273                         &ioctx);
1274         if (err) {
1275                 free(ixtv);
1276                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1277         }
1278         SYSIO_INTERFACE_RETURN(ioctx, 0);
1279 }
1280 #else
1281 #undef iwritex
1282 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1283                      SYSIO_INTERFACE_NAME(iwritex))
1284 #endif
1285
1286 #undef writex
1287 ssize_t
1288 SYSIO_INTERFACE_NAME(writex)(int fd,
1289                              const struct iovec *iov, size_t iov_count,
1290                              const struct xtvec *xtv, size_t xtv_count)
1291 {
1292         ioid_t  ioid;
1293
1294         if ((ioid = 
1295              SYSIO_INTERFACE_NAME(iwritex)(fd, 
1296                                            iov, 
1297                                            iov_count, 
1298                                            xtv, 
1299                                            xtv_count)) == IOID_FAIL)
1300                 return -1;
1301         return SYSIO_INTERFACE_NAME(iowait)(ioid);
1302 }
1303
1304 #if _LARGEFILE64_SOURCE
1305 #undef write64x
1306 ssize_t
1307 SYSIO_INTERFACE_NAME(write64x)(int fd,
1308          const struct iovec *iov, size_t iov_count,
1309          const struct xtvec64 *xtv, size_t xtv_count)
1310 {
1311         ioid_t  ioid;
1312
1313         if ((ioid = SYSIO_INTERFACE_NAME(iwrite64x)(fd, 
1314                                                     iov, 
1315                                                     iov_count, 
1316                                                     xtv, 
1317                                                     xtv_count)) == IOID_FAIL)
1318                 return -1;
1319         return SYSIO_INTERFACE_NAME(iowait)(ioid);
1320 }
1321 #endif
1322
1323 #ifdef notdef
1324 int
1325 write_list(int fd,
1326            int mem_list_count,
1327            char *mem_offsets[],
1328            int mem_lengths[],
1329            int file_list_count,
1330            int64_t file_offsets[],
1331            int32_t file_lengths[])
1332 {
1333         SYSIO_INTERFACE_DISPLAY_BLOCK;
1334
1335         SYSIO_INTERFACE_ENTER;
1336         SYSIO_INTERFACE_RETURN(-1, -ENOSYS);
1337 }
1338 #endif