ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/eio.c
(Generate patch)

Comparing libeio/eio.c (file contents):
Revision 1.65 by root, Mon May 30 12:56:50 2011 UTC vs.
Revision 1.71 by root, Fri Jun 10 12:35:18 2011 UTC

58#include <sys/statvfs.h> 58#include <sys/statvfs.h>
59#include <limits.h> 59#include <limits.h>
60#include <fcntl.h> 60#include <fcntl.h>
61#include <assert.h> 61#include <assert.h>
62 62
63/* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */
64/* intptr_t only comes form stdint.h, says idiot openbsd coder */
65#if HAVE_STDINT_H
66# include <stdint.h>
67#endif
68
63#ifndef EIO_FINISH 69#ifndef EIO_FINISH
64# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 70# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
65#endif 71#endif
66 72
67#ifndef EIO_DESTROY 73#ifndef EIO_DESTROY
936 942
937/* sendfile always needs emulation */ 943/* sendfile always needs emulation */
938static ssize_t 944static ssize_t
939eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self) 945eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self)
940{ 946{
947 ssize_t written = 0;
941 ssize_t res; 948 ssize_t res;
942 949
943 if (!count) 950 if (!count)
944 return 0; 951 return 0;
945 952
953 for (;;)
954 {
946#if HAVE_SENDFILE 955#if HAVE_SENDFILE
947# if __linux 956# if __linux
957 off_t soffset = offset;
948 res = sendfile (ofd, ifd, &offset, count); 958 res = sendfile (ofd, ifd, &soffset, count);
949 959
950# elif __FreeBSD__ 960# elif __FreeBSD__
951 /* 961 /*
952 * Of course, the freebsd sendfile is a dire hack with no thoughts 962 * Of course, the freebsd sendfile is a dire hack with no thoughts
953 * wasted on making it similar to other I/O functions. 963 * wasted on making it similar to other I/O functions.
954 */ 964 */
955 {
956 off_t sbytes; 965 off_t sbytes;
957 res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0); 966 res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0);
958 967
959 #if 0 /* according to the manpage, this is correct, but broken behaviour */ 968 #if 0 /* according to the manpage, this is correct, but broken behaviour */
960 /* freebsd' sendfile will return 0 on success */ 969 /* freebsd' sendfile will return 0 on success */
961 /* freebsd 8 documents it as only setting *sbytes on EINTR and EAGAIN, but */ 970 /* freebsd 8 documents it as only setting *sbytes on EINTR and EAGAIN, but */
962 /* not on e.g. EIO or EPIPE - sounds broken */ 971 /* not on e.g. EIO or EPIPE - sounds broken */
963 if ((res < 0 && (errno == EAGAIN || errno == EINTR) && sbytes) || res == 0) 972 if ((res < 0 && (errno == EAGAIN || errno == EINTR) && sbytes) || res == 0)
964 res = sbytes; 973 res = sbytes;
965 #endif 974 #endif
966 975
967 /* according to source inspection, this is correct, and useful behaviour */ 976 /* according to source inspection, this is correct, and useful behaviour */
968 if (sbytes) 977 if (sbytes)
969 res = sbytes; 978 res = sbytes;
970 }
971 979
972# elif defined (__APPLE__) 980# elif defined (__APPLE__)
973
974 {
975 off_t sbytes = count; 981 off_t sbytes = count;
976 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0); 982 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0);
977 983
978 /* according to the manpage, sbytes is always valid */ 984 /* according to the manpage, sbytes is always valid */
979 if (sbytes) 985 if (sbytes)
980 res = sbytes; 986 res = sbytes;
981 }
982 987
983# elif __hpux 988# elif __hpux
984 res = sendfile (ofd, ifd, offset, count, 0, 0); 989 res = sendfile (ofd, ifd, offset, count, 0, 0);
985 990
986# elif __solaris 991# elif __solaris
987 {
988 struct sendfilevec vec; 992 struct sendfilevec vec;
989 size_t sbytes; 993 size_t sbytes;
990 994
991 vec.sfv_fd = ifd; 995 vec.sfv_fd = ifd;
992 vec.sfv_flag = 0; 996 vec.sfv_flag = 0;
993 vec.sfv_off = offset; 997 vec.sfv_off = offset;
994 vec.sfv_len = count; 998 vec.sfv_len = count;
995 999
996 res = sendfilev (ofd, &vec, 1, &sbytes); 1000 res = sendfilev (ofd, &vec, 1, &sbytes);
997 1001
998 if (res < 0 && sbytes) 1002 if (res < 0 && sbytes)
999 res = sbytes; 1003 res = sbytes;
1000 }
1001 1004
1002# endif 1005# endif
1003 1006
1004#elif defined (_WIN32) 1007#elif defined (_WIN32)
1005
1006 /* does not work, just for documentation of what would need to be done */ 1008 /* does not work, just for documentation of what would need to be done */
1007 { 1009 /* actually, cannot be done like this, as TransmitFile changes the file offset, */
1010 /* libeio guarantees that the file offset does not change, and windows */
1011 /* has no way to get an independent handle to the same file description */
1008 HANDLE h = TO_SOCKET (ifd); 1012 HANDLE h = TO_SOCKET (ifd);
1009 SetFilePointer (h, offset, 0, FILE_BEGIN); 1013 SetFilePointer (h, offset, 0, FILE_BEGIN);
1010 res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0); 1014 res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0);
1011 }
1012 1015
1013#else 1016#else
1014 res = -1; 1017 res = -1;
1015 errno = ENOSYS; 1018 errno = ENOSYS;
1016#endif 1019#endif
1017 1020
1021 /* we assume sendfile can copy at least 128mb in one go */
1022 if (res <= 128 * 1024 * 1024)
1023 {
1024 if (res > 0)
1025 written += res;
1026
1027 if (written)
1028 return written;
1029
1030 break;
1031 }
1032 else
1033 {
1034 /* if we requested more, then probably the kernel was lazy */
1035 written += res;
1036 offset += res;
1037 count -= res;
1038
1039 if (!count)
1040 return written;
1041 }
1042 }
1043
1018 if (res < 0 1044 if (res < 0
1019 && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK 1045 && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK
1020 /* BSDs */ 1046 /* BSDs */
1021#ifdef ENOTSUP /* sigh, if the steenking pile called openbsd would only try to at least compile posix code... */ 1047#ifdef ENOTSUP /* sigh, if the steenking pile called openbsd would only try to at least compile posix code... */
1022 || errno == ENOTSUP 1048 || errno == ENOTSUP
1023#endif 1049#endif
1517} 1543}
1518 1544
1519#endif 1545#endif
1520 1546
1521int 1547int
1522eio__mtouch (void *mem, size_t len, int flags) 1548eio__mtouch (eio_req *req)
1523{ 1549{
1550 void *mem = req->ptr2;
1551 size_t len = req->size;
1552 int flags = req->int1;
1553
1524 eio_page_align (&mem, &len); 1554 eio_page_align (&mem, &len);
1525 1555
1526 { 1556 {
1527 intptr_t addr = (intptr_t)mem; 1557 intptr_t addr = (intptr_t)mem;
1528 intptr_t end = addr + len; 1558 intptr_t end = addr + len;
1529 intptr_t page = eio_pagesize (); 1559 intptr_t page = eio_pagesize ();
1530 1560
1531 if (addr < end) 1561 if (addr < end)
1532 if (flags & EIO_MT_MODIFY) /* modify */ 1562 if (flags & EIO_MT_MODIFY) /* modify */
1533 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len); 1563 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1534 else 1564 else
1535 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len); 1565 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1536 } 1566 }
1537 1567
1538 return 0; 1568 return 0;
1539} 1569}
1540 1570
1714 1744
1715 case EIO_SYNC: req->result = 0; sync (); break; 1745 case EIO_SYNC: req->result = 0; sync (); break;
1716 case EIO_FSYNC: req->result = fsync (req->int1); break; 1746 case EIO_FSYNC: req->result = fsync (req->int1); break;
1717 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; 1747 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
1718 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break; 1748 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break;
1719 case EIO_MTOUCH: req->result = eio__mtouch (req->ptr2, req->size, req->int1); break; 1749 case EIO_MTOUCH: req->result = eio__mtouch (req); break;
1720 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break; 1750 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
1721 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break; 1751 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
1722 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break; 1752 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
1723 1753
1724 case EIO_READDIR: eio__scandir (req, self); break; 1754 case EIO_READDIR: eio__scandir (req, self); break;
1768 case EIO_NOP: 1798 case EIO_NOP:
1769 req->result = 0; 1799 req->result = 0;
1770 break; 1800 break;
1771 1801
1772 case EIO_CUSTOM: 1802 case EIO_CUSTOM:
1773 ((void (*)(eio_req *))req->feed) (req); 1803 req->feed (req);
1774 break; 1804 break;
1775 1805
1776 default: 1806 default:
1777 errno = ENOSYS; 1807 errno = ENOSYS;
1778 req->result = -1; 1808 req->result = -1;
1999eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data) 2029eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2000{ 2030{
2001 return eio__2path (EIO_RENAME, path, new_path, pri, cb, data); 2031 return eio__2path (EIO_RENAME, path, new_path, pri, cb, data);
2002} 2032}
2003 2033
2004eio_req *eio_custom (eio_cb execute, int pri, eio_cb cb, void *data) 2034eio_req *eio_custom (void (*execute)(eio_req *), int pri, eio_cb cb, void *data)
2005{ 2035{
2006 REQ (EIO_CUSTOM); req->feed = (void (*)(eio_req *))execute; SEND; 2036 REQ (EIO_CUSTOM); req->feed = execute; SEND;
2007} 2037}
2008 2038
2009#endif 2039#endif
2010 2040
2011eio_req *eio_grp (eio_cb cb, void *data) 2041eio_req *eio_grp (eio_cb cb, void *data)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines