… | |
… | |
60 | #include <limits.h> |
60 | #include <limits.h> |
61 | #include <fcntl.h> |
61 | #include <fcntl.h> |
62 | #include <assert.h> |
62 | #include <assert.h> |
63 | |
63 | |
64 | /* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */ |
64 | /* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */ |
65 | /* intptr_t only comes form stdint.h, says idiot openbsd coder */ |
65 | /* intptr_t only comes from stdint.h, says idiot openbsd coder */ |
66 | #if HAVE_STDINT_H |
66 | #if HAVE_STDINT_H |
67 | # include <stdint.h> |
67 | # include <stdint.h> |
68 | #endif |
68 | #endif |
|
|
69 | |
|
|
70 | #ifndef ECANCELED |
|
|
71 | # define ECANCELED EDOM |
|
|
72 | #endif |
|
|
73 | |
|
|
74 | static void eio_destroy (eio_req *req); |
69 | |
75 | |
70 | #ifndef EIO_FINISH |
76 | #ifndef EIO_FINISH |
71 | # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 |
77 | # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 |
72 | #endif |
78 | #endif |
73 | |
79 | |
… | |
… | |
200 | /*****************************************************************************/ |
206 | /*****************************************************************************/ |
201 | |
207 | |
202 | #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) |
208 | #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) |
203 | |
209 | |
204 | /* calculate time difference in ~1/EIO_TICKS of a second */ |
210 | /* calculate time difference in ~1/EIO_TICKS of a second */ |
205 | ECB_INLINE int |
211 | ecb_inline int |
206 | tvdiff (struct timeval *tv1, struct timeval *tv2) |
212 | tvdiff (struct timeval *tv1, struct timeval *tv2) |
207 | { |
213 | { |
208 | return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS |
214 | return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS |
209 | + ((tv2->tv_usec - tv1->tv_usec) >> 10); |
215 | + ((tv2->tv_usec - tv1->tv_usec) >> 10); |
210 | } |
216 | } |
… | |
… | |
583 | } |
589 | } |
584 | |
590 | |
585 | static void |
591 | static void |
586 | etp_cancel (ETP_REQ *req) |
592 | etp_cancel (ETP_REQ *req) |
587 | { |
593 | { |
588 | X_LOCK (wrklock); |
594 | req->cancelled = 1; |
589 | req->flags |= EIO_FLAG_CANCELLED; |
|
|
590 | X_UNLOCK (wrklock); |
|
|
591 | |
595 | |
592 | eio_grp_cancel (req); |
596 | eio_grp_cancel (req); |
593 | } |
597 | } |
594 | |
598 | |
595 | static void |
599 | static void |
… | |
… | |
711 | return eio_finish (grp); |
715 | return eio_finish (grp); |
712 | else |
716 | else |
713 | return 0; |
717 | return 0; |
714 | } |
718 | } |
715 | |
719 | |
716 | void |
720 | static void |
717 | eio_destroy (eio_req *req) |
721 | eio_destroy (eio_req *req) |
718 | { |
722 | { |
719 | if ((req)->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1); |
723 | if ((req)->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1); |
720 | if ((req)->flags & EIO_FLAG_PTR2_FREE) free (req->ptr2); |
724 | if ((req)->flags & EIO_FLAG_PTR2_FREE) free (req->ptr2); |
721 | |
725 | |
… | |
… | |
739 | if (grp->grp_first == req) |
743 | if (grp->grp_first == req) |
740 | grp->grp_first = req->grp_next; |
744 | grp->grp_first = req->grp_next; |
741 | |
745 | |
742 | res2 = grp_dec (grp); |
746 | res2 = grp_dec (grp); |
743 | |
747 | |
744 | if (!res && res2) |
748 | if (!res) |
745 | res = res2; |
749 | res = res2; |
746 | } |
750 | } |
747 | |
751 | |
748 | eio_destroy (req); |
752 | eio_destroy (req); |
749 | |
753 | |
… | |
… | |
981 | if (!count) |
985 | if (!count) |
982 | return 0; |
986 | return 0; |
983 | |
987 | |
984 | for (;;) |
988 | for (;;) |
985 | { |
989 | { |
|
|
990 | #ifdef __APPLE__ |
|
|
991 | # undef HAVE_SENDFILE /* broken, as everything on os x */ |
|
|
992 | #endif |
986 | #if HAVE_SENDFILE |
993 | #if HAVE_SENDFILE |
987 | # if __linux |
994 | # if __linux |
988 | off_t soffset = offset; |
995 | off_t soffset = offset; |
989 | res = sendfile (ofd, ifd, &soffset, count); |
996 | res = sendfile (ofd, ifd, &soffset, count); |
990 | |
997 | |
… | |
… | |
1115 | count -= cnt; |
1122 | count -= cnt; |
1116 | } |
1123 | } |
1117 | } |
1124 | } |
1118 | |
1125 | |
1119 | return res; |
1126 | return res; |
|
|
1127 | } |
|
|
1128 | |
|
|
1129 | #ifdef PAGESIZE |
|
|
1130 | # define eio_pagesize() PAGESIZE |
|
|
1131 | #else |
|
|
1132 | static intptr_t |
|
|
1133 | eio_pagesize (void) |
|
|
1134 | { |
|
|
1135 | static intptr_t page; |
|
|
1136 | |
|
|
1137 | if (!page) |
|
|
1138 | page = sysconf (_SC_PAGESIZE); |
|
|
1139 | |
|
|
1140 | return page; |
|
|
1141 | } |
|
|
1142 | #endif |
|
|
1143 | |
|
|
1144 | static void |
|
|
1145 | eio_page_align (void **addr, size_t *length) |
|
|
1146 | { |
|
|
1147 | intptr_t mask = eio_pagesize () - 1; |
|
|
1148 | |
|
|
1149 | /* round down addr */ |
|
|
1150 | intptr_t adj = mask & (intptr_t)*addr; |
|
|
1151 | |
|
|
1152 | *addr = (void *)((intptr_t)*addr - adj); |
|
|
1153 | *length += adj; |
|
|
1154 | |
|
|
1155 | /* round up length */ |
|
|
1156 | *length = (*length + mask) & ~mask; |
|
|
1157 | } |
|
|
1158 | |
|
|
1159 | #if !_POSIX_MEMLOCK |
|
|
1160 | # define eio__mlockall(a) ((errno = ENOSYS), -1) |
|
|
1161 | #else |
|
|
1162 | |
|
|
1163 | static int |
|
|
1164 | eio__mlockall (int flags) |
|
|
1165 | { |
|
|
1166 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
|
|
1167 | extern int mallopt (int, int); |
|
|
1168 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
|
|
1169 | #endif |
|
|
1170 | |
|
|
1171 | if (EIO_MCL_CURRENT != MCL_CURRENT |
|
|
1172 | || EIO_MCL_FUTURE != MCL_FUTURE) |
|
|
1173 | { |
|
|
1174 | flags = 0 |
|
|
1175 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
|
|
1176 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0); |
|
|
1177 | } |
|
|
1178 | |
|
|
1179 | return mlockall (flags); |
|
|
1180 | } |
|
|
1181 | #endif |
|
|
1182 | |
|
|
1183 | #if !_POSIX_MEMLOCK_RANGE |
|
|
1184 | # define eio__mlock(a,b) ((errno = ENOSYS), -1) |
|
|
1185 | #else |
|
|
1186 | |
|
|
1187 | static int |
|
|
1188 | eio__mlock (void *addr, size_t length) |
|
|
1189 | { |
|
|
1190 | eio_page_align (&addr, &length); |
|
|
1191 | |
|
|
1192 | return mlock (addr, length); |
|
|
1193 | } |
|
|
1194 | |
|
|
1195 | #endif |
|
|
1196 | |
|
|
1197 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
|
|
1198 | # define eio__msync(a,b,c) ((errno = ENOSYS), -1) |
|
|
1199 | #else |
|
|
1200 | |
|
|
1201 | static int |
|
|
1202 | eio__msync (void *mem, size_t len, int flags) |
|
|
1203 | { |
|
|
1204 | eio_page_align (&mem, &len); |
|
|
1205 | |
|
|
1206 | if (EIO_MS_ASYNC != MS_SYNC |
|
|
1207 | || EIO_MS_INVALIDATE != MS_INVALIDATE |
|
|
1208 | || EIO_MS_SYNC != MS_SYNC) |
|
|
1209 | { |
|
|
1210 | flags = 0 |
|
|
1211 | | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0) |
|
|
1212 | | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0) |
|
|
1213 | | (flags & EIO_MS_SYNC ? MS_SYNC : 0); |
|
|
1214 | } |
|
|
1215 | |
|
|
1216 | return msync (mem, len, flags); |
|
|
1217 | } |
|
|
1218 | |
|
|
1219 | #endif |
|
|
1220 | |
|
|
1221 | static int |
|
|
1222 | eio__mtouch (eio_req *req) |
|
|
1223 | { |
|
|
1224 | void *mem = req->ptr2; |
|
|
1225 | size_t len = req->size; |
|
|
1226 | int flags = req->int1; |
|
|
1227 | |
|
|
1228 | eio_page_align (&mem, &len); |
|
|
1229 | |
|
|
1230 | { |
|
|
1231 | intptr_t addr = (intptr_t)mem; |
|
|
1232 | intptr_t end = addr + len; |
|
|
1233 | intptr_t page = eio_pagesize (); |
|
|
1234 | |
|
|
1235 | if (addr < end) |
|
|
1236 | if (flags & EIO_MT_MODIFY) /* modify */ |
|
|
1237 | do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1238 | else |
|
|
1239 | do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1240 | } |
|
|
1241 | |
|
|
1242 | return 0; |
|
|
1243 | } |
|
|
1244 | |
|
|
1245 | /*****************************************************************************/ |
|
|
1246 | /* requests implemented outside eio_execute, because they are so large */ |
|
|
1247 | |
|
|
1248 | static void |
|
|
1249 | eio__realpath (eio_req *req, etp_worker *self) |
|
|
1250 | { |
|
|
1251 | char *rel = req->ptr1; |
|
|
1252 | char *res; |
|
|
1253 | char *tmp1, *tmp2; |
|
|
1254 | #if SYMLOOP_MAX > 32 |
|
|
1255 | int symlinks = SYMLOOP_MAX; |
|
|
1256 | #else |
|
|
1257 | int symlinks = 32; |
|
|
1258 | #endif |
|
|
1259 | |
|
|
1260 | req->result = -1; |
|
|
1261 | |
|
|
1262 | errno = EINVAL; |
|
|
1263 | if (!rel) |
|
|
1264 | return; |
|
|
1265 | |
|
|
1266 | errno = ENOENT; |
|
|
1267 | if (!*rel) |
|
|
1268 | return; |
|
|
1269 | |
|
|
1270 | if (!req->ptr2) |
|
|
1271 | { |
|
|
1272 | X_LOCK (wrklock); |
|
|
1273 | req->flags |= EIO_FLAG_PTR2_FREE; |
|
|
1274 | X_UNLOCK (wrklock); |
|
|
1275 | req->ptr2 = malloc (PATH_MAX * 3); |
|
|
1276 | |
|
|
1277 | errno = ENOMEM; |
|
|
1278 | if (!req->ptr2) |
|
|
1279 | return; |
|
|
1280 | } |
|
|
1281 | |
|
|
1282 | res = req->ptr2; |
|
|
1283 | tmp1 = res + PATH_MAX; |
|
|
1284 | tmp2 = tmp1 + PATH_MAX; |
|
|
1285 | |
|
|
1286 | #if 0 /* disabled, the musl way to do things is just too racy */ |
|
|
1287 | #if __linux && defined(O_NONBLOCK) && defined(O_NOATIME) |
|
|
1288 | /* on linux we may be able to ask the kernel */ |
|
|
1289 | { |
|
|
1290 | int fd = open (rel, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOATIME); |
|
|
1291 | |
|
|
1292 | if (fd >= 0) |
|
|
1293 | { |
|
|
1294 | sprintf (tmp1, "/proc/self/fd/%d", fd); |
|
|
1295 | req->result = readlink (tmp1, res, PATH_MAX); |
|
|
1296 | close (fd); |
|
|
1297 | |
|
|
1298 | /* here we should probably stat the open file and the disk file, to make sure they still match */ |
|
|
1299 | |
|
|
1300 | if (req->result > 0) |
|
|
1301 | goto done; |
|
|
1302 | } |
|
|
1303 | else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO) |
|
|
1304 | return; |
|
|
1305 | } |
|
|
1306 | #endif |
|
|
1307 | #endif |
|
|
1308 | |
|
|
1309 | if (*rel != '/') |
|
|
1310 | { |
|
|
1311 | if (!getcwd (res, PATH_MAX)) |
|
|
1312 | return; |
|
|
1313 | |
|
|
1314 | if (res [1]) /* only use if not / */ |
|
|
1315 | res += strlen (res); |
|
|
1316 | } |
|
|
1317 | |
|
|
1318 | while (*rel) |
|
|
1319 | { |
|
|
1320 | ssize_t len, linklen; |
|
|
1321 | char *beg = rel; |
|
|
1322 | |
|
|
1323 | while (*rel && *rel != '/') |
|
|
1324 | ++rel; |
|
|
1325 | |
|
|
1326 | len = rel - beg; |
|
|
1327 | |
|
|
1328 | if (!len) /* skip slashes */ |
|
|
1329 | { |
|
|
1330 | ++rel; |
|
|
1331 | continue; |
|
|
1332 | } |
|
|
1333 | |
|
|
1334 | if (beg [0] == '.') |
|
|
1335 | { |
|
|
1336 | if (len == 1) |
|
|
1337 | continue; /* . - nop */ |
|
|
1338 | |
|
|
1339 | if (beg [1] == '.' && len == 2) |
|
|
1340 | { |
|
|
1341 | /* .. - back up one component, if possible */ |
|
|
1342 | |
|
|
1343 | while (res != req->ptr2) |
|
|
1344 | if (*--res == '/') |
|
|
1345 | break; |
|
|
1346 | |
|
|
1347 | continue; |
|
|
1348 | } |
|
|
1349 | } |
|
|
1350 | |
|
|
1351 | errno = ENAMETOOLONG; |
|
|
1352 | if (res + 1 + len + 1 >= tmp1) |
|
|
1353 | return; |
|
|
1354 | |
|
|
1355 | /* copy one component */ |
|
|
1356 | *res = '/'; |
|
|
1357 | memcpy (res + 1, beg, len); |
|
|
1358 | |
|
|
1359 | /* zero-terminate, for readlink */ |
|
|
1360 | res [len + 1] = 0; |
|
|
1361 | |
|
|
1362 | /* now check if it's a symlink */ |
|
|
1363 | linklen = readlink (req->ptr2, tmp1, PATH_MAX); |
|
|
1364 | |
|
|
1365 | if (linklen < 0) |
|
|
1366 | { |
|
|
1367 | if (errno != EINVAL) |
|
|
1368 | return; |
|
|
1369 | |
|
|
1370 | /* it's a normal directory. hopefully */ |
|
|
1371 | res += len + 1; |
|
|
1372 | } |
|
|
1373 | else |
|
|
1374 | { |
|
|
1375 | /* yay, it was a symlink - build new path in tmp2 */ |
|
|
1376 | int rellen = strlen (rel); |
|
|
1377 | |
|
|
1378 | errno = ENAMETOOLONG; |
|
|
1379 | if (linklen + 1 + rellen >= PATH_MAX) |
|
|
1380 | return; |
|
|
1381 | |
|
|
1382 | errno = ELOOP; |
|
|
1383 | if (!--symlinks) |
|
|
1384 | return; |
|
|
1385 | |
|
|
1386 | if (*tmp1 == '/') |
|
|
1387 | res = req->ptr2; /* symlink resolves to an absolute path */ |
|
|
1388 | |
|
|
1389 | /* we need to be careful, as rel might point into tmp2 already */ |
|
|
1390 | memmove (tmp2 + linklen + 1, rel, rellen + 1); |
|
|
1391 | tmp2 [linklen] = '/'; |
|
|
1392 | memcpy (tmp2, tmp1, linklen); |
|
|
1393 | |
|
|
1394 | rel = tmp2; |
|
|
1395 | } |
|
|
1396 | } |
|
|
1397 | |
|
|
1398 | /* special case for the lone root path */ |
|
|
1399 | if (res == req->ptr2) |
|
|
1400 | *res++ = '/'; |
|
|
1401 | |
|
|
1402 | req->result = res - (char *)req->ptr2; |
|
|
1403 | |
|
|
1404 | done: |
|
|
1405 | req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */ |
1120 | } |
1406 | } |
1121 | |
1407 | |
1122 | static signed char |
1408 | static signed char |
1123 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |
1409 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |
1124 | { |
1410 | { |
… | |
… | |
1305 | flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); |
1591 | flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); |
1306 | |
1592 | |
1307 | X_LOCK (wrklock); |
1593 | X_LOCK (wrklock); |
1308 | /* the corresponding closedir is in ETP_WORKER_CLEAR */ |
1594 | /* the corresponding closedir is in ETP_WORKER_CLEAR */ |
1309 | self->dirp = dirp = opendir (req->ptr1); |
1595 | self->dirp = dirp = opendir (req->ptr1); |
|
|
1596 | |
|
|
1597 | if (req->flags & EIO_FLAG_PTR1_FREE) |
|
|
1598 | free (req->ptr1); |
1310 | |
1599 | |
1311 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1600 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1312 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1601 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1313 | req->ptr2 = names = malloc (namesalloc); |
1602 | req->ptr2 = names = malloc (namesalloc); |
1314 | X_UNLOCK (wrklock); |
1603 | X_UNLOCK (wrklock); |
… | |
… | |
1481 | break; |
1770 | break; |
1482 | } |
1771 | } |
1483 | } |
1772 | } |
1484 | } |
1773 | } |
1485 | |
1774 | |
1486 | #ifdef PAGESIZE |
|
|
1487 | # define eio_pagesize() PAGESIZE |
|
|
1488 | #else |
|
|
1489 | static intptr_t |
|
|
1490 | eio_pagesize (void) |
|
|
1491 | { |
|
|
1492 | static intptr_t page; |
|
|
1493 | |
|
|
1494 | if (!page) |
|
|
1495 | page = sysconf (_SC_PAGESIZE); |
|
|
1496 | |
|
|
1497 | return page; |
|
|
1498 | } |
|
|
1499 | #endif |
|
|
1500 | |
|
|
1501 | static void |
|
|
1502 | eio_page_align (void **addr, size_t *length) |
|
|
1503 | { |
|
|
1504 | intptr_t mask = eio_pagesize () - 1; |
|
|
1505 | |
|
|
1506 | /* round down addr */ |
|
|
1507 | intptr_t adj = mask & (intptr_t)*addr; |
|
|
1508 | |
|
|
1509 | *addr = (void *)((intptr_t)*addr - adj); |
|
|
1510 | *length += adj; |
|
|
1511 | |
|
|
1512 | /* round up length */ |
|
|
1513 | *length = (*length + mask) & ~mask; |
|
|
1514 | } |
|
|
1515 | |
|
|
1516 | #if !_POSIX_MEMLOCK |
|
|
1517 | # define eio__mlockall(a) ((errno = ENOSYS), -1) |
|
|
1518 | #else |
|
|
1519 | |
|
|
1520 | static int |
|
|
1521 | eio__mlockall (int flags) |
|
|
1522 | { |
|
|
1523 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
|
|
1524 | extern int mallopt (int, int); |
|
|
1525 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
|
|
1526 | #endif |
|
|
1527 | |
|
|
1528 | if (EIO_MCL_CURRENT != MCL_CURRENT |
|
|
1529 | || EIO_MCL_FUTURE != MCL_FUTURE) |
|
|
1530 | { |
|
|
1531 | flags = 0 |
|
|
1532 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
|
|
1533 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0); |
|
|
1534 | } |
|
|
1535 | |
|
|
1536 | return mlockall (flags); |
|
|
1537 | } |
|
|
1538 | #endif |
|
|
1539 | |
|
|
1540 | #if !_POSIX_MEMLOCK_RANGE |
|
|
1541 | # define eio__mlock(a,b) ((errno = ENOSYS), -1) |
|
|
1542 | #else |
|
|
1543 | |
|
|
1544 | static int |
|
|
1545 | eio__mlock (void *addr, size_t length) |
|
|
1546 | { |
|
|
1547 | eio_page_align (&addr, &length); |
|
|
1548 | |
|
|
1549 | return mlock (addr, length); |
|
|
1550 | } |
|
|
1551 | |
|
|
1552 | #endif |
|
|
1553 | |
|
|
1554 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
|
|
1555 | # define eio__msync(a,b,c) ((errno = ENOSYS), -1) |
|
|
1556 | #else |
|
|
1557 | |
|
|
1558 | static int |
|
|
1559 | eio__msync (void *mem, size_t len, int flags) |
|
|
1560 | { |
|
|
1561 | eio_page_align (&mem, &len); |
|
|
1562 | |
|
|
1563 | if (EIO_MS_ASYNC != MS_SYNC |
|
|
1564 | || EIO_MS_INVALIDATE != MS_INVALIDATE |
|
|
1565 | || EIO_MS_SYNC != MS_SYNC) |
|
|
1566 | { |
|
|
1567 | flags = 0 |
|
|
1568 | | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0) |
|
|
1569 | | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0) |
|
|
1570 | | (flags & EIO_MS_SYNC ? MS_SYNC : 0); |
|
|
1571 | } |
|
|
1572 | |
|
|
1573 | return msync (mem, len, flags); |
|
|
1574 | } |
|
|
1575 | |
|
|
1576 | #endif |
|
|
1577 | |
|
|
1578 | static int |
|
|
1579 | eio__mtouch (eio_req *req) |
|
|
1580 | { |
|
|
1581 | void *mem = req->ptr2; |
|
|
1582 | size_t len = req->size; |
|
|
1583 | int flags = req->int1; |
|
|
1584 | |
|
|
1585 | eio_page_align (&mem, &len); |
|
|
1586 | |
|
|
1587 | { |
|
|
1588 | intptr_t addr = (intptr_t)mem; |
|
|
1589 | intptr_t end = addr + len; |
|
|
1590 | intptr_t page = eio_pagesize (); |
|
|
1591 | |
|
|
1592 | if (addr < end) |
|
|
1593 | if (flags & EIO_MT_MODIFY) /* modify */ |
|
|
1594 | do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1595 | else |
|
|
1596 | do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1597 | } |
|
|
1598 | |
|
|
1599 | return 0; |
|
|
1600 | } |
|
|
1601 | |
|
|
1602 | /*****************************************************************************/ |
1775 | /*****************************************************************************/ |
1603 | |
1776 | |
1604 | #define ALLOC(len) \ |
1777 | #define ALLOC(len) \ |
1605 | if (!req->ptr2) \ |
1778 | if (!req->ptr2) \ |
1606 | { \ |
1779 | { \ |
… | |
… | |
1663 | X_UNLOCK (reqlock); |
1836 | X_UNLOCK (reqlock); |
1664 | |
1837 | |
1665 | if (req->type < 0) |
1838 | if (req->type < 0) |
1666 | goto quit; |
1839 | goto quit; |
1667 | |
1840 | |
1668 | if (!EIO_CANCELLED (req)) |
|
|
1669 | ETP_EXECUTE (self, req); |
1841 | ETP_EXECUTE (self, req); |
1670 | |
1842 | |
1671 | X_LOCK (reslock); |
1843 | X_LOCK (reslock); |
1672 | |
1844 | |
1673 | ++npending; |
1845 | ++npending; |
1674 | |
1846 | |
… | |
… | |
1695 | eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
1867 | eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
1696 | { |
1868 | { |
1697 | return etp_init (want_poll, done_poll); |
1869 | return etp_init (want_poll, done_poll); |
1698 | } |
1870 | } |
1699 | |
1871 | |
1700 | ECB_INLINE void |
1872 | ecb_inline void |
1701 | eio_api_destroy (eio_req *req) |
1873 | eio_api_destroy (eio_req *req) |
1702 | { |
1874 | { |
1703 | free (req); |
1875 | free (req); |
1704 | } |
1876 | } |
1705 | |
1877 | |
… | |
… | |
1728 | } |
1900 | } |
1729 | |
1901 | |
1730 | static void |
1902 | static void |
1731 | eio_execute (etp_worker *self, eio_req *req) |
1903 | eio_execute (etp_worker *self, eio_req *req) |
1732 | { |
1904 | { |
|
|
1905 | if (ecb_expect_false (EIO_CANCELLED (req))) |
|
|
1906 | { |
|
|
1907 | req->result = -1; |
|
|
1908 | req->errorno = ECANCELED; |
|
|
1909 | return; |
|
|
1910 | } |
|
|
1911 | |
1733 | switch (req->type) |
1912 | switch (req->type) |
1734 | { |
1913 | { |
1735 | case EIO_READ: ALLOC (req->size); |
1914 | case EIO_READ: ALLOC (req->size); |
1736 | req->result = req->offs >= 0 |
1915 | req->result = req->offs >= 0 |
1737 | ? pread (req->int1, req->ptr2, req->size, req->offs) |
1916 | ? pread (req->int1, req->ptr2, req->size, req->offs) |
… | |
… | |
1771 | case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; |
1950 | case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; |
1772 | case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; |
1951 | case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; |
1773 | case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; |
1952 | case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; |
1774 | case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; |
1953 | case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; |
1775 | |
1954 | |
|
|
1955 | case EIO_REALPATH: eio__realpath (req, self); break; |
|
|
1956 | |
1776 | case EIO_READLINK: ALLOC (PATH_MAX); |
1957 | case EIO_READLINK: ALLOC (PATH_MAX); |
1777 | req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; |
1958 | req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; |
1778 | |
1959 | |
1779 | case EIO_SYNC: req->result = 0; sync (); break; |
1960 | case EIO_SYNC: req->result = 0; sync (); break; |
1780 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
1961 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
… | |
… | |
1997 | eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data) |
2178 | eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data) |
1998 | { |
2179 | { |
1999 | return eio__1path (EIO_READLINK, path, pri, cb, data); |
2180 | return eio__1path (EIO_READLINK, path, pri, cb, data); |
2000 | } |
2181 | } |
2001 | |
2182 | |
|
|
2183 | eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data) |
|
|
2184 | { |
|
|
2185 | return eio__1path (EIO_REALPATH, path, pri, cb, data); |
|
|
2186 | } |
|
|
2187 | |
2002 | eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data) |
2188 | eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data) |
2003 | { |
2189 | { |
2004 | return eio__1path (EIO_STAT, path, pri, cb, data); |
2190 | return eio__1path (EIO_STAT, path, pri, cb, data); |
2005 | } |
2191 | } |
2006 | |
2192 | |