PostgreSQL Source Code: src/backend/storage/file/fd.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
74
79#include <sys/stat.h>
80#include <sys/types.h>
81#ifndef WIN32
82#include <sys/mman.h>
83#endif
84#include <limits.h>
86#include <fcntl.h>
87
104
105
106#if defined(HAVE_SYNC_FILE_RANGE)
107#define PG_FLUSH_DATA_WORKS 1
108#elif !defined(WIN32) && defined(MS_ASYNC)
109#define PG_FLUSH_DATA_WORKS 1
110#elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
111#define PG_FLUSH_DATA_WORKS 1
112#endif
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129#define NUM_RESERVED_FDS 10
130
131
132
133
134
135
136
137
138#define FD_MINFREE 48
139
140
141
142
143
144
145
147
148
149
150
151
152
153
154
155
156
157
158
160
161
163
164
166
167
169
170
171
172#ifdef FDDEBUG
173#define DO_DB(A) \
174 do { \
175 int _do_db_save_errno = errno; \
176 A; \
177 errno = _do_db_save_errno; \
178 } while (0)
179#else
180#define DO_DB(A) \
181 ((void) 0)
182#endif
183
184#define VFD_CLOSED (-1)
185
186#define FileIsValid(file) \
187 ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
188
189#define FileIsNotOpen(file) (VfdCache[file].fd == VFD_CLOSED)
190
191
192#define FD_DELETE_AT_CLOSE (1 << 0)
193#define FD_CLOSE_AT_EOXACT (1 << 1)
194#define FD_TEMP_FILE_LIMIT (1 << 2)
195
197{
206
210
211
212
213
214
215
218
219
220
221
223
224
225
226
227
229
230
231
232
233
234
235
237
238
239#ifdef USE_ASSERT_CHECKING
240static bool temporary_files_allowed = false;
241#endif
242
243
244
245
246
247typedef enum
248{
254
255typedef struct
256{
259 union
260 {
266
270
271
272
273
275
276
277
278
279
281
282
283
284
285
286
287
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
333
338
343
344static void walkdir(const char *path,
345 void (*action) (const char *fname, bool isdir, int elevel),
346 bool process_symlinks,
347 int elevel);
348#ifdef PG_FLUSH_DATA_WORKS
349static void pre_sync_fname(const char *fname, bool isdir, int elevel);
350#endif
351static void datadir_fsync_fname(const char *fname, bool isdir, int elevel);
353
355
356
357
360
362{
363 .name = "File",
368};
369
370
371static inline void
373{
375}
376static inline void
378{
380}
381
382
383
384
385int
387{
388#if !defined(WIN32) && defined(USE_ASSERT_CHECKING)
389 struct stat st;
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
411 {
412 int desc_flags = fcntl(fd, F_GETFL);
413
414
415
416
417
419 Assert((desc_flags & (O_RDWR | O_WRONLY)) == 0);
420 else
421 Assert((desc_flags & (O_RDWR | O_WRONLY)) != 0);
422 }
423 errno = 0;
424#endif
425
426
427#if defined(HAVE_FSYNC_WRITETHROUGH)
430 else
431#endif
433}
434
435
436
437
438
439
440int
442{
443 int rc;
444
446 return 0;
447
448retry:
450
451 if (rc == -1 && errno == EINTR)
452 goto retry;
453
454 return rc;
455}
456
457
458
459
460int
462{
464 {
465#if defined(F_FULLFSYNC)
466 return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
467#else
468 errno = ENOSYS;
469 return -1;
470#endif
471 }
472 else
473 return 0;
474}
475
476
477
478
479int
481{
482 int rc;
483
485 return 0;
486
487retry:
489
490 if (rc == -1 && errno == EINTR)
491 goto retry;
492
493 return rc;
494}
495
496
497
498
499
500
501
502bool
504{
505 struct stat st;
506
508
511 else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES))
514 errmsg("could not access file \"%s\": %m", name)));
515
516 return false;
517}
518
519
520
521
522
523
524void
526{
527
528
529
530
531
532
534 return;
535
536
537
538
539
540#if defined(HAVE_SYNC_FILE_RANGE)
541 {
542 int rc;
543 static bool not_implemented_by_kernel = false;
544
545 if (not_implemented_by_kernel)
546 return;
547
548retry:
549
550
551
552
553
554
555
556
557
558
559 rc = sync_file_range(fd, offset, nbytes,
560 SYNC_FILE_RANGE_WRITE);
561 if (rc != 0)
562 {
563 int elevel;
564
566 goto retry;
567
568
569
570
571
572
573 if (errno == ENOSYS)
574 {
576 not_implemented_by_kernel = true;
577 }
578 else
580
583 errmsg("could not flush dirty data: %m")));
584 }
585
586 return;
587 }
588#endif
589#if !defined(WIN32) && defined(MS_ASYNC)
590 {
591 void *p;
592 static int pagesize = 0;
593
594
595
596
597
598
599
600
601
602
603
604
605
606 if (offset == 0 && nbytes == 0)
607 {
608 nbytes = lseek(fd, 0, SEEK_END);
609 if (nbytes < 0)
610 {
613 errmsg("could not determine dirty data size: %m")));
614 return;
615 }
616 }
617
618
619
620
621
622
623
624
625 if (pagesize == 0)
626 pagesize = sysconf(_SC_PAGESIZE);
627
628
629 if (pagesize > 0)
630 nbytes = (nbytes / pagesize) * pagesize;
631
632
633 if (nbytes <= 0)
634 return;
635
636
637
638
639
640
641 if (nbytes <= (off_t) SSIZE_MAX)
642 p = mmap(NULL, nbytes, PROT_READ, MAP_SHARED, fd, offset);
643 else
645
647 {
648 int rc;
649
650 rc = msync(p, (size_t) nbytes, MS_ASYNC);
651 if (rc != 0)
652 {
655 errmsg("could not flush dirty data: %m")));
656
657 }
658
659 rc = munmap(p, (size_t) nbytes);
660 if (rc != 0)
661 {
662
665 errmsg("could not munmap() while flushing data: %m")));
666 }
667
668 return;
669 }
670 }
671#endif
672#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
673 {
674 int rc;
675
676
677
678
679
680
681
682
683
684 rc = posix_fadvise(fd, offset, nbytes, POSIX_FADV_DONTNEED);
685
686 if (rc != 0)
687 {
688
691 errmsg("could not flush dirty data: %m")));
692 }
693
694 return;
695 }
696#endif
697}
698
699
700
701
702static int
704{
705 int ret;
706
707retry:
708 ret = ftruncate(fd, length);
709
710 if (ret == -1 && errno == EINTR)
711 goto retry;
712
713 return ret;
714}
715
716
717
718
719int
721{
722 int ret;
723#ifdef WIN32
724 int save_errno;
725 int fd;
726
728 if (fd >= 0)
729 {
731 save_errno = errno;
733 errno = save_errno;
734 }
735 else
736 ret = -1;
737#else
738
739retry:
740 ret = truncate(path, length);
741
742 if (ret == -1 && errno == EINTR)
743 goto retry;
744#endif
745
746 return ret;
747}
748
749
750
751
752
753
754
755void
757{
759}
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781int
782durable_rename(const char *oldfile, const char *newfile, int elevel)
783{
784 int fd;
785
786
787
788
789
790
791
792
794 return -1;
795
797 if (fd < 0)
798 {
799 if (errno != ENOENT)
800 {
803 errmsg("could not open file \"%s\": %m", newfile)));
804 return -1;
805 }
806 }
807 else
808 {
810 {
811 int save_errno;
812
813
814 save_errno = errno;
816 errno = save_errno;
817
820 errmsg("could not fsync file \"%s\": %m", newfile)));
821 return -1;
822 }
823
825 {
828 errmsg("could not close file \"%s\": %m", newfile)));
829 return -1;
830 }
831 }
832
833
834 if (rename(oldfile, newfile) < 0)
835 {
838 errmsg("could not rename file \"%s\" to \"%s\": %m",
839 oldfile, newfile)));
840 return -1;
841 }
842
843
844
845
846
848 return -1;
849
851 return -1;
852
853 return 0;
854}
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871int
873{
874 if (unlink(fname) < 0)
875 {
878 errmsg("could not remove file \"%s\": %m",
879 fname)));
880 return -1;
881 }
882
883
884
885
886
888 return -1;
889
890 return 0;
891}
892
893
894
895
896
897
898
899
900
901
902void
904{
906
907
911 (errcode(ERRCODE_OUT_OF_MEMORY),
912 errmsg("out of memory")));
913
916
918}
919
920
921
922
923
924
925
926
927
928
929
930
931
932void
934{
936 Assert(!temporary_files_allowed);
937
938
939
940
941
943
944#ifdef USE_ASSERT_CHECKING
945 temporary_files_allowed = true;
946#endif
947}
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963static void
965{
966 int *fd;
967 int size;
968 int used = 0;
969 int highestfd = 0;
970 int j;
971
972#ifdef HAVE_GETRLIMIT
973 struct rlimit rlim;
974 int getrlimit_status;
975#endif
976
977 size = 1024;
978 fd = (int *) palloc(size * sizeof(int));
979
980#ifdef HAVE_GETRLIMIT
981 getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
982 if (getrlimit_status != 0)
984#endif
985
986
987 for (;;)
988 {
989 int thisfd;
990
991#ifdef HAVE_GETRLIMIT
992
993
994
995
996
997 if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
998 break;
999#endif
1000
1001 thisfd = dup(2);
1002 if (thisfd < 0)
1003 {
1004
1005 if (errno != EMFILE && errno != ENFILE)
1006 elog(WARNING, "duplicating stderr file descriptor failed after %d successes: %m", used);
1007 break;
1008 }
1009
1010 if (used >= size)
1011 {
1012 size *= 2;
1013 fd = (int *) repalloc(fd, size * sizeof(int));
1014 }
1015 fd[used++] = thisfd;
1016
1017 if (highestfd < thisfd)
1018 highestfd = thisfd;
1019
1020 if (used >= max_to_probe)
1021 break;
1022 }
1023
1024
1025 for (j = 0; j < used; j++)
1027
1029
1030
1031
1032
1033
1034
1035 *usable_fds = used;
1036 *already_open = highestfd + 1 - used;
1037}
1038
1039
1040
1041
1042
1043void
1045{
1046 int usable_fds;
1047 int already_open;
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1059 &usable_fds, &already_open);
1060
1062
1063
1064
1065
1067
1068
1069
1070
1073 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1074 errmsg("insufficient file descriptors available to start server process"),
1075 errdetail("System allows %d, server needs at least %d, %d files are already open.",
1078 already_open)));
1079
1080 elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
1082}
1083
1084
1085
1086
1087
1088int
1090{
1092}
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110int
1112{
1113 int fd;
1114
1115tryAgain:
1116#ifdef PG_O_DIRECT_USE_F_NOCACHE
1117
1118
1119
1120
1121
1123 (O_APPEND |
1125 O_CREAT |
1127 O_EXCL |
1128 O_RDWR |
1129 O_RDONLY |
1130 O_SYNC |
1131 O_TRUNC |
1132 O_WRONLY)) == 0,
1133 "PG_O_DIRECT value collides with standard flag");
1134 fd = open(fileName, fileFlags & ~PG_O_DIRECT, fileMode);
1135#else
1136 fd = open(fileName, fileFlags, fileMode);
1137#endif
1138
1139 if (fd >= 0)
1140 {
1141#ifdef PG_O_DIRECT_USE_F_NOCACHE
1143 {
1144 if (fcntl(fd, F_NOCACHE, 1) < 0)
1145 {
1146 int save_errno = errno;
1147
1149 errno = save_errno;
1150 return -1;
1151 }
1152 }
1153#endif
1154
1155 return fd;
1156 }
1157
1158 if (errno == EMFILE || errno == ENFILE)
1159 {
1160 int save_errno = errno;
1161
1163 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1164 errmsg("out of file descriptors: %m; release and retry")));
1165 errno = 0;
1167 goto tryAgain;
1168 errno = save_errno;
1169 }
1170
1171 return -1;
1172}
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187bool
1189{
1190
1191
1192
1193
1195 {
1197 return true;
1198 }
1199 errno = EMFILE;
1200 return false;
1201}
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222void
1224{
1225
1226
1227
1228
1229
1231
1233}
1234
1235
1236
1237
1238
1239
1240void
1242{
1245}
1246
1247
1248#if defined(FDDEBUG)
1249
1250static void
1251_dump_lru(void)
1252{
1255 char buf[2048];
1256
1258 while (mru != 0)
1259 {
1263 }
1266}
1267#endif
1268
1269static void
1271{
1272 Vfd *vfdP;
1273
1275
1277 file, VfdCache[file].fileName));
1278 DO_DB(_dump_lru());
1279
1281
1284
1285 DO_DB(_dump_lru());
1286}
1287
1288static void
1290{
1291 Vfd *vfdP;
1292
1294
1296 file, VfdCache[file].fileName));
1297
1299
1301
1302
1303
1304
1305
1306 if (close(vfdP->fd) != 0)
1308 "could not close file \"%s\": %m", vfdP->fileName);
1311
1312
1314}
1315
1316static void
1318{
1319 Vfd *vfdP;
1320
1322
1324 file, VfdCache[file].fileName));
1325 DO_DB(_dump_lru());
1326
1328
1333
1334 DO_DB(_dump_lru());
1335}
1336
1337
1338static int
1340{
1341 Vfd *vfdP;
1342
1344
1346 file, VfdCache[file].fileName));
1347
1349
1351 {
1352
1354
1355
1356
1357
1358
1359
1362 if (vfdP->fd < 0)
1363 {
1365 return -1;
1366 }
1367 else
1368 {
1370 }
1371 }
1372
1373
1374
1375
1376
1378
1379 return 0;
1380}
1381
1382
1383
1384
1385static bool
1387{
1389
1391 {
1392
1393
1394
1395
1398 return true;
1399 }
1400 return false;
1401}
1402
1403
1404
1405
1406
1407static void
1409{
1411 {
1413 break;
1414 }
1415}
1416
1419{
1422
1424
1426
1427 if (VfdCache[0].nextFree == 0)
1428 {
1429
1430
1431
1432
1433
1435 Vfd *newVfdCache;
1436
1437 if (newCacheSize < 32)
1438 newCacheSize = 32;
1439
1440
1441
1442
1444 if (newVfdCache == NULL)
1446 (errcode(ERRCODE_OUT_OF_MEMORY),
1447 errmsg("out of memory")));
1449
1450
1451
1452
1454 {
1458 }
1461
1462
1463
1464
1466 }
1467
1469
1471
1472 return file;
1473}
1474
1475static void
1477{
1479
1482
1484 {
1487 }
1489
1492}
1493
1494
1495static int
1497{
1498 int returnValue;
1499
1501 file, VfdCache[file].fileName));
1502
1503
1504
1505
1506
1507
1509 {
1511 if (returnValue != 0)
1512 return returnValue;
1513 }
1514 else if (VfdCache[0].lruLessRecently != file)
1515 {
1516
1517
1518
1519
1520
1523 }
1524
1525 return 0;
1526}
1527
1528
1529
1530
1531static void
1533{
1535
1537 {
1540 (errmsg("temporary file: path \"%s\", size %lu",
1541 path, (unsigned long) size)));
1542 }
1543}
1544
1545
1546
1547
1548
1549
1550static void
1552{
1555
1556
1559}
1560
1561
1562
1563
1564#ifdef NOT_USED
1565void
1566FileInvalidate(File file)
1567{
1571}
1572#endif
1573
1574
1575
1576
1577
1580{
1582}
1583
1584
1585
1586
1587
1588
1589
1590
1593{
1594 char *fnamecopy;
1596 Vfd *vfdP;
1597
1598 DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1599 fileName, fileFlags, fileMode));
1600
1601
1602
1603
1604 fnamecopy = strdup(fileName);
1605 if (fnamecopy == NULL)
1607 (errcode(ERRCODE_OUT_OF_MEMORY),
1608 errmsg("out of memory")));
1609
1612
1613
1615
1616
1617
1618
1619
1620
1621
1623
1625
1626 if (vfdP->fd < 0)
1627 {
1628 int save_errno = errno;
1629
1631 free(fnamecopy);
1632 errno = save_errno;
1633 return -1;
1634 }
1636 DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1637 vfdP->fd));
1638
1640
1641 vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1646
1648
1649 return file;
1650}
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663void
1665{
1667 {
1668 if (errno == EEXIST)
1669 return;
1670
1671
1672
1673
1674
1675
1679 errmsg("cannot create temporary directory \"%s\": %m",
1681
1682
1686 errmsg("cannot create temporary subdirectory \"%s\": %m",
1688 }
1689}
1690
1691
1692
1693
1694void
1696{
1697 struct stat statbuf;
1698
1699
1700 if (stat(dirname, &statbuf) != 0 && errno == ENOENT)
1701 return;
1702
1703
1704
1705
1706
1707
1708
1709
1711}
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1729{
1730 File file = 0;
1731
1732 Assert(temporary_files_allowed);
1733
1734
1735
1736
1737
1738 if (!interXact)
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1751 {
1753
1756 }
1757
1758
1759
1760
1761
1762
1763 if (file <= 0)
1766 DEFAULTTABLESPACE_OID,
1767 true);
1768
1769
1771
1772
1773 if (!interXact)
1775
1776 return file;
1777}
1778
1779
1780
1781
1782void
1784{
1785
1786
1787
1788
1789
1791 tablespace == DEFAULTTABLESPACE_OID ||
1794 else
1795 {
1796
1800 }
1801}
1802
1803
1804
1805
1806
1809{
1813
1815
1816
1817
1818
1819
1820 snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld",
1822
1823
1824
1825
1826
1828 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1829 if (file <= 0)
1830 {
1831
1832
1833
1834
1835
1836
1837
1838
1840
1842 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1843 if (file <= 0 && rejectError)
1844 elog(ERROR, "could not create temporary file \"%s\": %m",
1845 tempfilepath);
1846 }
1847
1848 return file;
1849}
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1866{
1868
1869 Assert(temporary_files_allowed);
1870
1872
1873
1874
1875
1876
1878 if (file <= 0)
1879 {
1880 if (error_on_failure)
1883 errmsg("could not create temporary file \"%s\": %m",
1884 path)));
1885 else
1886 return file;
1887 }
1888
1889
1891
1892
1894
1895 return file;
1896}
1897
1898
1899
1900
1901
1902
1903
1906{
1908
1909 Assert(temporary_files_allowed);
1910
1912
1914
1915
1916 if (file <= 0 && errno != ENOENT)
1919 errmsg("could not open temporary file \"%s\": %m",
1920 path)));
1921
1922 if (file > 0)
1923 {
1924
1926 }
1927
1928 return file;
1929}
1930
1931
1932
1933
1934
1935bool
1937{
1938 struct stat filestats;
1939 int stat_errno;
1940
1941
1942 if (stat(path, &filestats) != 0)
1943 stat_errno = errno;
1944 else
1945 stat_errno = 0;
1946
1947
1948
1949
1950
1951
1952 if (stat_errno == ENOENT)
1953 return false;
1954
1955 if (unlink(path) < 0)
1956 {
1957 if (errno != ENOENT)
1960 errmsg("could not unlink temporary file \"%s\": %m",
1961 path)));
1962 return false;
1963 }
1964
1965 if (stat_errno == 0)
1967 else
1968 {
1969 errno = stat_errno;
1972 errmsg("could not stat file \"%s\": %m", path)));
1973 }
1974
1975 return true;
1976}
1977
1978
1979
1980
1981void
1983{
1984 Vfd *vfdP;
1985
1987
1989 file, VfdCache[file].fileName));
1990
1992
1994 {
1996
1997
1998 if (close(vfdP->fd) != 0)
1999 {
2000
2001
2002
2003
2005 "could not close file \"%s\": %m", vfdP->fileName);
2006 }
2007
2010
2011
2013 }
2014
2016 {
2017
2020 }
2021
2022
2023
2024
2026 {
2027 struct stat filestats;
2028 int stat_errno;
2029
2030
2031
2032
2033
2034
2035
2036
2037 vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
2038
2039
2040
2042 stat_errno = errno;
2043 else
2044 stat_errno = 0;
2045
2046
2050 errmsg("could not delete file \"%s\": %m", vfdP->fileName)));
2051
2052
2053 if (stat_errno == 0)
2055 else
2056 {
2057 errno = stat_errno;
2060 errmsg("could not stat file \"%s\": %m", vfdP->fileName)));
2061 }
2062 }
2063
2064
2067
2068
2069
2070
2072}
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082int
2084{
2086
2088 file, VfdCache[file].fileName,
2090
2091#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
2092 {
2093 int returnCode;
2094
2096 if (returnCode < 0)
2097 return returnCode;
2098
2099retry:
2101 returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2102 POSIX_FADV_WILLNEED);
2104
2105 if (returnCode == EINTR)
2106 goto retry;
2107
2108 return returnCode;
2109 }
2110#elif defined(__darwin__)
2111 {
2112 struct radvisory
2113 {
2114 off_t ra_offset;
2115 int ra_count;
2116 } ra;
2117 int returnCode;
2118
2120 if (returnCode < 0)
2121 return returnCode;
2122
2123 ra.ra_offset = offset;
2124 ra.ra_count = amount;
2126 returnCode = fcntl(VfdCache[file].fd, F_RDADVISE, &ra);
2128 if (returnCode != -1)
2129 return 0;
2130 else
2131 return errno;
2132 }
2133#else
2134 return 0;
2135#endif
2136}
2137
2138void
2140{
2141 int returnCode;
2142
2144
2146 file, VfdCache[file].fileName,
2148
2149 if (nbytes <= 0)
2150 return;
2151
2153 return;
2154
2156 if (returnCode < 0)
2157 return;
2158
2162}
2163
2164ssize_t
2165FileReadV(File file, const struct iovec *iov, int iovcnt, off_t offset,
2166 uint32 wait_event_info)
2167{
2168 ssize_t returnCode;
2169 Vfd *vfdP;
2170
2172
2174 file, VfdCache[file].fileName,
2176 iovcnt));
2177
2179 if (returnCode < 0)
2180 return returnCode;
2181
2183
2184retry:
2186 returnCode = pg_preadv(vfdP->fd, iov, iovcnt, offset);
2188
2189 if (returnCode < 0)
2190 {
2191
2192
2193
2194
2195
2196
2197
2198#ifdef WIN32
2199 DWORD error = GetLastError();
2200
2202 {
2203 case ERROR_NO_SYSTEM_RESOURCES:
2206 break;
2207 default:
2209 break;
2210 }
2211#endif
2212
2213 if (errno == EINTR)
2214 goto retry;
2215 }
2216
2217 return returnCode;
2218}
2219
2220int
2222 int iovcnt, off_t offset,
2223 uint32 wait_event_info)
2224{
2225 int returnCode;
2226 Vfd *vfdP;
2227
2229
2231 file, VfdCache[file].fileName,
2233 iovcnt));
2234
2236 if (returnCode < 0)
2237 return returnCode;
2238
2240
2242
2243 return 0;
2244}
2245
2246ssize_t
2247FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset,
2248 uint32 wait_event_info)
2249{
2250 ssize_t returnCode;
2251 Vfd *vfdP;
2252
2254
2256 file, VfdCache[file].fileName,
2258 iovcnt));
2259
2261 if (returnCode < 0)
2262 return returnCode;
2263
2265
2266
2267
2268
2269
2270
2271
2272
2273
2275 {
2276 off_t past_write = offset;
2277
2278 for (int i = 0; i < iovcnt; ++i)
2279 past_write += iov[i].iov_len;
2280
2281 if (past_write > vfdP->fileSize)
2282 {
2284
2285 newTotal += past_write - vfdP->fileSize;
2288 (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
2289 errmsg("temporary file size exceeds \"temp_file_limit\" (%dkB)",
2291 }
2292 }
2293
2294retry:
2296 returnCode = pg_pwritev(vfdP->fd, iov, iovcnt, offset);
2298
2299 if (returnCode >= 0)
2300 {
2301
2302
2303
2304
2305
2306
2307
2308 errno = ENOSPC;
2309
2310
2311
2312
2314 {
2315 off_t past_write = offset + returnCode;
2316
2317 if (past_write > vfdP->fileSize)
2318 {
2320 vfdP->fileSize = past_write;
2321 }
2322 }
2323 }
2324 else
2325 {
2326
2327
2328
2329#ifdef WIN32
2330 DWORD error = GetLastError();
2331
2333 {
2334 case ERROR_NO_SYSTEM_RESOURCES:
2337 break;
2338 default:
2340 break;
2341 }
2342#endif
2343
2344 if (errno == EINTR)
2345 goto retry;
2346 }
2347
2348 return returnCode;
2349}
2350
2351int
2353{
2354 int returnCode;
2355
2357
2359 file, VfdCache[file].fileName));
2360
2362 if (returnCode < 0)
2363 return returnCode;
2364
2368
2369 return returnCode;
2370}
2371
2372
2373
2374
2375
2376
2377
2378int
2380{
2381 int returnCode;
2382 ssize_t written;
2383
2385
2387 file, VfdCache[file].fileName,
2389
2391 if (returnCode < 0)
2392 return returnCode;
2393
2397
2398 if (written < 0)
2399 return -1;
2400 else if (written != amount)
2401 {
2402
2403 if (errno == 0)
2404 errno = ENOSPC;
2405 return -1;
2406 }
2407
2408 return 0;
2409}
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423int
2425{
2426#ifdef HAVE_POSIX_FALLOCATE
2427 int returnCode;
2428
2430
2432 file, VfdCache[file].fileName,
2434
2436 if (returnCode < 0)
2437 return -1;
2438
2439retry:
2441 returnCode = posix_fallocate(VfdCache[file].fd, offset, amount);
2443
2444 if (returnCode == 0)
2445 return 0;
2446 else if (returnCode == EINTR)
2447 goto retry;
2448
2449
2450 errno = returnCode;
2451
2452
2453
2454
2455
2456 if (returnCode != EINVAL && returnCode != EOPNOTSUPP)
2457 return -1;
2458#endif
2459
2460 return FileZero(file, offset, amount, wait_event_info);
2461}
2462
2463off_t
2465{
2467
2469 file, VfdCache[file].fileName));
2470
2472 {
2474 return (off_t) -1;
2475 }
2476
2477 return lseek(VfdCache[file].fd, 0, SEEK_END);
2478}
2479
2480int
2482{
2483 int returnCode;
2484
2486
2488 file, VfdCache[file].fileName));
2489
2491 if (returnCode < 0)
2492 return returnCode;
2493
2497
2498 if (returnCode == 0 && VfdCache[file].fileSize > offset)
2499 {
2500
2504 }
2505
2506 return returnCode;
2507}
2508
2509
2510
2511
2512
2513
2514
2515char *
2517{
2519
2521}
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531int
2533{
2534 int returnCode;
2535
2537 if (returnCode < 0)
2538 return returnCode;
2539
2542}
2543
2544
2545
2546
2547int
2549{
2552}
2553
2554
2555
2556
2557mode_t
2559{
2562}
2563
2564
2565
2566
2567
2568static bool
2570{
2572 int newMax;
2573
2574
2576 return true;
2577
2578
2579
2580
2581
2582
2583
2585 {
2588
2589 if (newDescs == NULL)
2591 (errcode(ERRCODE_OUT_OF_MEMORY),
2592 errmsg("out of memory")));
2595 return true;
2596 }
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2611 {
2614
2615 if (newDescs == NULL)
2616 return false;
2619 return true;
2620 }
2621
2622
2623 return false;
2624}
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643FILE *
2645{
2646 FILE *file;
2647
2648 DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2650
2651
2654 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2655 errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2657
2658
2660
2661TryAgain:
2662 if ((file = fopen(name, mode)) != NULL)
2663 {
2665
2671 }
2672
2673 if (errno == EMFILE || errno == ENFILE)
2674 {
2675 int save_errno = errno;
2676
2678 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2679 errmsg("out of file descriptors: %m; release and retry")));
2680 errno = 0;
2682 goto TryAgain;
2683 errno = save_errno;
2684 }
2685
2686 return NULL;
2687}
2688
2689
2690
2691
2692
2693int
2695{
2697}
2698
2699
2700
2701
2702int
2704{
2705 int fd;
2706
2707 DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2709
2710
2713 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2714 errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2716
2717
2719
2721
2722 if (fd >= 0)
2723 {
2725
2730
2731 return fd;
2732 }
2733
2734 return -1;
2735}
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746FILE *
2748{
2749 FILE *file;
2750 int save_errno;
2751
2752 DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2754
2755
2758 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2759 errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2761
2762
2764
2765TryAgain:
2766 fflush(NULL);
2768 errno = 0;
2769 file = popen(command, mode);
2770 save_errno = errno;
2772 errno = save_errno;
2773 if (file != NULL)
2774 {
2776
2782 }
2783
2784 if (errno == EMFILE || errno == ENFILE)
2785 {
2787 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2788 errmsg("out of file descriptors: %m; release and retry")));
2790 goto TryAgain;
2791 errno = save_errno;
2792 }
2793
2794 return NULL;
2795}
2796
2797
2798
2799
2800
2801
2802static int
2804{
2805 int result;
2806
2807
2808 switch (desc->kind)
2809 {
2811 result = fclose(desc->desc.file);
2812 break;
2814 result = pclose(desc->desc.file);
2815 break;
2818 break;
2822 break;
2823 default:
2824 elog(ERROR, "AllocateDesc kind not recognized");
2825 result = 0;
2826 break;
2827 }
2828
2829
2832
2833 return result;
2834}
2835
2836
2837
2838
2839
2840
2841
2842int
2844{
2845 int i;
2846
2848
2849
2851 {
2853
2856 }
2857
2858
2859 elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2860
2861 return fclose(file);
2862}
2863
2864
2865
2866
2867
2868
2869
2870int
2872{
2873 int i;
2874
2876
2877
2879 {
2881
2884 }
2885
2886
2887 elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2888
2890
2892}
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2908{
2909 DIR *dir;
2910
2911 DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2913
2914
2917 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2918 errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2920
2921
2923
2924TryAgain:
2925 if ((dir = opendir(dirname)) != NULL)
2926 {
2928
2934 }
2935
2936 if (errno == EMFILE || errno == ENFILE)
2937 {
2938 int save_errno = errno;
2939
2941 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2942 errmsg("out of file descriptors: %m; release and retry")));
2943 errno = 0;
2945 goto TryAgain;
2946 errno = save_errno;
2947 }
2948
2949 return NULL;
2950}
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2974{
2976}
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2989{
2990 struct dirent *dent;
2991
2992
2993 if (dir == NULL)
2994 {
2997 errmsg("could not open directory \"%s\": %m",
2998 dirname)));
2999 return NULL;
3000 }
3001
3002 errno = 0;
3003 if ((dent = readdir(dir)) != NULL)
3004 return dent;
3005
3006 if (errno)
3009 errmsg("could not read directory \"%s\": %m",
3010 dirname)));
3011 return NULL;
3012}
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024int
3026{
3027 int i;
3028
3029
3030 if (dir == NULL)
3031 return 0;
3032
3034
3035
3037 {
3039
3042 }
3043
3044
3045 elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
3046
3048}
3049
3050
3051
3052
3053
3054int
3056{
3057 int i;
3058
3060
3061
3063 {
3065
3068 }
3069
3070
3071 elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
3072
3073 return pclose(file);
3074}
3075
3076
3077
3078
3079
3080
3081
3082
3083void
3085{
3087
3089 {
3092 {
3095 }
3096 }
3097}
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112void
3114{
3115 Assert(numSpaces >= 0);
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127 if (numSpaces > 1)
3129 0, numSpaces - 1);
3130 else
3132}
3133
3134
3135
3136
3137
3138
3139
3140
3141bool
3143{
3145}
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156int
3158{
3159 int i;
3160
3164
3165 return i;
3166}
3167
3168
3169
3170
3171
3172
3173
3176{
3178 {
3179
3183 }
3185}
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195void
3198{
3200
3202 {
3204 {
3205 if (isCommit)
3207 else
3208 {
3209
3211 }
3212 }
3213 }
3214}
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228void
3230{
3234}
3235
3236
3237
3238
3239
3240
3241
3242static void
3244{
3246
3247
3248#ifdef USE_ASSERT_CHECKING
3249 temporary_files_allowed = false;
3250#endif
3251}
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265static void
3267{
3269
3270
3271
3272
3273
3275 {
3278 {
3280
3283 {
3284
3285
3286
3287
3288
3289
3290
3291 if (isProcExit)
3294 {
3296 "temporary file %s not closed at end-of-transaction",
3299 }
3300 }
3301 }
3302
3304 }
3305
3306
3308 elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
3310
3311
3314}
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337void
3339{
3341 DIR *spc_dir;
3342 struct dirent *spc_de;
3343
3344
3345
3346
3350
3351
3352
3353
3355
3357 {
3358 if (strcmp(spc_de->d_name, ".") == 0 ||
3359 strcmp(spc_de->d_name, "..") == 0)
3360 continue;
3361
3362 snprintf(temp_path, sizeof(temp_path), "%s/%s/%s/%s",
3366
3367 snprintf(temp_path, sizeof(temp_path), "%s/%s/%s",
3370 }
3371
3373
3374
3375
3376
3377
3378
3379
3380}
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397void
3399{
3400 DIR *temp_dir;
3401 struct dirent *temp_de;
3403
3405
3406 if (temp_dir == NULL && errno == ENOENT && missing_ok)
3407 return;
3408
3409 while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
3410 {
3411 if (strcmp(temp_de->d_name, ".") == 0 ||
3412 strcmp(temp_de->d_name, "..") == 0)
3413 continue;
3414
3415 snprintf(rm_path, sizeof(rm_path), "%s/%s",
3416 tmpdirname, temp_de->d_name);
3417
3418 if (unlink_all ||
3419 strncmp(temp_de->d_name,
3422 {
3424
3426 continue;
3428 {
3429
3431
3432 if (rmdir(rm_path) < 0)
3435 errmsg("could not remove directory \"%s\": %m",
3436 rm_path)));
3437 }
3438 else
3439 {
3440 if (unlink(rm_path) < 0)
3443 errmsg("could not remove file \"%s\": %m",
3444 rm_path)));
3445 }
3446 }
3447 else
3449 (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3450 rm_path)));
3451 }
3452
3454}
3455
3456
3457static void
3459{
3460 DIR *ts_dir;
3462 char dbspace_path[MAXPGPATH * 2];
3463
3465
3467 {
3468
3469
3470
3471
3472
3473 if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3474 continue;
3475
3476 snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3477 tsdirname, de->d_name);
3479 }
3480
3482}
3483
3484
3485static void
3487{
3488 DIR *dbspace_dir;
3491
3492 dbspace_dir = AllocateDir(dbspacedirname);
3493
3494 while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3495 {
3497 continue;
3498
3499 snprintf(rm_path, sizeof(rm_path), "%s/%s",
3500 dbspacedirname, de->d_name);
3501
3502 if (unlink(rm_path) < 0)
3505 errmsg("could not remove file \"%s\": %m",
3506 rm_path)));
3507 }
3508
3510}
3511
3512
3513bool
3515{
3516 int pos;
3517 int savepos;
3518
3519
3520 if (name[0] != 't')
3521 return false;
3522
3523
3524 for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3525 ;
3526 if (pos == 1 || name[pos] != '_')
3527 return false;
3528
3529
3530 for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3531 ;
3532 if (savepos == pos)
3533 return false;
3534
3535
3536 if (name[pos] == '_')
3537 {
3539
3540 if (forkchar <= 0)
3541 return false;
3542 pos += forkchar + 1;
3543 }
3544 if (name[pos] == '.')
3545 {
3546 int segchar;
3547
3548 for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3549 ;
3550 if (segchar <= 1)
3551 return false;
3552 pos += segchar;
3553 }
3554
3555
3556 if (name[pos] != '\0')
3557 return false;
3558 return true;
3559}
3560
3561#ifdef HAVE_SYNCFS
3562static void
3563do_syncfs(const char *path)
3564{
3565 int fd;
3566
3567 ereport_startup_progress("syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s",
3568 path);
3569
3571 if (fd < 0)
3572 {
3575 errmsg("could not open file \"%s\": %m", path)));
3576 return;
3577 }
3578 if (syncfs(fd) < 0)
3581 errmsg("could not synchronize file system for file \"%s\": %m", path)));
3583}
3584#endif
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608void
3610{
3611 bool xlog_is_symlink;
3612
3613
3615 return;
3616
3617
3618
3619
3620
3621 xlog_is_symlink = false;
3622
3623 {
3624 struct stat st;
3625
3626 if (lstat("pg_wal", &st) < 0)
3629 errmsg("could not stat file \"%s\": %m",
3630 "pg_wal")));
3632 xlog_is_symlink = true;
3633 }
3634
3635#ifdef HAVE_SYNCFS
3637 {
3638 DIR *dir;
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3651
3652
3653 do_syncfs(".");
3654
3657 {
3659
3660 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
3661 continue;
3662
3664 do_syncfs(path);
3665 }
3667
3668 if (xlog_is_symlink)
3669 do_syncfs("pg_wal");
3670 return;
3671 }
3672#endif
3673
3674#ifdef PG_FLUSH_DATA_WORKS
3675
3677
3678
3679
3680
3681
3682
3684 if (xlog_is_symlink)
3685 walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3687#endif
3688
3689
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3702 if (xlog_is_symlink)
3705}
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722static void
3724 void (*action) (const char *fname, bool isdir, int elevel),
3725 bool process_symlinks,
3726 int elevel)
3727{
3728 DIR *dir;
3730
3732
3733 while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3734 {
3736
3738
3739 if (strcmp(de->d_name, ".") == 0 ||
3740 strcmp(de->d_name, "..") == 0)
3741 continue;
3742
3744
3746 {
3748 (*action) (subpath, false, elevel);
3749 break;
3752 break;
3753 default:
3754
3755
3756
3757
3758
3759
3760 break;
3761 }
3762 }
3763
3764 FreeDir(dir);
3765
3766
3767
3768
3769
3770
3771
3772 if (dir)
3773 (*action) (path, true, elevel);
3774}
3775
3776
3777
3778
3779
3780
3781
3782
3783#ifdef PG_FLUSH_DATA_WORKS
3784
3785static void
3786pre_sync_fname(const char *fname, bool isdir, int elevel)
3787{
3788 int fd;
3789
3790
3791 if (isdir)
3792 return;
3793
3794 ereport_startup_progress("syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s",
3795 fname);
3796
3798
3799 if (fd < 0)
3800 {
3801 if (errno == EACCES)
3802 return;
3805 errmsg("could not open file \"%s\": %m", fname)));
3806 return;
3807 }
3808
3809
3810
3811
3812
3814
3818 errmsg("could not close file \"%s\": %m", fname)));
3819}
3820
3821#endif
3822
3823static void
3825{
3826 ereport_startup_progress("syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s",
3827 fname);
3828
3829
3830
3831
3832
3834}
3835
3836static void
3838{
3839 if (isdir)
3840 {
3841 if (rmdir(fname) != 0 && errno != ENOENT)
3844 errmsg("could not remove directory \"%s\": %m", fname)));
3845 }
3846 else
3847 {
3848
3850 }
3851}
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861int
3862fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
3863{
3864 int fd;
3865 int flags;
3866 int returncode;
3867
3868
3869
3870
3871
3872
3873
3875 if (!isdir)
3876 flags |= O_RDWR;
3877 else
3878 flags |= O_RDONLY;
3879
3881
3882
3883
3884
3885
3886
3887 if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3888 return 0;
3889 else if (fd < 0 && ignore_perm && errno == EACCES)
3890 return 0;
3891 else if (fd < 0)
3892 {
3895 errmsg("could not open file \"%s\": %m", fname)));
3896 return -1;
3897 }
3898
3900
3901
3902
3903
3904
3905 if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
3906 {
3907 int save_errno;
3908
3909
3910 save_errno = errno;
3912 errno = save_errno;
3913
3916 errmsg("could not fsync file \"%s\": %m", fname)));
3917 return -1;
3918 }
3919
3921 {
3924 errmsg("could not close file \"%s\": %m", fname)));
3925 return -1;
3926 }
3927
3928 return 0;
3929}
3930
3931
3932
3933
3934
3935
3936
3937static int
3939{
3941
3944
3945
3946
3947
3948
3949
3950 if (strlen(parentpath) == 0)
3952
3953 if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3954 return -1;
3955
3956 return 0;
3957}
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977int
3979{
3981}
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000int
4002{
4004}
4005
4006bool
4008{
4009 bool result = true;
4010 int flags;
4011
4012#if PG_O_DIRECT == 0
4013 if (strcmp(*newval, "") != 0)
4014 {
4016 "debug_io_direct");
4017 result = false;
4018 }
4019 flags = 0;
4020#else
4021 List *elemlist;
4023 char *rawstring;
4024
4025
4027
4028 if ((rawstring, ',', &elemlist))
4029 {
4031 "debug_io_direct");
4032 pfree(rawstring);
4034 return false;
4035 }
4036
4037 flags = 0;
4038 foreach(l, elemlist)
4039 {
4040 char *item = (char *) lfirst(l);
4041
4048 else
4049 {
4051 result = false;
4052 break;
4053 }
4054 }
4055
4056
4057
4058
4059
4060#if XLOG_BLCKSZ < PG_IO_ALIGN_SIZE
4062 {
4063 GUC_check_errdetail("\"%s\" is not supported for WAL because %s is too small.",
4064 "debug_io_direct", "XLOG_BLCKSZ");
4065 result = false;
4066 }
4067#endif
4068#if BLCKSZ < PG_IO_ALIGN_SIZE
4070 {
4071 GUC_check_errdetail("\"%s\" is not supported for data because %s is too small.",
4072 "debug_io_direct", "BLCKSZ");
4073 result = false;
4074 }
4075#endif
4076
4077 pfree(rawstring);
4079#endif
4080
4081 if (!result)
4082 return result;
4083
4084
4086 if (!*extra)
4087 return false;
4088 *((int *) *extra) = flags;
4089
4090 return result;
4091}
4092
4093void
4095{
4096 int *flags = (int *) extra;
4097
4099}
4100
4101
4102
4103static void
4105{
4107 Vfd *vfdP;
4108
4110
4113
4115}
4116
4117static char *
4119{
4121}
void pgaio_closing_fd(int fd)
void pgaio_io_start_readv(PgAioHandle *ioh, int fd, int iovcnt, uint64 offset)
void begin_startup_progress_phase(void)
#define MemSet(start, val, len)
#define StaticAssertStmt(condition, errmessage)
int fdatasync(int fildes)
#define OidIsValid(objectId)
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
static int pg_ftruncate(int fd, off_t length)
int max_files_per_process
void pg_flush_data(int fd, off_t offset, off_t nbytes)
int FileGetRawDesc(File file)
int MakePGDirectory(const char *directoryName)
int recovery_init_sync_method
static const ResourceOwnerDesc file_resowner_desc
void FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info)
int pg_fsync_no_writethrough(int fd)
FILE * OpenPipeStream(const char *command, const char *mode)
static int numTempTableSpaces
static bool ReleaseLruFile(void)
#define FD_DELETE_AT_CLOSE
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
static int maxAllocatedDescs
static void Delete(File file)
static int FreeDesc(AllocateDesc *desc)
static long tempFileCounter
static char * ResOwnerPrintFile(Datum res)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
char * FilePathName(File file)
static void ResourceOwnerForgetFile(ResourceOwner owner, File file)
int GetTempTablespaces(Oid *tableSpaces, int numSpaces)
static int numAllocatedDescs
File PathNameOpenTemporaryFile(const char *path, int mode)
static void LruDelete(File file)
#define FileIsValid(file)
void assign_debug_io_direct(const char *newval, void *extra)
int FileSync(File file, uint32 wait_event_info)
int CloseTransientFile(int fd)
int BasicOpenFile(const char *fileName, int fileFlags)
static File AllocateVfd(void)
File PathNameCreateTemporaryFile(const char *path, bool error_on_failure)
void PathNameDeleteTemporaryDir(const char *dirname)
int ClosePipeStream(FILE *file)
void AtEOXact_Files(bool isCommit)
int FileGetRawFlags(File file)
static int nextTempTableSpace
#define FD_CLOSE_AT_EOXACT
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel)
static void ResOwnerReleaseFile(Datum res)
static void RemovePgTempRelationFiles(const char *tsdirname)
mode_t FileGetRawMode(File file)
static AllocateDesc * allocatedDescs
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
static int FileAccess(File file)
static void FreeVfd(File file)
int pg_fsync_writethrough(int fd)
void FileClose(File file)
int FileStartReadV(PgAioHandle *ioh, File file, int iovcnt, off_t offset, uint32 wait_event_info)
void ReleaseExternalFD(void)
#define FD_TEMP_FILE_LIMIT
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
bool pg_file_exists(const char *name)
void RemovePgTempFiles(void)
#define FileIsNotOpen(file)
bool TempTablespacesAreSet(void)
void fsync_fname(const char *fname, bool isdir)
int FileFallocate(File file, off_t offset, off_t amount, uint32 wait_event_info)
int FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info)
int data_sync_elevel(int elevel)
File PathNameOpenFile(const char *fileName, int fileFlags)
static void Insert(File file)
Oid GetNextTempTableSpace(void)
File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
static void ReportTemporaryFileUsage(const char *path, off_t size)
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
bool AcquireExternalFD(void)
static void RegisterTemporaryFile(File file)
DIR * AllocateDir(const char *dirname)
static Oid * tempTableSpaces
static bool reserveAllocatedDesc(void)
void InitFileAccess(void)
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
File OpenTemporaryFile(bool interXact)
int durable_unlink(const char *fname, int elevel)
static uint64 temporary_files_size
void ReserveExternalFD(void)
struct dirent * ReadDir(DIR *dir, const char *dirname)
bool looks_like_temp_rel_name(const char *name)
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
void set_max_safe_fds(void)
static void CleanupTempFiles(bool isCommit, bool isProcExit)
static bool have_xact_temporary_files
static int LruInsert(File file)
static int numExternalFDs
static int fsync_parent_path(const char *fname, int elevel)
void PathNameCreateTemporaryDir(const char *basedir, const char *directory)
FILE * AllocateFile(const char *name, const char *mode)
void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
int OpenTransientFile(const char *fileName, int fileFlags)
void InitTemporaryFileAccess(void)
int OpenTransientFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
static void ReleaseLruFiles(void)
ssize_t FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset, uint32 wait_event_info)
void SyncDataDirectory(void)
int FileZero(File file, off_t offset, off_t amount, uint32 wait_event_info)
off_t FileSize(File file)
ssize_t FileReadV(File file, const struct iovec *iov, int iovcnt, off_t offset, uint32 wait_event_info)
int FileTruncate(File file, off_t offset, uint32 wait_event_info)
bool check_debug_io_direct(char **newval, void **extra, GucSource source)
static void ResourceOwnerRememberFile(ResourceOwner owner, File file)
static void BeforeShmemExit_Files(int code, Datum arg)
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
int pg_truncate(const char *path, off_t length)
void SetTempTablespaces(Oid *tableSpaces, int numSpaces)
void TempTablespacePath(char *path, Oid tablespace)
#define IO_DIRECT_WAL_INIT
ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset)
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
#define PG_TEMP_FILES_DIR
#define PG_TEMP_FILE_PREFIX
@ DATA_DIR_SYNC_METHOD_SYNCFS
@ DATA_DIR_SYNC_METHOD_FSYNC
void * guc_malloc(int elevel, size_t size)
#define GUC_check_errdetail
Assert(PointerIsAligned(start, uint64))
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
void list_free(List *list)
Datum subpath(PG_FUNCTION_ARGS)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
#define CHECK_FOR_INTERRUPTS()
static PgChecksumMode mode
static ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
static ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
pg_prng_state pg_global_prng_state
static rewind_source * source
void pgstat_report_tempfile(size_t filesize)
int pg_strcasecmp(const char *s1, const char *s2)
void get_parent_directory(char *path)
size_t strlcpy(char *dst, const char *src, size_t siz)
static Datum Int32GetDatum(int32 X)
static int32 DatumGetInt32(Datum X)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
int forkname_chars(const char *str, ForkNumber *fork)
#define TABLESPACE_VERSION_DIRECTORY
ResourceOwner CurrentResourceOwner
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerEnlarge(ResourceOwner owner)
@ RESOURCE_RELEASE_AFTER_LOCKS
#define RELEASE_PRIO_FILES
void pg_usleep(long microsec)
#define ereport_startup_progress(msg,...)
SubTransactionId create_subid
union AllocateDesc::@20 desc
bool SplitGUCList(char *rawstring, char separator, List **namelist)
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)
void _dosmaperr(unsigned long)
SubTransactionId GetCurrentSubTransactionId(void)
@ WAL_SYNC_METHOD_FSYNC_WRITETHROUGH
static const char * directory