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{

198 int fd;

199 unsigned short fdstate;

201 File nextFree;

204 off_t fileSize;

205 char *fileName;

206

207 int fileFlags;

208 mode_t fileMode;

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 (SplitGUCList(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