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

Comparing libeio/eio.c (file contents):
Revision 1.93 by root, Mon Jul 18 01:27:03 2011 UTC vs.
Revision 1.103 by root, Thu Sep 15 13:20:54 2011 UTC

43 43
44#include "eio.h" 44#include "eio.h"
45#include "ecb.h" 45#include "ecb.h"
46 46
47#ifdef EIO_STACKSIZE 47#ifdef EIO_STACKSIZE
48# define XTHREAD_STACKSIZE EIO_STACKSIZE 48# define X_STACKSIZE EIO_STACKSIZE
49#endif 49#endif
50#include "xthread.h" 50#include "xthread.h"
51 51
52#include <errno.h> 52#include <errno.h>
53#include <stddef.h> 53#include <stddef.h>
71#endif 71#endif
72#ifndef ELOOP 72#ifndef ELOOP
73# define ELOOP EDOM 73# define ELOOP EDOM
74#endif 74#endif
75 75
76#if !defined(ENOTSOCK) && defined(WSAENOTSOCK)
77# define ENOTSOCK WSAENOTSOCK
78#endif
79
76static void eio_destroy (eio_req *req); 80static void eio_destroy (eio_req *req);
77 81
78#ifndef EIO_FINISH 82#ifndef EIO_FINISH
79# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 83# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
80#endif 84#endif
101#ifdef _WIN32 105#ifdef _WIN32
102 106
103 #undef PAGESIZE 107 #undef PAGESIZE
104 #define PAGESIZE 4096 /* GetSystemInfo? */ 108 #define PAGESIZE 4096 /* GetSystemInfo? */
105 109
110 /* TODO: look at how perl does stat (non-sloppy), unlink (ro-files), utime, link */
111
106 #ifdef EIO_STRUCT_STATI64 112 #ifdef EIO_STRUCT_STATI64
113 /* look at perl's non-sloppy stat */
107 #define stat(path,buf) _stati64 (path,buf) 114 #define stat(path,buf) _stati64 (path,buf)
108 #define fstat(fd,buf) _fstati64 (path,buf) 115 #define fstat(fd,buf) _fstati64 (fd,buf)
109 #endif 116 #endif
110 #define lstat(path,buf) stat (path,buf) 117 #define lstat(path,buf) stat (path,buf)
111 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1)) 118 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
112 #define mkdir(path,mode) _mkdir (path) 119 #define mkdir(path,mode) _mkdir (path)
113 #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1)) 120 #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
125 #define sync() EIO_ENOSYS () 132 #define sync() EIO_ENOSYS ()
126 #define readlink(path,buf,s) EIO_ENOSYS () 133 #define readlink(path,buf,s) EIO_ENOSYS ()
127 #define statvfs(path,buf) EIO_ENOSYS () 134 #define statvfs(path,buf) EIO_ENOSYS ()
128 #define fstatvfs(fd,buf) EIO_ENOSYS () 135 #define fstatvfs(fd,buf) EIO_ENOSYS ()
129 136
137 /* rename() uses MoveFile, which fails to overwrite */
138 #define rename(old,neu) eio__rename (old, neu)
139
140 static int
141 eio__rename (const char *old, const char *neu)
142 {
143 if (MoveFileEx (old, neu, MOVEFILE_REPLACE_EXISTING))
144 return 0;
145
146 /* should steal _dosmaperr */
147 switch (GetLastError ())
148 {
149 case ERROR_FILE_NOT_FOUND:
150 case ERROR_PATH_NOT_FOUND:
151 case ERROR_INVALID_DRIVE:
152 case ERROR_NO_MORE_FILES:
153 case ERROR_BAD_NETPATH:
154 case ERROR_BAD_NET_NAME:
155 case ERROR_BAD_PATHNAME:
156 case ERROR_FILENAME_EXCED_RANGE:
157 errno = ENOENT;
158 break;
159
160 default:
161 errno = EACCES;
162 break;
163 }
164
165 return -1;
166 }
167
130 /* we could even stat and see if it exists */ 168 /* we could even stat and see if it exists */
131 static int 169 static int
132 symlink (const char *old, const char *neu) 170 symlink (const char *old, const char *neu)
133 { 171 {
134 #if WINVER >= 0x0600 172 #if WINVER >= 0x0600
160 198
161 #include <sys/time.h> 199 #include <sys/time.h>
162 #include <sys/select.h> 200 #include <sys/select.h>
163 #include <sys/statvfs.h> 201 #include <sys/statvfs.h>
164 #include <unistd.h> 202 #include <unistd.h>
165 #include <utime.h>
166 #include <signal.h> 203 #include <signal.h>
167 #include <dirent.h> 204 #include <dirent.h>
168 205
169 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES 206 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
170 #include <sys/mman.h> 207 #include <sys/mman.h>
192 229
193 #ifndef EIO_STRUCT_DIRENT 230 #ifndef EIO_STRUCT_DIRENT
194 #define EIO_STRUCT_DIRENT struct dirent 231 #define EIO_STRUCT_DIRENT struct dirent
195 #endif 232 #endif
196 233
234#endif
235
236#if HAVE_UTIMES
237# include <utime.h>
238#endif
239
240#if HAVE_SYS_SYSCALL_H
241# include <sys/syscall.h>
242#endif
243
244#if HAVE_SYS_PRCTL_H
245# include <sys/prctl.h>
197#endif 246#endif
198 247
199#if HAVE_SENDFILE 248#if HAVE_SENDFILE
200# if __linux 249# if __linux
201# include <sys/sendfile.h> 250# include <sys/sendfile.h>
233 282
234/* buffer size for various temporary buffers */ 283/* buffer size for various temporary buffers */
235#define EIO_BUFSIZE 65536 284#define EIO_BUFSIZE 65536
236 285
237#define dBUF \ 286#define dBUF \
238 char *eio_buf; \
239 ETP_WORKER_LOCK (self); \
240 self->dbuf = eio_buf = malloc (EIO_BUFSIZE); \ 287 char *eio_buf = malloc (EIO_BUFSIZE); \
241 ETP_WORKER_UNLOCK (self); \
242 errno = ENOMEM; \ 288 errno = ENOMEM; \
243 if (!eio_buf) \ 289 if (!eio_buf) \
244 return -1; 290 return -1
291
292#define FUBd \
293 free (eio_buf)
245 294
246#define EIO_TICKS ((1000000 + 1023) >> 10) 295#define EIO_TICKS ((1000000 + 1023) >> 10)
247 296
248#define ETP_PRI_MIN EIO_PRI_MIN 297#define ETP_PRI_MIN EIO_PRI_MIN
249#define ETP_PRI_MAX EIO_PRI_MAX 298#define ETP_PRI_MAX EIO_PRI_MAX
255static int eio_finish (eio_req *req); 304static int eio_finish (eio_req *req);
256#define ETP_FINISH(req) eio_finish (req) 305#define ETP_FINISH(req) eio_finish (req)
257static void eio_execute (struct etp_worker *self, eio_req *req); 306static void eio_execute (struct etp_worker *self, eio_req *req);
258#define ETP_EXECUTE(wrk,req) eio_execute (wrk,req) 307#define ETP_EXECUTE(wrk,req) eio_execute (wrk,req)
259 308
260#define ETP_WORKER_CLEAR(req) \
261 if (wrk->dbuf) \
262 { \
263 free (wrk->dbuf); \
264 wrk->dbuf = 0; \
265 }
266
267#define ETP_WORKER_COMMON \
268 void *dbuf;
269
270/*****************************************************************************/ 309/*****************************************************************************/
271 310
272#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) 311#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
273 312
274/* calculate time difference in ~1/EIO_TICKS of a second */ 313/* calculate time difference in ~1/EIO_TICKS of a second */
285static void (*done_poll_cb) (void); 324static void (*done_poll_cb) (void);
286 325
287static unsigned int max_poll_time; /* reslock */ 326static unsigned int max_poll_time; /* reslock */
288static unsigned int max_poll_reqs; /* reslock */ 327static unsigned int max_poll_reqs; /* reslock */
289 328
290static volatile unsigned int nreqs; /* reqlock */ 329static unsigned int nreqs; /* reqlock */
291static volatile unsigned int nready; /* reqlock */ 330static unsigned int nready; /* reqlock */
292static volatile unsigned int npending; /* reqlock */ 331static unsigned int npending; /* reqlock */
293static volatile unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */ 332static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
294static volatile unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */ 333static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
295 334
296static xmutex_t wrklock; 335static xmutex_t wrklock;
297static xmutex_t reslock; 336static xmutex_t reslock;
298static xmutex_t reqlock; 337static xmutex_t reqlock;
299static xcond_t reqwait; 338static xcond_t reqwait;
315 xthread_t tid; 354 xthread_t tid;
316 355
317 /* locked by reslock, reqlock or wrklock */ 356 /* locked by reslock, reqlock or wrklock */
318 ETP_REQ *req; /* currently processed request */ 357 ETP_REQ *req; /* currently processed request */
319 358
359#ifdef ETP_WORKER_COMMON
320 ETP_WORKER_COMMON 360 ETP_WORKER_COMMON
361#endif
321} etp_worker; 362} etp_worker;
322 363
323static etp_worker wrk_first; /* NOT etp */ 364static etp_worker wrk_first; /* NOT etp */
324 365
325#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock) 366#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
328/* worker threads management */ 369/* worker threads management */
329 370
330static void ecb_cold 371static void ecb_cold
331etp_worker_clear (etp_worker *wrk) 372etp_worker_clear (etp_worker *wrk)
332{ 373{
333 ETP_WORKER_CLEAR (wrk);
334} 374}
335 375
336static void ecb_cold 376static void ecb_cold
337etp_worker_free (etp_worker *wrk) 377etp_worker_free (etp_worker *wrk)
338{ 378{
939#if !HAVE_FDATASYNC 979#if !HAVE_FDATASYNC
940# undef fdatasync 980# undef fdatasync
941# define fdatasync(fd) fsync (fd) 981# define fdatasync(fd) fsync (fd)
942#endif 982#endif
943 983
984static int
985eio__syncfs (int fd)
986{
987 int res;
988
989#if HAVE_SYS_SYNCFS
990 res = (int)syscall (__NR_syncfs, (int)(fd));
991#else
992 res = -1;
993 errno = ENOSYS;
994#endif
995
996 if (res < 0 && errno == ENOSYS && fd >= 0)
997 sync ();
998
999 return res;
1000}
1001
944/* sync_file_range always needs emulation */ 1002/* sync_file_range always needs emulation */
945static int 1003static int
946eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags) 1004eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags)
947{ 1005{
948#if HAVE_SYNC_FILE_RANGE 1006#if HAVE_SYNC_FILE_RANGE
997 pread (fd, eio_buf, len, offset); 1055 pread (fd, eio_buf, len, offset);
998 offset += len; 1056 offset += len;
999 todo -= len; 1057 todo -= len;
1000 } 1058 }
1001 1059
1060 FUBd;
1061
1002 errno = 0; 1062 errno = 0;
1003 return count; 1063 return count;
1004} 1064}
1005 1065
1006#endif 1066#endif
1007 1067
1008/* sendfile always needs emulation */ 1068/* sendfile always needs emulation */
1009static eio_ssize_t 1069static eio_ssize_t
1010eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self) 1070eio__sendfile (int ofd, int ifd, off_t offset, size_t count)
1011{ 1071{
1012 eio_ssize_t written = 0; 1072 eio_ssize_t written = 0;
1013 eio_ssize_t res; 1073 eio_ssize_t res;
1014 1074
1015 if (!count) 1075 if (!count)
1151 1211
1152 offset += cnt; 1212 offset += cnt;
1153 res += cnt; 1213 res += cnt;
1154 count -= cnt; 1214 count -= cnt;
1155 } 1215 }
1216
1217 FUBd;
1156 } 1218 }
1157 1219
1158 return res; 1220 return res;
1159} 1221}
1160 1222
1644 dirp = FindFirstFile (path, &entp); 1706 dirp = FindFirstFile (path, &entp);
1645 free (path); 1707 free (path);
1646 1708
1647 if (dirp == INVALID_HANDLE_VALUE) 1709 if (dirp == INVALID_HANDLE_VALUE)
1648 { 1710 {
1649 dirp = 0; 1711 /* should steal _dosmaperr */
1650
1651 switch (GetLastError ()) 1712 switch (GetLastError ())
1652 { 1713 {
1653 case ERROR_FILE_NOT_FOUND: 1714 case ERROR_FILE_NOT_FOUND:
1654 req->result = 0; 1715 req->result = 0;
1655 break; 1716 break;
1656 1717
1657 case ERROR_INVALID_NAME: 1718 case ERROR_INVALID_NAME:
1658 case ERROR_PATH_NOT_FOUND: 1719 case ERROR_PATH_NOT_FOUND:
1659 case ERROR_NO_MORE_FILES: 1720 case ERROR_NO_MORE_FILES:
1660 errno = ENOENT; 1721 errno = ENOENT;
1661 break; 1722 break;
1662 1723
1663 case ERROR_NOT_ENOUGH_MEMORY: 1724 case ERROR_NOT_ENOUGH_MEMORY:
1664 errno = ENOMEM; 1725 errno = ENOMEM;
1665 break; 1726 break;
1666 1727
1667 default: 1728 default:
1668 errno = EINVAL; 1729 errno = EINVAL;
1669 break; 1730 break;
1670 } 1731 }
1732
1733 return;
1671 } 1734 }
1672 } 1735 }
1673#else 1736#else
1674 dirp = opendir (req->ptr1); 1737 dirp = opendir (req->ptr1);
1738
1739 if (!dirp)
1740 return;
1675#endif 1741#endif
1676 1742
1677 if (req->flags & EIO_FLAG_PTR1_FREE) 1743 if (req->flags & EIO_FLAG_PTR1_FREE)
1678 free (req->ptr1); 1744 free (req->ptr1);
1679 1745
1680 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; 1746 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
1681 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; 1747 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
1682 req->ptr2 = names = malloc (namesalloc); 1748 req->ptr2 = names = malloc (namesalloc);
1683 1749
1684 if (dirp && names && (!flags || dents)) 1750 if (!names || (flags && !dents))
1751 return;
1752
1685 for (;;) 1753 for (;;)
1686 { 1754 {
1687 int done; 1755 int done;
1688 1756
1689#ifdef _WIN32 1757#ifdef _WIN32
1690 done = !dirp; 1758 done = !dirp;
1691#else 1759#else
1692 errno = 0; 1760 errno = 0;
1693 entp = readdir (dirp); 1761 entp = readdir (dirp);
1694 done = !entp; 1762 done = !entp;
1695#endif 1763#endif
1696 1764
1697 if (done) 1765 if (done)
1698 { 1766 {
1699#ifndef _WIN32 1767#ifndef _WIN32
1700 int old_errno = errno; 1768 int old_errno = errno;
1701 closedir (dirp); 1769 closedir (dirp);
1702 errno = old_errno; 1770 errno = old_errno;
1703 1771
1704 if (errno) 1772 if (errno)
1705 break; 1773 break;
1706#endif 1774#endif
1707 1775
1708 /* sort etc. */ 1776 /* sort etc. */
1709 req->int1 = flags; 1777 req->int1 = flags;
1710 req->result = dentoffs; 1778 req->result = dentoffs;
1711 1779
1712 if (flags & EIO_READDIR_STAT_ORDER) 1780 if (flags & EIO_READDIR_STAT_ORDER)
1713 eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits); 1781 eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits);
1714 else if (flags & EIO_READDIR_DIRS_FIRST) 1782 else if (flags & EIO_READDIR_DIRS_FIRST)
1715 if (flags & EIO_READDIR_FOUND_UNKNOWN) 1783 if (flags & EIO_READDIR_FOUND_UNKNOWN)
1716 eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */ 1784 eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */
1717 else 1785 else
1786 {
1787 /* in this case, all is known, and we just put dirs first and sort them */
1788 eio_dirent *oth = dents + dentoffs;
1789 eio_dirent *dir = dents;
1790
1791 /* now partition dirs to the front, and non-dirs to the back */
1792 /* by walking from both sides and swapping if necessary */
1793 while (oth > dir)
1794 {
1795 if (dir->type == EIO_DT_DIR)
1796 ++dir;
1797 else if ((--oth)->type == EIO_DT_DIR)
1798 {
1799 eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1800
1801 ++dir;
1802 }
1803 }
1804
1805 /* now sort the dirs only (dirs all have the same score) */
1806 eio_dent_sort (dents, dir - dents, 0, inode_bits);
1807 }
1808
1809 break;
1810 }
1811
1812 /* now add the entry to our list(s) */
1813 name = D_NAME (entp);
1814
1815 /* skip . and .. entries */
1816 if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1817 {
1818 int len = D_NAMLEN (entp) + 1;
1819
1820 while (ecb_expect_false (namesoffs + len > namesalloc))
1821 {
1822 namesalloc *= 2;
1823 req->ptr2 = names = realloc (names, namesalloc);
1824
1825 if (!names)
1826 break;
1827 }
1828
1829 memcpy (names + namesoffs, name, len);
1830
1831 if (dents)
1832 {
1833 struct eio_dirent *ent;
1834
1835 if (ecb_expect_false (dentoffs == dentalloc))
1718 { 1836 {
1719 /* in this case, all is known, and we just put dirs first and sort them */ 1837 dentalloc *= 2;
1838 req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1839
1840 if (!dents)
1841 break;
1842 }
1843
1720 eio_dirent *oth = dents + dentoffs; 1844 ent = dents + dentoffs;
1721 eio_dirent *dir = dents;
1722 1845
1723 /* now partition dirs to the front, and non-dirs to the back */ 1846 ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1724 /* by walking from both sides and swapping if necessary */ 1847 ent->namelen = len - 1;
1725 while (oth > dir) 1848 ent->inode = D_INO (entp);
1849
1850 inode_bits |= ent->inode;
1851
1852 switch (D_TYPE (entp))
1853 {
1854 default:
1855 ent->type = EIO_DT_UNKNOWN;
1856 flags |= EIO_READDIR_FOUND_UNKNOWN;
1857 break;
1858
1859 #ifdef DT_FIFO
1860 case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1861 #endif
1862 #ifdef DT_CHR
1863 case DT_CHR: ent->type = EIO_DT_CHR; break;
1864 #endif
1865 #ifdef DT_MPC
1866 case DT_MPC: ent->type = EIO_DT_MPC; break;
1867 #endif
1868 #ifdef DT_DIR
1869 case DT_DIR: ent->type = EIO_DT_DIR; break;
1870 #endif
1871 #ifdef DT_NAM
1872 case DT_NAM: ent->type = EIO_DT_NAM; break;
1873 #endif
1874 #ifdef DT_BLK
1875 case DT_BLK: ent->type = EIO_DT_BLK; break;
1876 #endif
1877 #ifdef DT_MPB
1878 case DT_MPB: ent->type = EIO_DT_MPB; break;
1879 #endif
1880 #ifdef DT_REG
1881 case DT_REG: ent->type = EIO_DT_REG; break;
1882 #endif
1883 #ifdef DT_NWK
1884 case DT_NWK: ent->type = EIO_DT_NWK; break;
1885 #endif
1886 #ifdef DT_CMP
1887 case DT_CMP: ent->type = EIO_DT_CMP; break;
1888 #endif
1889 #ifdef DT_LNK
1890 case DT_LNK: ent->type = EIO_DT_LNK; break;
1891 #endif
1892 #ifdef DT_SOCK
1893 case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1894 #endif
1895 #ifdef DT_DOOR
1896 case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1897 #endif
1898 #ifdef DT_WHT
1899 case DT_WHT: ent->type = EIO_DT_WHT; break;
1900 #endif
1901 }
1902
1903 ent->score = 7;
1904
1905 if (flags & EIO_READDIR_DIRS_FIRST)
1906 {
1907 if (ent->type == EIO_DT_UNKNOWN)
1726 { 1908 {
1727 if (dir->type == EIO_DT_DIR) 1909 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1728 ++dir; 1910 ent->score = 1;
1729 else if ((--oth)->type == EIO_DT_DIR) 1911 else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1730 { 1912 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1731 eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1732
1733 ++dir;
1734 }
1735 } 1913 }
1736 1914 else if (ent->type == EIO_DT_DIR)
1737 /* now sort the dirs only (dirs all have the same score) */ 1915 ent->score = 0;
1738 eio_dent_sort (dents, dir - dents, 0, inode_bits);
1739 } 1916 }
1740
1741 break;
1742 }
1743
1744 /* now add the entry to our list(s) */
1745 name = D_NAME (entp);
1746
1747 /* skip . and .. entries */
1748 if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1749 {
1750 int len = D_NAMLEN (entp) + 1;
1751
1752 while (ecb_expect_false (namesoffs + len > namesalloc))
1753 {
1754 namesalloc *= 2;
1755 req->ptr2 = names = realloc (names, namesalloc);
1756
1757 if (!names)
1758 break;
1759 } 1917 }
1760 1918
1761 memcpy (names + namesoffs, name, len);
1762
1763 if (dents)
1764 {
1765 struct eio_dirent *ent;
1766
1767 if (ecb_expect_false (dentoffs == dentalloc))
1768 {
1769 dentalloc *= 2;
1770 req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1771
1772 if (!dents)
1773 break;
1774 }
1775
1776 ent = dents + dentoffs;
1777
1778 ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1779 ent->namelen = len - 1;
1780 ent->inode = D_INO (entp);
1781
1782 inode_bits |= ent->inode;
1783
1784 switch (D_TYPE (entp))
1785 {
1786 default:
1787 ent->type = EIO_DT_UNKNOWN;
1788 flags |= EIO_READDIR_FOUND_UNKNOWN;
1789 break;
1790
1791 #ifdef DT_FIFO
1792 case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1793 #endif
1794 #ifdef DT_CHR
1795 case DT_CHR: ent->type = EIO_DT_CHR; break;
1796 #endif
1797 #ifdef DT_MPC
1798 case DT_MPC: ent->type = EIO_DT_MPC; break;
1799 #endif
1800 #ifdef DT_DIR
1801 case DT_DIR: ent->type = EIO_DT_DIR; break;
1802 #endif
1803 #ifdef DT_NAM
1804 case DT_NAM: ent->type = EIO_DT_NAM; break;
1805 #endif
1806 #ifdef DT_BLK
1807 case DT_BLK: ent->type = EIO_DT_BLK; break;
1808 #endif
1809 #ifdef DT_MPB
1810 case DT_MPB: ent->type = EIO_DT_MPB; break;
1811 #endif
1812 #ifdef DT_REG
1813 case DT_REG: ent->type = EIO_DT_REG; break;
1814 #endif
1815 #ifdef DT_NWK
1816 case DT_NWK: ent->type = EIO_DT_NWK; break;
1817 #endif
1818 #ifdef DT_CMP
1819 case DT_CMP: ent->type = EIO_DT_CMP; break;
1820 #endif
1821 #ifdef DT_LNK
1822 case DT_LNK: ent->type = EIO_DT_LNK; break;
1823 #endif
1824 #ifdef DT_SOCK
1825 case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1826 #endif
1827 #ifdef DT_DOOR
1828 case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1829 #endif
1830 #ifdef DT_WHT
1831 case DT_WHT: ent->type = EIO_DT_WHT; break;
1832 #endif
1833 }
1834
1835 ent->score = 7;
1836
1837 if (flags & EIO_READDIR_DIRS_FIRST)
1838 {
1839 if (ent->type == EIO_DT_UNKNOWN)
1840 {
1841 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1842 ent->score = 1;
1843 else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1844 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1845 }
1846 else if (ent->type == EIO_DT_DIR)
1847 ent->score = 0;
1848 }
1849 }
1850
1851 namesoffs += len; 1919 namesoffs += len;
1852 ++dentoffs; 1920 ++dentoffs;
1853 } 1921 }
1854 1922
1855 if (EIO_CANCELLED (req)) 1923 if (EIO_CANCELLED (req))
1856 { 1924 {
1857 errno = ECANCELED; 1925 errno = ECANCELED;
1858 break; 1926 break;
1859 } 1927 }
1860 1928
1861#ifdef _WIN32 1929#ifdef _WIN32
1862 if (!FindNextFile (dirp, &entp)) 1930 if (!FindNextFile (dirp, &entp))
1863 { 1931 {
1864 FindClose (dirp); 1932 FindClose (dirp);
1865 dirp = 0; 1933 dirp = 0;
1866 } 1934 }
1867#endif 1935#endif
1868 } 1936 }
1869} 1937}
1870 1938
1871/*****************************************************************************/ 1939/*****************************************************************************/
1872 1940
1873#define ALLOC(len) \ 1941#define ALLOC(len) \
1889{ 1957{
1890 ETP_REQ *req; 1958 ETP_REQ *req;
1891 struct timespec ts; 1959 struct timespec ts;
1892 etp_worker *self = (etp_worker *)thr_arg; 1960 etp_worker *self = (etp_worker *)thr_arg;
1893 1961
1962#if HAVE_PRCTL_SET_NAME
1963 prctl (PR_SET_NAME, (unsigned long)"eio_thread", 0, 0, 0);
1964#endif
1965
1894 /* try to distribute timeouts somewhat evenly */ 1966 /* try to distribute timeouts somewhat evenly */
1895 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); 1967 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
1896 1968
1897 for (;;) 1969 for (;;)
1898 { 1970 {
2025 case EIO_WRITE: req->result = req->offs >= 0 2097 case EIO_WRITE: req->result = req->offs >= 0
2026 ? pwrite (req->int1, req->ptr2, req->size, req->offs) 2098 ? pwrite (req->int1, req->ptr2, req->size, req->offs)
2027 : write (req->int1, req->ptr2, req->size); break; 2099 : write (req->int1, req->ptr2, req->size); break;
2028 2100
2029 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; 2101 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2030 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size, self); break; 2102 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2031 2103
2032 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2104 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2033 req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break; 2105 req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2034 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2106 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2035 req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break; 2107 req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2065 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; 2137 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
2066 2138
2067 case EIO_SYNC: req->result = 0; sync (); break; 2139 case EIO_SYNC: req->result = 0; sync (); break;
2068 case EIO_FSYNC: req->result = fsync (req->int1); break; 2140 case EIO_FSYNC: req->result = fsync (req->int1); break;
2069 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; 2141 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
2142 case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break;
2143 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2070 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break; 2144 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break;
2071 case EIO_MTOUCH: req->result = eio__mtouch (req); break; 2145 case EIO_MTOUCH: req->result = eio__mtouch (req); break;
2072 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break; 2146 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
2073 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break; 2147 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
2074 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2075 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break; 2148 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;
2076 2149
2077 case EIO_READDIR: eio__scandir (req, self); break; 2150 case EIO_READDIR: eio__scandir (req, self); break;
2078 2151
2079 case EIO_BUSY: 2152 case EIO_BUSY:
2160eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) 2233eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2161{ 2234{
2162 REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; 2235 REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2163} 2236}
2164 2237
2238eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2239{
2240 REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2241}
2242
2243eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data)
2244{
2245 REQ (EIO_SYNCFS); req->int1 = fd; SEND;
2246}
2247
2248eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2249{
2250 REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2251}
2252
2165eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) 2253eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2166{ 2254{
2167 REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; 2255 REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2168} 2256}
2169 2257
2175eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data) 2263eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data)
2176{ 2264{
2177 REQ (EIO_MLOCKALL); req->int1 = flags; SEND; 2265 REQ (EIO_MLOCKALL); req->int1 = flags; SEND;
2178} 2266}
2179 2267
2180eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2181{
2182 REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2183}
2184
2185eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data) 2268eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data)
2186{ 2269{
2187 REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND; 2270 REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND;
2188}
2189
2190eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2191{
2192 REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2193} 2271}
2194 2272
2195eio_req *eio_close (int fd, int pri, eio_cb cb, void *data) 2273eio_req *eio_close (int fd, int pri, eio_cb cb, void *data)
2196{ 2274{
2197 REQ (EIO_CLOSE); req->int1 = fd; SEND; 2275 REQ (EIO_CLOSE); req->int1 = fd; SEND;
2425/* misc garbage */ 2503/* misc garbage */
2426 2504
2427eio_ssize_t 2505eio_ssize_t
2428eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) 2506eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count)
2429{ 2507{
2430 etp_worker wrk;
2431 eio_ssize_t ret;
2432
2433 wrk.dbuf = 0;
2434
2435 ret = eio__sendfile (ofd, ifd, offset, count, &wrk); 2508 return eio__sendfile (ofd, ifd, offset, count);
2436
2437 if (wrk.dbuf)
2438 free (wrk.dbuf);
2439
2440 return ret;
2441} 2509}
2442 2510

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines