Whamcloud - gitweb
LU-4725 obd: lu_object_find_at hung
[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 defined(_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 #ifdef _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                                          _SYSIO_PREADV_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 #ifdef _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                              _SYSIO_PREADV_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 #ifdef _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 #ifdef _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 #ifdef _LARGEFILE64_SOURCE
702 #undef iread64x
703 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ireadx)),
704                      SYSIO_INTERFACE_NAME(iread64x))
705 #endif
706
707 #ifdef _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 #ifdef _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,
848                              int count)
849 {
850         struct file *fil;
851         struct intnl_xtvec xtvector;
852         struct ioctx *ioctx;
853         int     err;
854         ssize_t cc;
855         SYSIO_INTERFACE_DISPLAY_BLOCK;
856
857         SYSIO_INTERFACE_ENTER;
858         fil = _sysio_fd_find(fd);
859         if (!fil)
860                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
861
862         err =
863             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
864                         fil,
865                         iov, count, NULL,
866                         &xtvector, NULL,
867                         &ioctx);
868         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
869                 err = (int )cc;
870
871         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
872 }
873
874 #ifdef __GLIBC__
875 #undef __writev
876 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
877                      PREPEND(__, SYSIO_INTERFACE_NAME(writev)))
878 #undef __libc_writev
879 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(writev),
880                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_writev)))
881 #endif
882
883 ioid_t
884 SYSIO_INTERFACE_NAME(iwrite)(int fd, const void *buf, size_t count)
885 {
886         struct iovec *iov;
887         struct file *fil;
888         struct intnl_xtvec *xtv;
889         struct ioctx *ioctx;
890         int     err;
891         SYSIO_INTERFACE_DISPLAY_BLOCK;
892
893         SYSIO_INTERFACE_ENTER;
894         fil = _sysio_fd_find(fd);
895         if (!fil)
896                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
897
898         iov = malloc(sizeof(struct iovec));
899         if (!iov)
900                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
901
902         iov->iov_base = (void *)buf;
903         iov->iov_len = count;
904         xtv = malloc(sizeof(struct intnl_xtvec));
905         if (!xtv) {
906                 free(iov);
907                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
908         }
909         err =
910             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
911                         fil,
912                         iov, 1, free_iov,
913                         xtv, free_xtv,
914                         &ioctx);
915         if (err) {
916                 free(xtv);
917                 free(iov);
918                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
919         }
920         SYSIO_INTERFACE_RETURN(ioctx, 0);
921 }
922
923 ssize_t
924 SYSIO_INTERFACE_NAME(write)(int fd, const void *buf, size_t count)
925 {
926         struct file *fil;
927         struct iovec iovector;
928         struct intnl_xtvec xtvector;
929         int     err;
930         struct ioctx *ioctx;
931         ssize_t cc;
932         SYSIO_INTERFACE_DISPLAY_BLOCK;
933
934         SYSIO_INTERFACE_ENTER;
935         fil = _sysio_fd_find(fd);
936         if (!fil)
937                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
938
939         iovector.iov_base = (void *)buf;
940         iovector.iov_len = count;
941         err =
942             _sysio_iiov(IIOXOP_WRITE(fil->f_ino),
943                         fil,
944                         &iovector, 1, NULL,
945                         &xtvector, NULL,
946                         &ioctx);
947         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
948                 err = (int )cc;
949
950         SYSIO_INTERFACE_RETURN(err < 0 ? -1 : cc, err);
951 }
952
953 #ifdef __GLIBC__
954 #undef __write
955 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
956                      PREPEND(__, SYSIO_INTERFACE_NAME(write)))
957 #undef __libc_write
958 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(write),
959                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_write)))
960 #endif 
961
962 static ioid_t
963 PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(int fd, 
964                                            const struct iovec *iov, 
965                                            size_t count, 
966                                            _SYSIO_OFF_T offset)
967 {
968         struct file *fil;
969         struct intnl_xtvec *xtv;
970         struct ioctx *ioctx;
971         int     err;
972         SYSIO_INTERFACE_DISPLAY_BLOCK;
973
974         SYSIO_INTERFACE_ENTER;
975         fil = _sysio_fd_find(fd);
976         if (!fil)
977                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
978
979         xtv = malloc(sizeof(struct intnl_xtvec));
980         if (!xtv)
981                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
982
983         err =
984             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
985                          fil,
986                          iov, count, NULL,
987                          offset,
988                          xtv, free_xtv,
989                          &ioctx);
990         if (err) {
991                 free(xtv);
992                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
993         }
994         SYSIO_INTERFACE_RETURN(ioctx, 0);
995 }
996
997 #ifdef _LARGEFILE64_SOURCE
998 #undef ipwrite64v
999 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev)),
1000                      SYSIO_INTERFACE_NAME(ipwrite64v))
1001 #endif
1002
1003 ioid_t
1004 SYSIO_INTERFACE_NAME(ipwritev)(int fd, 
1005                                const struct iovec *iov, 
1006                                size_t count, 
1007                                off_t offset)
1008 {
1009
1010         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwritev))(fd, 
1011                                                           iov, 
1012                                                           count, 
1013                                                           offset);
1014 }
1015
1016 static ssize_t
1017 PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(int fd, 
1018                                           const struct iovec *iov, 
1019                                           _SYSIO_PREADV_T count, 
1020                                           _SYSIO_OFF_T offset)
1021 {
1022         struct file *fil;
1023         struct intnl_xtvec xtvector;
1024         struct ioctx *ioctx;
1025         int     err;
1026         ssize_t cc;
1027         SYSIO_INTERFACE_DISPLAY_BLOCK;
1028
1029         SYSIO_INTERFACE_ENTER;
1030         fil = _sysio_fd_find(fd);
1031         if (!fil)
1032                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1033
1034         err =
1035             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1036                          fil,
1037                          iov, count, NULL,
1038                          offset,
1039                          &xtvector, NULL,
1040                          &ioctx);
1041         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1042                 err = (int )cc;
1043
1044         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1045 }
1046
1047 #ifdef _LARGEFILE64_SOURCE
1048 #undef pwrite64v
1049 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwritev)),
1050                      SYSIO_INTERFACE_NAME(pwrite64v))
1051 #endif
1052
1053 ssize_t
1054 SYSIO_INTERFACE_NAME(pwritev)(int fd, 
1055                               const struct iovec *iov, 
1056                               _SYSIO_PREADV_T count, 
1057                               off_t offset)
1058 {
1059
1060         return PREPEND(_, SYSIO_INTERFACE_NAME(pwritev))(fd, 
1061                                                          iov, 
1062                                                          count, 
1063                                                          offset);
1064 }
1065
1066 static ioid_t
1067 PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(int fd, 
1068                                           const void *buf, 
1069                                           size_t count, 
1070                                           _SYSIO_OFF_T offset)
1071 {
1072         struct file *fil;
1073         struct intnl_xtvec *xtv;
1074         struct iovec *iov;
1075         struct ioctx *ioctx;
1076         int     err;
1077         SYSIO_INTERFACE_DISPLAY_BLOCK;
1078
1079         SYSIO_INTERFACE_ENTER;
1080         fil = _sysio_fd_find(fd);
1081         if (!fil)
1082                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1083
1084         xtv = malloc(sizeof(struct intnl_xtvec));
1085         iov = malloc(sizeof(struct iovec));
1086         if (!(xtv && iov)) {
1087                 err = -errno;
1088                 goto error;
1089         }
1090         xtv->xtv_off = offset;
1091         iov->iov_base = (void *)buf;
1092         xtv->xtv_len = iov->iov_len = count;
1093         err =
1094             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1095                          fil,
1096                          iov, 1, free_iov,
1097                          offset,
1098                          xtv, free_xtv,
1099                          &ioctx);
1100 error:
1101         if (err) {
1102                 if (iov)
1103                         free(iov);
1104                 if (xtv)
1105                         free(xtv);
1106                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1107         }
1108         SYSIO_INTERFACE_RETURN(ioctx, 0);
1109 }
1110
1111 #ifdef _LARGEFILE64_SOURCE
1112 #undef ipwrite64
1113 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite)),
1114                      SYSIO_INTERFACE_NAME(ipwrite64))
1115 #endif
1116
1117 ioid_t
1118 SYSIO_INTERFACE_NAME(ipwrite)(int fd, 
1119                               const void *buf, 
1120                               size_t count, 
1121                               off_t offset)
1122 {
1123
1124         return PREPEND(_, SYSIO_INTERFACE_NAME(ipwrite))(fd, 
1125                                                          buf, 
1126                                                          count, 
1127                                                          offset);
1128 }
1129
1130 ssize_t
1131 PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(int fd, 
1132                                          const void *buf, 
1133                                          size_t count, 
1134                                          _SYSIO_OFF_T offset)
1135 {
1136         struct file *fil;
1137         struct intnl_xtvec xtvec;
1138         struct iovec iovec;
1139         struct ioctx *ioctx;
1140         int     err;
1141         ssize_t cc;
1142         SYSIO_INTERFACE_DISPLAY_BLOCK;
1143
1144         SYSIO_INTERFACE_ENTER;
1145         fil = _sysio_fd_find(fd);
1146         if (!fil)
1147                 SYSIO_INTERFACE_RETURN(-1, -EBADF);
1148
1149         xtvec.xtv_off = offset;
1150         iovec.iov_base = (void *)buf;
1151         xtvec.xtv_len = iovec.iov_len = count;
1152         err =
1153             _sysio_ipiov(IIOXOP_WRITE(fil->f_ino),
1154                          fil,
1155                          &iovec, 1, NULL,
1156                          offset,
1157                          &xtvec, NULL,
1158                          &ioctx);
1159         if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0)
1160                 err = (int )cc;
1161
1162         SYSIO_INTERFACE_RETURN(err ? -1 : cc, err);
1163 }
1164
1165 #ifdef _LARGEFILE64_SOURCE
1166 #undef pwrite64
1167 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1168                      SYSIO_INTERFACE_NAME(pwrite64))
1169 #ifdef __GLIBC
1170 #undef __pwrite64
1171 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1172                      PREPEND(__, SYSIO_INTERFACE_NAME(pwrite64)))
1173 #undef __libc_pwrite64
1174 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(pwrite)),
1175                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite64)))
1176 #endif
1177 #endif
1178
1179 ssize_t
1180 SYSIO_INTERFACE_NAME(pwrite)(int fd, 
1181                              const void *buf, 
1182                              size_t count, 
1183                              off_t offset)
1184 {
1185
1186         return PREPEND(_, SYSIO_INTERFACE_NAME(pwrite))(fd, 
1187                                                         buf, 
1188                                                         count, 
1189                                                         offset);
1190 }
1191
1192 #ifdef __GLIBC
1193 #undef __libc_pwrite
1194 sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(pwrite), __libc_pwrite)
1195                      PREPEND(__, SYSIO_INTERFACE_NAME(libc_pwrite)))
1196 #endif
1197
1198 static ioid_t
1199 PREPEND(_, SYSIO_INTERFACE_NAME(iwritex))(int fd,
1200                                           const struct iovec *iov, 
1201                                           size_t iov_count, 
1202                                           const struct intnl_xtvec *xtv, 
1203                                           size_t xtv_count)
1204 {
1205         struct file *fil;
1206         int     err;
1207         struct ioctx *ioctx;
1208         SYSIO_INTERFACE_DISPLAY_BLOCK;
1209
1210         SYSIO_INTERFACE_ENTER;
1211         fil = _sysio_fd_find(fd);
1212         if (!(fil && xtv_count))
1213                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1214
1215         err =
1216             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1217                         fil,
1218                         iov, iov_count, NULL,
1219                         xtv, xtv_count, NULL,
1220                         NULL,
1221                         &ioctx);
1222
1223         SYSIO_INTERFACE_RETURN(err ? IOID_FAIL : ioctx, err);
1224 }
1225
1226 #ifdef _LARGEFILE64_SOURCE
1227 #undef iwrite64x
1228 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1229                      SYSIO_INTERFACE_NAME(iwrite64x))
1230 #endif
1231
1232 #ifdef _LARGEFILE64_SOURCE
1233 ioid_t
1234 SYSIO_INTERFACE_NAME(iwritex)(int fd,
1235                               const struct iovec *iov, size_t iov_count,
1236                               const struct xtvec *xtv, size_t xtv_count)
1237 {
1238         struct file *fil;
1239         struct intnl_xtvec *ixtv, *ixtvent;
1240         size_t  count;
1241         int     err;
1242         struct ioctx *ioctx;
1243         SYSIO_INTERFACE_DISPLAY_BLOCK;
1244
1245         SYSIO_INTERFACE_ENTER;
1246         fil = _sysio_fd_find(fd);
1247         if (!fil)
1248                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EBADF);
1249
1250         /* Perform a check on the iov_count and xtv_count */
1251         if ((iov_count == 0) || (xtv_count == 0))
1252                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -EINVAL);
1253
1254         ixtv = ixtvent = malloc(xtv_count * sizeof(struct intnl_xtvec));
1255         if (!ixtv)
1256                 SYSIO_INTERFACE_RETURN(IOID_FAIL, -ENOMEM);
1257
1258         count = xtv_count;
1259         while (count--) {
1260                 ixtvent->xtv_off = xtv->xtv_off;
1261                 ixtvent->xtv_len = xtv->xtv_len;
1262                 ixtvent++;
1263                 xtv++;
1264         }
1265
1266         err =
1267             _sysio_iiox(IIOXOP_WRITE(fil->f_ino),
1268                         fil,
1269                         iov, iov_count, NULL,
1270                         ixtv, xtv_count, free_xtv,
1271                         NULL,
1272                         &ioctx);
1273         if (err) {
1274                 free(ixtv);
1275                 SYSIO_INTERFACE_RETURN(IOID_FAIL, err);
1276         }
1277         SYSIO_INTERFACE_RETURN(ioctx, 0);
1278 }
1279 #else
1280 #undef iwritex
1281 sysio_sym_weak_alias(PREPEND(_, SYSIO_INTERFACE_NAME(iwritex)),
1282                      SYSIO_INTERFACE_NAME(iwritex))
1283 #endif
1284
1285 #undef writex
1286 ssize_t
1287 SYSIO_INTERFACE_NAME(writex)(int fd,
1288                              const struct iovec *iov, size_t iov_count,
1289                              const struct xtvec *xtv, size_t xtv_count)
1290 {
1291         ioid_t  ioid;
1292
1293         if ((ioid = 
1294              SYSIO_INTERFACE_NAME(iwritex)(fd, 
1295                                            iov, 
1296                                            iov_count, 
1297                                            xtv, 
1298                                            xtv_count)) == IOID_FAIL)
1299                 return -1;
1300         return SYSIO_INTERFACE_NAME(iowait)(ioid);
1301 }
1302
1303 #ifdef _LARGEFILE64_SOURCE
1304 #undef write64x
1305 ssize_t
1306 SYSIO_INTERFACE_NAME(write64x)(int fd,
1307          const struct iovec *iov, size_t iov_count,
1308          const struct xtvec64 *xtv, size_t xtv_count)
1309 {
1310         ioid_t  ioid;
1311
1312         if ((ioid = SYSIO_INTERFACE_NAME(iwrite64x)(fd, 
1313                                                     iov, 
1314                                                     iov_count, 
1315                                                     xtv, 
1316                                                     xtv_count)) == IOID_FAIL)
1317                 return -1;
1318         return SYSIO_INTERFACE_NAME(iowait)(ioid);
1319 }
1320 #endif
1321
1322 #ifdef notdef
1323 int
1324 write_list(int fd,
1325            int mem_list_count,
1326            char *mem_offsets[],
1327            int mem_lengths[],
1328            int file_list_count,
1329            int64_t file_offsets[],
1330            int32_t file_lengths[])
1331 {
1332         SYSIO_INTERFACE_DISPLAY_BLOCK;
1333
1334         SYSIO_INTERFACE_ENTER;
1335         SYSIO_INTERFACE_RETURN(-1, -ENOSYS);
1336 }
1337 #endif