Coverage Report

Created: 2026-11-09 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/storage/smgr/md.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * md.c
4
 *    This code manages relations that reside on magnetic disk.
5
 *
6
 * Or at least, that was what the Berkeley folk had in mind when they named
7
 * this file.  In reality, what this code provides is an interface from
8
 * the smgr API to Unix-like filesystem APIs, so it will work with any type
9
 * of device for which the operating system provides filesystem support.
10
 * It doesn't matter whether the bits are on spinning rust or some other
11
 * storage technology.
12
 *
13
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
14
 * Portions Copyright (c) 1994, Regents of the University of California
15
 *
16
 *
17
 * IDENTIFICATION
18
 *    src/backend/storage/smgr/md.c
19
 *
20
 *-------------------------------------------------------------------------
21
 */
22
#include "postgres.h"
23
24
#include <limits.h>
25
#include <unistd.h>
26
#include <fcntl.h>
27
#include <sys/file.h>
28
29
#include "access/xlogutils.h"
30
#include "commands/tablespace.h"
31
#include "common/file_utils.h"
32
#include "miscadmin.h"
33
#include "pg_trace.h"
34
#include "pgstat.h"
35
#include "storage/aio.h"
36
#include "storage/bufmgr.h"
37
#include "storage/fd.h"
38
#include "storage/md.h"
39
#include "storage/relfilelocator.h"
40
#include "storage/smgr.h"
41
#include "storage/sync.h"
42
#include "utils/memutils.h"
43
#include "utils/wait_event.h"
44
45
/*
46
 * The magnetic disk storage manager keeps track of open file
47
 * descriptors in its own descriptor pool.  This is done to make it
48
 * easier to support relations that are larger than the operating
49
 * system's file size limit (often 2GBytes).  In order to do that,
50
 * we break relations up into "segment" files that are each shorter than
51
 * the OS file size limit.  The segment size is set by the RELSEG_SIZE
52
 * configuration constant in pg_config.h.
53
 *
54
 * On disk, a relation must consist of consecutively numbered segment
55
 * files in the pattern
56
 *  -- Zero or more full segments of exactly RELSEG_SIZE blocks each
57
 *  -- Exactly one partial segment of size 0 <= size < RELSEG_SIZE blocks
58
 *  -- Optionally, any number of inactive segments of size 0 blocks.
59
 * The full and partial segments are collectively the "active" segments.
60
 * Inactive segments are those that once contained data but are currently
61
 * not needed because of an mdtruncate() operation.  The reason for leaving
62
 * them present at size zero, rather than unlinking them, is that other
63
 * backends and/or the checkpointer might be holding open file references to
64
 * such segments.  If the relation expands again after mdtruncate(), such
65
 * that a deactivated segment becomes active again, it is important that
66
 * such file references still be valid --- else data might get written
67
 * out to an unlinked old copy of a segment file that will eventually
68
 * disappear.
69
 *
70
 * RELSEG_SIZE must fit into BlockNumber; but since we expose its value
71
 * as an integer GUC, it actually needs to fit in signed int.  It's worth
72
 * having a cross-check for this since configure's --with-segsize options
73
 * could let people select insane values.
74
 */
75
StaticAssertDecl(RELSEG_SIZE > 0 && RELSEG_SIZE <= INT_MAX,
76
         "RELSEG_SIZE must fit in an integer");
77
78
/*
79
 * File descriptors are stored in the per-fork md_seg_fds arrays inside
80
 * SMgrRelation. The length of these arrays is stored in md_num_open_segs.
81
 * Note that a fork's md_num_open_segs having a specific value does not
82
 * necessarily mean the relation doesn't have additional segments; we may
83
 * just not have opened the next segment yet.  (We could not have "all
84
 * segments are in the array" as an invariant anyway, since another backend
85
 * could extend the relation while we aren't looking.)  We do not have
86
 * entries for inactive segments, however; as soon as we find a partial
87
 * segment, we assume that any subsequent segments are inactive.
88
 *
89
 * The entire MdfdVec array is palloc'd in the MdCxt memory context.
90
 */
91
92
typedef struct _MdfdVec
93
{
94
  File    mdfd_vfd;   /* fd number in fd.c's pool */
95
  BlockNumber mdfd_segno;   /* segment number, from 0 */
96
} MdfdVec;
97
98
static MemoryContext MdCxt;   /* context for all MdfdVec objects */
99
100
101
/* Populate a file tag describing an md.c segment file. */
102
0
#define INIT_MD_FILETAG(a,xx_rlocator,xx_forknum,xx_segno) \
103
0
( \
104
0
  memset(&(a), 0, sizeof(FileTag)), \
105
0
  (a).handler = SYNC_HANDLER_MD, \
106
0
  (a).rlocator = (xx_rlocator), \
107
0
  (a).forknum = (xx_forknum), \
108
0
  (a).segno = (xx_segno) \
109
0
)
110
111
112
/*** behavior for mdopen & _mdfd_getseg ***/
113
/* ereport if segment not present */
114
0
#define EXTENSION_FAIL        (1 << 0)
115
/* return NULL if segment not present */
116
0
#define EXTENSION_RETURN_NULL   (1 << 1)
117
/* create new segments as needed */
118
0
#define EXTENSION_CREATE      (1 << 2)
119
/* create new segments if needed during recovery */
120
0
#define EXTENSION_CREATE_RECOVERY (1 << 3)
121
/* don't try to open a segment, if not already open */
122
0
#define EXTENSION_DONT_OPEN     (1 << 5)
123
124
125
/*
126
 * Fixed-length string to represent paths to files that need to be built by
127
 * md.c.
128
 *
129
 * The maximum number of segments is MaxBlockNumber / RELSEG_SIZE, where
130
 * RELSEG_SIZE can be set to 1 (for testing only).
131
 */
132
0
#define SEGMENT_CHARS OIDCHARS
133
#define MD_PATH_STR_MAXLEN \
134
0
  (\
135
0
    REL_PATH_STR_MAXLEN \
136
0
    + sizeof((char)'.') \
137
0
    + SEGMENT_CHARS \
138
0
  )
139
typedef struct MdPathStr
140
{
141
  char    str[MD_PATH_STR_MAXLEN + 1];
142
} MdPathStr;
143
144
145
/* local routines */
146
static void mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum,
147
             bool isRedo);
148
static MdfdVec *mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior);
149
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum,
150
                   MdfdVec *seg);
151
static void register_unlink_tombstone(RelFileLocatorBackend rlocator);
152
static void register_forget_request(RelFileLocatorBackend rlocator, ForkNumber forknum,
153
                  BlockNumber segno);
154
static void _fdvec_resize(SMgrRelation reln,
155
              ForkNumber forknum,
156
              int nseg);
157
static MdPathStr _mdfd_segpath(SMgrRelation reln, ForkNumber forknum,
158
                 BlockNumber segno);
159
static MdfdVec *_mdfd_openseg(SMgrRelation reln, ForkNumber forknum,
160
                BlockNumber segno, int oflags);
161
static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forknum,
162
               BlockNumber blkno, bool skipFsync, int behavior);
163
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum,
164
                MdfdVec *seg);
165
166
static PgAioResult md_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data);
167
static void md_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel);
168
169
const PgAioHandleCallbacks aio_md_readv_cb = {
170
  .complete_shared = md_readv_complete,
171
  .report = md_readv_report,
172
};
173
174
175
static inline int
176
_mdfd_open_flags(void)
177
0
{
178
0
  int     flags = O_RDWR | PG_BINARY;
179
180
0
  if (io_direct_flags & IO_DIRECT_DATA)
181
0
    flags |= PG_O_DIRECT;
182
183
0
  return flags;
184
0
}
185
186
/*
187
 * mdinit() -- Initialize private state for magnetic disk storage manager.
188
 */
189
void
190
mdinit(void)
191
0
{
192
0
  MdCxt = AllocSetContextCreate(TopMemoryContext,
193
0
                  "MdSmgr",
194
0
                  ALLOCSET_DEFAULT_SIZES);
195
0
}
196
197
/*
198
 * mdexists() -- Does the physical file exist?
199
 *
200
 * Note: this will return true for lingering files, with pending deletions
201
 */
202
bool
203
mdexists(SMgrRelation reln, ForkNumber forknum)
204
0
{
205
  /*
206
   * Close it first, to ensure that we notice if the fork has been unlinked
207
   * since we opened it.  As an optimization, we can skip that in recovery,
208
   * which already closes relations when dropping them.
209
   */
210
0
  if (!InRecovery)
211
0
    mdclose(reln, forknum);
212
213
0
  return (mdopenfork(reln, forknum, EXTENSION_RETURN_NULL) != NULL);
214
0
}
215
216
/*
217
 * mdcreate() -- Create a new relation on magnetic disk.
218
 *
219
 * If isRedo is true, it's okay for the relation to exist already.
220
 */
221
void
222
mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
223
0
{
224
0
  MdfdVec    *mdfd;
225
0
  RelPathStr  path;
226
0
  File    fd;
227
228
0
  if (isRedo && reln->md_num_open_segs[forknum] > 0)
229
0
    return;         /* created and opened already... */
230
231
0
  Assert(reln->md_num_open_segs[forknum] == 0);
232
233
  /*
234
   * We may be using the target table space for the first time in this
235
   * database, so create a per-database subdirectory if needed.
236
   *
237
   * XXX this is a fairly ugly violation of module layering, but this seems
238
   * to be the best place to put the check.  Maybe TablespaceCreateDbspace
239
   * should be here and not in commands/tablespace.c?  But that would imply
240
   * importing a lot of stuff that smgr.c oughtn't know, either.
241
   */
242
0
  TablespaceCreateDbspace(reln->smgr_rlocator.locator.spcOid,
243
0
              reln->smgr_rlocator.locator.dbOid,
244
0
              isRedo);
245
246
0
  path = relpath(reln->smgr_rlocator, forknum);
247
248
0
  fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL);
249
250
0
  if (fd < 0)
251
0
  {
252
0
    int     save_errno = errno;
253
254
0
    if (isRedo)
255
0
      fd = PathNameOpenFile(path.str, _mdfd_open_flags());
256
0
    if (fd < 0)
257
0
    {
258
      /* be sure to report the error reported by create, not open */
259
0
      errno = save_errno;
260
0
      ereport(ERROR,
261
0
          (errcode_for_file_access(),
262
0
           errmsg("could not create file \"%s\": %m", path.str)));
263
0
    }
264
0
  }
265
266
0
  _fdvec_resize(reln, forknum, 1);
267
0
  mdfd = &reln->md_seg_fds[forknum][0];
268
0
  mdfd->mdfd_vfd = fd;
269
0
  mdfd->mdfd_segno = 0;
270
271
0
  if (!SmgrIsTemp(reln))
272
0
    register_dirty_segment(reln, forknum, mdfd);
273
0
}
274
275
/*
276
 * mdunlink() -- Unlink a relation.
277
 *
278
 * Note that we're passed a RelFileLocatorBackend --- by the time this is called,
279
 * there won't be an SMgrRelation hashtable entry anymore.
280
 *
281
 * forknum can be a fork number to delete a specific fork, or InvalidForkNumber
282
 * to delete all forks.
283
 *
284
 * For regular relations, we don't unlink the first segment file of the rel,
285
 * but just truncate it to zero length, and record a request to unlink it after
286
 * the next checkpoint.  Additional segments can be unlinked immediately,
287
 * however.  Leaving the empty file in place prevents that relfilenumber
288
 * from being reused.  The scenario this protects us from is:
289
 * 1. We delete a relation (and commit, and actually remove its file).
290
 * 2. We create a new relation, which by chance gets the same relfilenumber as
291
 *    the just-deleted one (OIDs must've wrapped around for that to happen).
292
 * 3. We crash before another checkpoint occurs.
293
 * During replay, we would delete the file and then recreate it, which is fine
294
 * if the contents of the file were repopulated by subsequent WAL entries.
295
 * But if we didn't WAL-log insertions, but instead relied on fsyncing the
296
 * file after populating it (as we do at wal_level=minimal), the contents of
297
 * the file would be lost forever.  By leaving the empty file until after the
298
 * next checkpoint, we prevent reassignment of the relfilenumber until it's
299
 * safe, because relfilenumber assignment skips over any existing file.
300
 *
301
 * Additional segments, if any, are truncated and then unlinked.  The reason
302
 * for truncating is that other backends may still hold open FDs for these at
303
 * the smgr level, so that the kernel can't remove the file yet.  We want to
304
 * reclaim the disk space right away despite that.
305
 *
306
 * We do not need to go through this dance for temp relations, though, because
307
 * we never make WAL entries for temp rels, and so a temp rel poses no threat
308
 * to the health of a regular rel that has taken over its relfilenumber.
309
 * The fact that temp rels and regular rels have different file naming
310
 * patterns provides additional safety.  Other backends shouldn't have open
311
 * FDs for them, either.
312
 *
313
 * We also don't do it while performing a binary upgrade.  There is no reuse
314
 * hazard in that case, since after a crash or even a simple ERROR, the
315
 * upgrade fails and the whole cluster must be recreated from scratch.
316
 * Furthermore, it is important to remove the files from disk immediately,
317
 * because we may be about to reuse the same relfilenumber.
318
 *
319
 * All the above applies only to the relation's main fork; other forks can
320
 * just be removed immediately, since they are not needed to prevent the
321
 * relfilenumber from being recycled.  Also, we do not carefully
322
 * track whether other forks have been created or not, but just attempt to
323
 * unlink them unconditionally; so we should never complain about ENOENT.
324
 *
325
 * If isRedo is true, it's unsurprising for the relation to be already gone.
326
 * Also, we should remove the file immediately instead of queuing a request
327
 * for later, since during redo there's no possibility of creating a
328
 * conflicting relation.
329
 *
330
 * Note: we currently just never warn about ENOENT at all.  We could warn in
331
 * the main-fork, non-isRedo case, but it doesn't seem worth the trouble.
332
 *
333
 * Note: any failure should be reported as WARNING not ERROR, because
334
 * we are usually not in a transaction anymore when this is called.
335
 */
336
void
337
mdunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
338
0
{
339
  /* Now do the per-fork work */
340
0
  if (forknum == InvalidForkNumber)
341
0
  {
342
0
    for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
343
0
      mdunlinkfork(rlocator, forknum, isRedo);
344
0
  }
345
0
  else
346
0
    mdunlinkfork(rlocator, forknum, isRedo);
347
0
}
348
349
/*
350
 * Truncate a file to release disk space.
351
 */
352
static int
353
do_truncate(const char *path)
354
{
355
  int     save_errno;
356
  int     ret;
357
358
  ret = pg_truncate(path, 0);
359
360
  /* Log a warning here to avoid repetition in callers. */
361
  if (ret < 0 && errno != ENOENT)
362
  {
363
    save_errno = errno;
364
    ereport(WARNING,
365
        (errcode_for_file_access(),
366
         errmsg("could not truncate file \"%s\": %m", path)));
367
    errno = save_errno;
368
  }
369
370
  return ret;
371
}
372
373
static void
374
mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
375
{
376
  RelPathStr  path;
377
  int     ret;
378
  int     save_errno;
379
380
  path = relpath(rlocator, forknum);
381
382
  /*
383
   * Truncate and then unlink the first segment, or just register a request
384
   * to unlink it later, as described in the comments for mdunlink().
385
   */
386
  if (isRedo || IsBinaryUpgrade || forknum != MAIN_FORKNUM ||
387
    RelFileLocatorBackendIsTemp(rlocator))
388
  {
389
    if (!RelFileLocatorBackendIsTemp(rlocator))
390
    {
391
      /* Prevent other backends' fds from holding on to the disk space */
392
      ret = do_truncate(path.str);
393
394
      /* Forget any pending sync requests for the first segment */
395
      save_errno = errno;
396
      register_forget_request(rlocator, forknum, 0 /* first seg */ );
397
      errno = save_errno;
398
    }
399
    else
400
      ret = 0;
401
402
    /* Next unlink the file, unless it was already found to be missing */
403
    if (ret >= 0 || errno != ENOENT)
404
    {
405
      ret = unlink(path.str);
406
      if (ret < 0 && errno != ENOENT)
407
      {
408
        save_errno = errno;
409
        ereport(WARNING,
410
            (errcode_for_file_access(),
411
             errmsg("could not remove file \"%s\": %m", path.str)));
412
        errno = save_errno;
413
      }
414
    }
415
  }
416
  else
417
  {
418
    /* Prevent other backends' fds from holding on to the disk space */
419
    ret = do_truncate(path.str);
420
421
    /* Register request to unlink first segment later */
422
    save_errno = errno;
423
    register_unlink_tombstone(rlocator);
424
    errno = save_errno;
425
  }
426
427
  /*
428
   * Delete any additional segments.
429
   *
430
   * Note that because we loop until getting ENOENT, we will correctly
431
   * remove all inactive segments as well as active ones.  Ideally we'd
432
   * continue the loop until getting exactly that errno, but that risks an
433
   * infinite loop if the problem is directory-wide (for instance, if we
434
   * suddenly can't read the data directory itself).  We compromise by
435
   * continuing after a non-ENOENT truncate error, but stopping after any
436
   * unlink error.  If there is indeed a directory-wide problem, additional
437
   * unlink attempts wouldn't work anyway.
438
   */
439
  if (ret >= 0 || errno != ENOENT)
440
  {
441
    MdPathStr segpath;
442
    BlockNumber segno;
443
444
    for (segno = 1;; segno++)
445
    {
446
      sprintf(segpath.str, "%s.%u", path.str, segno);
447
448
      if (!RelFileLocatorBackendIsTemp(rlocator))
449
      {
450
        /*
451
         * Prevent other backends' fds from holding on to the disk
452
         * space.  We're done if we see ENOENT, though.
453
         */
454
        if (do_truncate(segpath.str) < 0 && errno == ENOENT)
455
          break;
456
457
        /*
458
         * Forget any pending sync requests for this segment before we
459
         * try to unlink.
460
         */
461
        register_forget_request(rlocator, forknum, segno);
462
      }
463
464
      if (unlink(segpath.str) < 0)
465
      {
466
        /* ENOENT is expected after the last segment... */
467
        if (errno != ENOENT)
468
          ereport(WARNING,
469
              (errcode_for_file_access(),
470
               errmsg("could not remove file \"%s\": %m", segpath.str)));
471
        break;
472
      }
473
    }
474
  }
475
}
476
477
/*
478
 * mdextend() -- Add a block to the specified relation.
479
 *
480
 * The semantics are nearly the same as mdwrite(): write at the
481
 * specified position.  However, this is to be used for the case of
482
 * extending a relation (i.e., blocknum is at or beyond the current
483
 * EOF).  Note that we assume writing a block beyond current EOF
484
 * causes intervening file space to become filled with zeroes.
485
 */
486
void
487
mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
488
     const void *buffer, bool skipFsync)
489
0
{
490
0
  pgoff_t   seekpos;
491
0
  ssize_t   nbytes;
492
0
  MdfdVec    *v;
493
494
  /* If this build supports direct I/O, the buffer must be I/O aligned. */
495
0
  if (PG_O_DIRECT != 0 && PG_IO_ALIGN_SIZE <= BLCKSZ)
496
0
    Assert((uintptr_t) buffer == TYPEALIGN(PG_IO_ALIGN_SIZE, buffer));
497
498
  /* This assert is too expensive to have on normally ... */
499
#ifdef CHECK_WRITE_VS_EXTEND
500
  Assert(blocknum >= mdnblocks(reln, forknum));
501
#endif
502
503
  /*
504
   * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
505
   * more --- we mustn't create a block whose number actually is
506
   * InvalidBlockNumber.  (Note that this failure should be unreachable
507
   * because of upstream checks in bufmgr.c.)
508
   */
509
0
  if (blocknum == InvalidBlockNumber)
510
0
    ereport(ERROR,
511
0
        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
512
0
         errmsg("cannot extend file \"%s\" beyond %u blocks",
513
0
            relpath(reln->smgr_rlocator, forknum).str,
514
0
            InvalidBlockNumber)));
515
516
0
  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
517
518
0
  seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
519
520
0
  Assert(seekpos < (pgoff_t) BLCKSZ * RELSEG_SIZE);
521
522
0
  if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_EXTEND)) != BLCKSZ)
523
0
  {
524
0
    if (nbytes < 0)
525
0
      ereport(ERROR,
526
0
          (errcode_for_file_access(),
527
0
           errmsg("could not extend file \"%s\": %m",
528
0
              FilePathName(v->mdfd_vfd)),
529
0
           errhint("Check free disk space.")));
530
    /* short write: complain appropriately */
531
0
    ereport(ERROR,
532
0
        (errcode(ERRCODE_DISK_FULL),
533
0
         errmsg("could not extend file \"%s\": wrote only %zd of %zu bytes at block %u",
534
0
            FilePathName(v->mdfd_vfd),
535
0
            nbytes, (size_t) BLCKSZ, blocknum),
536
0
         errhint("Check free disk space.")));
537
0
  }
538
539
0
  if (!skipFsync && !SmgrIsTemp(reln))
540
0
    register_dirty_segment(reln, forknum, v);
541
542
0
  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
543
0
}
544
545
/*
546
 * mdzeroextend() -- Add new zeroed out blocks to the specified relation.
547
 *
548
 * Similar to mdextend(), except the relation can be extended by multiple
549
 * blocks at once and the added blocks will be filled with zeroes.
550
 */
551
void
552
mdzeroextend(SMgrRelation reln, ForkNumber forknum,
553
       BlockNumber blocknum, int nblocks, bool skipFsync)
554
0
{
555
0
  MdfdVec    *v;
556
0
  BlockNumber curblocknum = blocknum;
557
0
  int     remblocks = nblocks;
558
559
0
  Assert(nblocks > 0);
560
561
  /* This assert is too expensive to have on normally ... */
562
#ifdef CHECK_WRITE_VS_EXTEND
563
  Assert(blocknum >= mdnblocks(reln, forknum));
564
#endif
565
566
  /*
567
   * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
568
   * more --- we mustn't create a block whose number actually is
569
   * InvalidBlockNumber or larger.
570
   */
571
0
  if ((uint64) blocknum + nblocks >= (uint64) InvalidBlockNumber)
572
0
    ereport(ERROR,
573
0
        (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
574
0
         errmsg("cannot extend file \"%s\" beyond %u blocks",
575
0
            relpath(reln->smgr_rlocator, forknum).str,
576
0
            InvalidBlockNumber)));
577
578
0
  while (remblocks > 0)
579
0
  {
580
0
    BlockNumber segstartblock = curblocknum % ((BlockNumber) RELSEG_SIZE);
581
0
    pgoff_t   seekpos = (pgoff_t) BLCKSZ * segstartblock;
582
0
    int     numblocks;
583
584
0
    if (segstartblock + remblocks > RELSEG_SIZE)
585
0
      numblocks = RELSEG_SIZE - segstartblock;
586
0
    else
587
0
      numblocks = remblocks;
588
589
0
    v = _mdfd_getseg(reln, forknum, curblocknum, skipFsync, EXTENSION_CREATE);
590
591
0
    Assert(segstartblock < RELSEG_SIZE);
592
0
    Assert(segstartblock + numblocks <= RELSEG_SIZE);
593
594
    /*
595
     * If available and useful, use posix_fallocate() (via
596
     * FileFallocate()) to extend the relation. That's often more
597
     * efficient than using write(), as it commonly won't cause the kernel
598
     * to allocate page cache space for the extended pages.
599
     *
600
     * However, we don't use FileFallocate() for small extensions, as it
601
     * defeats delayed allocation on some filesystems. Not clear where
602
     * that decision should be made though? For now just use a cutoff of
603
     * 8, anything between 4 and 8 worked OK in some local testing.
604
     */
605
0
    if (numblocks > 8 &&
606
0
      file_extend_method != FILE_EXTEND_METHOD_WRITE_ZEROS)
607
0
    {
608
0
      int     ret = 0;
609
610
0
#ifdef HAVE_POSIX_FALLOCATE
611
0
      if (file_extend_method == FILE_EXTEND_METHOD_POSIX_FALLOCATE)
612
0
      {
613
0
        ret = FileFallocate(v->mdfd_vfd,
614
0
                  seekpos, (pgoff_t) BLCKSZ * numblocks,
615
0
                  WAIT_EVENT_DATA_FILE_EXTEND);
616
0
      }
617
0
      else
618
0
#endif
619
0
      {
620
0
        elog(ERROR, "unsupported file_extend_method: %d",
621
0
           file_extend_method);
622
0
      }
623
0
      if (ret != 0)
624
0
      {
625
0
        ereport(ERROR,
626
0
            errcode_for_file_access(),
627
0
            errmsg("could not extend file \"%s\" with FileFallocate(): %m",
628
0
                 FilePathName(v->mdfd_vfd)),
629
0
            errhint("Check free disk space."));
630
0
      }
631
0
    }
632
0
    else
633
0
    {
634
0
      int     ret;
635
636
      /*
637
       * Even if we don't want to use fallocate, we can still extend a
638
       * bit more efficiently than writing each 8kB block individually.
639
       * pg_pwrite_zeros() (via FileZero()) uses pg_pwritev_with_retry()
640
       * to avoid multiple writes or needing a zeroed buffer for the
641
       * whole length of the extension.
642
       */
643
0
      ret = FileZero(v->mdfd_vfd,
644
0
               seekpos, (pgoff_t) BLCKSZ * numblocks,
645
0
               WAIT_EVENT_DATA_FILE_EXTEND);
646
0
      if (ret < 0)
647
0
        ereport(ERROR,
648
0
            errcode_for_file_access(),
649
0
            errmsg("could not extend file \"%s\": %m",
650
0
                 FilePathName(v->mdfd_vfd)),
651
0
            errhint("Check free disk space."));
652
0
    }
653
654
0
    if (!skipFsync && !SmgrIsTemp(reln))
655
0
      register_dirty_segment(reln, forknum, v);
656
657
0
    Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
658
659
0
    remblocks -= numblocks;
660
0
    curblocknum += numblocks;
661
0
  }
662
0
}
663
664
/*
665
 * mdopenfork() -- Open one fork of the specified relation.
666
 *
667
 * Note we only open the first segment, when there are multiple segments.
668
 *
669
 * If first segment is not present, either ereport or return NULL according
670
 * to "behavior".  We treat EXTENSION_CREATE the same as EXTENSION_FAIL;
671
 * EXTENSION_CREATE means it's OK to extend an existing relation, not to
672
 * invent one out of whole cloth.
673
 */
674
static MdfdVec *
675
mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
676
0
{
677
0
  MdfdVec    *mdfd;
678
0
  RelPathStr  path;
679
0
  File    fd;
680
681
  /* No work if already open */
682
0
  if (reln->md_num_open_segs[forknum] > 0)
683
0
    return &reln->md_seg_fds[forknum][0];
684
685
0
  path = relpath(reln->smgr_rlocator, forknum);
686
687
0
  fd = PathNameOpenFile(path.str, _mdfd_open_flags());
688
689
0
  if (fd < 0)
690
0
  {
691
0
    if ((behavior & EXTENSION_RETURN_NULL) &&
692
0
      FILE_POSSIBLY_DELETED(errno))
693
0
      return NULL;
694
0
    ereport(ERROR,
695
0
        (errcode_for_file_access(),
696
0
         errmsg("could not open file \"%s\": %m", path.str)));
697
0
  }
698
699
0
  _fdvec_resize(reln, forknum, 1);
700
0
  mdfd = &reln->md_seg_fds[forknum][0];
701
0
  mdfd->mdfd_vfd = fd;
702
0
  mdfd->mdfd_segno = 0;
703
704
0
  Assert(_mdnblocks(reln, forknum, mdfd) <= ((BlockNumber) RELSEG_SIZE));
705
706
0
  return mdfd;
707
0
}
708
709
/*
710
 * mdopen() -- Initialize newly-opened relation.
711
 */
712
void
713
mdopen(SMgrRelation reln)
714
0
{
715
  /* mark it not open */
716
0
  for (int forknum = 0; forknum <= MAX_FORKNUM; forknum++)
717
0
    reln->md_num_open_segs[forknum] = 0;
718
0
}
719
720
/*
721
 * mdclose() -- Close the specified relation, if it isn't closed already.
722
 */
723
void
724
mdclose(SMgrRelation reln, ForkNumber forknum)
725
0
{
726
0
  int     nopensegs = reln->md_num_open_segs[forknum];
727
728
  /* No work if already closed */
729
0
  if (nopensegs == 0)
730
0
    return;
731
732
  /* close segments starting from the end */
733
0
  while (nopensegs > 0)
734
0
  {
735
0
    MdfdVec    *v = &reln->md_seg_fds[forknum][nopensegs - 1];
736
737
0
    FileClose(v->mdfd_vfd);
738
0
    _fdvec_resize(reln, forknum, nopensegs - 1);
739
0
    nopensegs--;
740
0
  }
741
0
}
742
743
/*
744
 * mdprefetch() -- Initiate asynchronous read of the specified blocks of a relation
745
 */
746
bool
747
mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
748
       int nblocks)
749
0
{
750
0
#ifdef USE_PREFETCH
751
752
0
  Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
753
754
0
  if ((uint64) blocknum + nblocks > (uint64) MaxBlockNumber + 1)
755
0
    return false;
756
757
0
  while (nblocks > 0)
758
0
  {
759
0
    pgoff_t   seekpos;
760
0
    MdfdVec    *v;
761
0
    int     nblocks_this_segment;
762
763
0
    v = _mdfd_getseg(reln, forknum, blocknum, false,
764
0
             InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
765
0
    if (v == NULL)
766
0
      return false;
767
768
0
    seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
769
770
0
    Assert(seekpos < (pgoff_t) BLCKSZ * RELSEG_SIZE);
771
772
0
    nblocks_this_segment =
773
0
      Min(nblocks,
774
0
        RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
775
776
0
    (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ * nblocks_this_segment,
777
0
              WAIT_EVENT_DATA_FILE_PREFETCH);
778
779
0
    blocknum += nblocks_this_segment;
780
0
    nblocks -= nblocks_this_segment;
781
0
  }
782
0
#endif              /* USE_PREFETCH */
783
784
0
  return true;
785
0
}
786
787
/*
788
 * Convert an array of buffer address into an array of iovec objects, and
789
 * return the number that were required.  'iov' must have enough space for up
790
 * to 'nblocks' elements, but the number used may be less depending on
791
 * merging.  In the case of a run of fully contiguous buffers, a single iovec
792
 * will be populated that can be handled as a plain non-vectored I/O.
793
 */
794
static int
795
buffers_to_iovec(struct iovec *iov, void **buffers, int nblocks)
796
0
{
797
0
  struct iovec *iovp;
798
0
  int     iovcnt;
799
800
0
  Assert(nblocks >= 1);
801
802
  /* If this build supports direct I/O, buffers must be I/O aligned. */
803
0
  for (int i = 0; i < nblocks; ++i)
804
0
  {
805
0
    if (PG_O_DIRECT != 0 && PG_IO_ALIGN_SIZE <= BLCKSZ)
806
0
      Assert((uintptr_t) buffers[i] ==
807
0
           TYPEALIGN(PG_IO_ALIGN_SIZE, buffers[i]));
808
0
  }
809
810
  /* Start the first iovec off with the first buffer. */
811
0
  iovp = &iov[0];
812
0
  iovp->iov_base = buffers[0];
813
0
  iovp->iov_len = BLCKSZ;
814
0
  iovcnt = 1;
815
816
  /* Try to merge the rest. */
817
0
  for (int i = 1; i < nblocks; ++i)
818
0
  {
819
0
    void     *buffer = buffers[i];
820
821
0
    if (((char *) iovp->iov_base + iovp->iov_len) == buffer)
822
0
    {
823
      /* Contiguous with the last iovec. */
824
0
      iovp->iov_len += BLCKSZ;
825
0
    }
826
0
    else
827
0
    {
828
      /* Need a new iovec. */
829
0
      iovp++;
830
0
      iovp->iov_base = buffer;
831
0
      iovp->iov_len = BLCKSZ;
832
0
      iovcnt++;
833
0
    }
834
0
  }
835
836
0
  return iovcnt;
837
0
}
838
839
/*
840
 * mdmaxcombine() -- Return the maximum number of total blocks that can be
841
 *         combined with an IO starting at blocknum.
842
 */
843
uint32
844
mdmaxcombine(SMgrRelation reln, ForkNumber forknum,
845
       BlockNumber blocknum)
846
0
{
847
0
  BlockNumber segoff;
848
849
0
  segoff = blocknum % ((BlockNumber) RELSEG_SIZE);
850
851
0
  return RELSEG_SIZE - segoff;
852
0
}
853
854
/*
855
 * mdreadv() -- Read the specified blocks from a relation.
856
 */
857
void
858
mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
859
    void **buffers, BlockNumber nblocks)
860
0
{
861
0
  while (nblocks > 0)
862
0
  {
863
0
    struct iovec iov[PG_IOV_MAX];
864
0
    int     iovcnt;
865
0
    pgoff_t   seekpos;
866
0
    ssize_t   nbytes;
867
0
    MdfdVec    *v;
868
0
    BlockNumber nblocks_this_segment;
869
0
    size_t    transferred_this_segment;
870
0
    size_t    size_this_segment;
871
872
0
    v = _mdfd_getseg(reln, forknum, blocknum, false,
873
0
             EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY);
874
875
0
    seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
876
877
0
    Assert(seekpos < (pgoff_t) BLCKSZ * RELSEG_SIZE);
878
879
0
    nblocks_this_segment =
880
0
      Min(nblocks,
881
0
        RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
882
0
    nblocks_this_segment = Min(nblocks_this_segment, lengthof(iov));
883
884
0
    if (nblocks_this_segment != nblocks)
885
0
      elog(ERROR, "read crosses segment boundary");
886
887
0
    iovcnt = buffers_to_iovec(iov, buffers, nblocks_this_segment);
888
0
    size_this_segment = nblocks_this_segment * BLCKSZ;
889
0
    transferred_this_segment = 0;
890
891
    /*
892
     * Inner loop to continue after a short read.  We'll keep going until
893
     * we hit EOF rather than assuming that a short read means we hit the
894
     * end.
895
     */
896
0
    for (;;)
897
0
    {
898
0
      TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
899
0
                        reln->smgr_rlocator.locator.spcOid,
900
0
                        reln->smgr_rlocator.locator.dbOid,
901
0
                        reln->smgr_rlocator.locator.relNumber,
902
0
                        reln->smgr_rlocator.backend);
903
0
      nbytes = FileReadV(v->mdfd_vfd, iov, iovcnt, seekpos,
904
0
                 WAIT_EVENT_DATA_FILE_READ);
905
0
      TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
906
0
                         reln->smgr_rlocator.locator.spcOid,
907
0
                         reln->smgr_rlocator.locator.dbOid,
908
0
                         reln->smgr_rlocator.locator.relNumber,
909
0
                         reln->smgr_rlocator.backend,
910
0
                         nbytes,
911
0
                         size_this_segment - transferred_this_segment);
912
913
#ifdef SIMULATE_SHORT_READ
914
      nbytes = Min(nbytes, 4096);
915
#endif
916
917
0
      if (nbytes < 0)
918
0
        ereport(ERROR,
919
0
            (errcode_for_file_access(),
920
0
             errmsg("could not read blocks %u..%u in file \"%s\": %m",
921
0
                blocknum,
922
0
                blocknum + nblocks_this_segment - 1,
923
0
                FilePathName(v->mdfd_vfd))));
924
925
0
      if (nbytes == 0)
926
0
      {
927
        /*
928
         * We are at or past EOF, or we read a partial block at EOF.
929
         * Normally this is an error; upper levels should never try to
930
         * read a nonexistent block.  However, if zero_damaged_pages
931
         * is ON or we are InRecovery, we should instead return zeroes
932
         * without complaining.  This allows, for example, the case of
933
         * trying to update a block that was later truncated away.
934
         *
935
         * NB: We think that this codepath is unreachable in recovery
936
         * and incomplete with zero_damaged_pages, as missing segments
937
         * are not created. Putting blocks into the buffer-pool that
938
         * do not exist on disk is rather problematic, as it will not
939
         * be found by scans that rely on smgrnblocks(), as they are
940
         * beyond EOF. It also can cause weird problems with relation
941
         * extension, as relation extension does not expect blocks
942
         * beyond EOF to exist.
943
         *
944
         * Therefore we do not want to copy the logic into
945
         * mdstartreadv(), where it would have to be more complicated
946
         * due to potential differences in the zero_damaged_pages
947
         * setting between the definer and completor of IO.
948
         *
949
         * For PG 18, we are putting an Assert(false) in mdreadv()
950
         * (triggering failures in assertion-enabled builds, but
951
         * continuing to work in production builds). Afterwards we
952
         * plan to remove this code entirely.
953
         */
954
0
        if (zero_damaged_pages || InRecovery)
955
0
        {
956
0
          Assert(false);  /* see comment above */
957
958
0
          for (BlockNumber i = transferred_this_segment / BLCKSZ;
959
0
             i < nblocks_this_segment;
960
0
             ++i)
961
0
            memset(buffers[i], 0, BLCKSZ);
962
0
          break;
963
0
        }
964
0
        else
965
0
          ereport(ERROR,
966
0
              (errcode(ERRCODE_DATA_CORRUPTED),
967
0
               errmsg("could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes",
968
0
                  blocknum,
969
0
                  blocknum + nblocks_this_segment - 1,
970
0
                  FilePathName(v->mdfd_vfd),
971
0
                  transferred_this_segment,
972
0
                  size_this_segment)));
973
0
      }
974
975
      /* One loop should usually be enough. */
976
0
      transferred_this_segment += nbytes;
977
0
      Assert(transferred_this_segment <= size_this_segment);
978
0
      if (transferred_this_segment == size_this_segment)
979
0
        break;
980
981
      /* Adjust position and vectors after a short read. */
982
0
      seekpos += nbytes;
983
0
      iovcnt = compute_remaining_iovec(iov, iov, iovcnt, nbytes);
984
0
    }
985
986
0
    nblocks -= nblocks_this_segment;
987
0
    buffers += nblocks_this_segment;
988
0
    blocknum += nblocks_this_segment;
989
0
  }
990
0
}
991
992
/*
993
 * mdstartreadv() -- Asynchronous version of mdreadv().
994
 */
995
void
996
mdstartreadv(PgAioHandle *ioh,
997
       SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
998
       void **buffers, BlockNumber nblocks)
999
0
{
1000
0
  pgoff_t   seekpos;
1001
0
  MdfdVec    *v;
1002
0
  BlockNumber nblocks_this_segment;
1003
0
  struct iovec *iov;
1004
0
  int     iovcnt;
1005
0
  int     ret;
1006
1007
0
  v = _mdfd_getseg(reln, forknum, blocknum, false,
1008
0
           EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY);
1009
1010
0
  seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
1011
1012
0
  Assert(seekpos < (pgoff_t) BLCKSZ * RELSEG_SIZE);
1013
1014
0
  nblocks_this_segment =
1015
0
    Min(nblocks,
1016
0
      RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
1017
1018
0
  if (nblocks_this_segment != nblocks)
1019
0
    elog(ERROR, "read crossing segment boundary");
1020
1021
0
  iovcnt = pgaio_io_get_iovec(ioh, &iov);
1022
1023
0
  Assert(nblocks <= iovcnt);
1024
1025
0
  iovcnt = buffers_to_iovec(iov, buffers, nblocks_this_segment);
1026
1027
0
  Assert(iovcnt <= nblocks_this_segment);
1028
1029
0
  if (!(io_direct_flags & IO_DIRECT_DATA))
1030
0
    pgaio_io_set_flag(ioh, PGAIO_HF_BUFFERED);
1031
1032
0
  pgaio_io_set_target_smgr(ioh,
1033
0
               reln,
1034
0
               forknum,
1035
0
               blocknum,
1036
0
               nblocks,
1037
0
               false);
1038
0
  pgaio_io_register_callbacks(ioh, PGAIO_HCB_MD_READV, 0);
1039
1040
0
  ret = FileStartReadV(ioh, v->mdfd_vfd, iovcnt, seekpos, WAIT_EVENT_DATA_FILE_READ);
1041
0
  if (ret != 0)
1042
0
    ereport(ERROR,
1043
0
        (errcode_for_file_access(),
1044
0
         errmsg("could not start reading blocks %u..%u in file \"%s\": %m",
1045
0
            blocknum,
1046
0
            blocknum + nblocks_this_segment - 1,
1047
0
            FilePathName(v->mdfd_vfd))));
1048
1049
  /*
1050
   * The error checks corresponding to the post-read checks in mdreadv() are
1051
   * in md_readv_complete().
1052
   *
1053
   * However we chose, at least for now, to not implement the
1054
   * zero_damaged_pages logic present in mdreadv(). As outlined in mdreadv()
1055
   * that logic is rather problematic, and we want to get rid of it. Here
1056
   * equivalent logic would have to be more complicated due to potential
1057
   * differences in the zero_damaged_pages setting between the definer and
1058
   * completor of IO.
1059
   */
1060
0
}
1061
1062
/*
1063
 * mdwritev() -- Write the supplied blocks at the appropriate location.
1064
 *
1065
 * This is to be used only for updating already-existing blocks of a
1066
 * relation (ie, those before the current EOF).  To extend a relation,
1067
 * use mdextend().
1068
 */
1069
void
1070
mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
1071
     const void **buffers, BlockNumber nblocks, bool skipFsync)
1072
0
{
1073
  /* This assert is too expensive to have on normally ... */
1074
#ifdef CHECK_WRITE_VS_EXTEND
1075
  Assert((uint64) blocknum + (uint64) nblocks <= (uint64) mdnblocks(reln, forknum));
1076
#endif
1077
1078
0
  while (nblocks > 0)
1079
0
  {
1080
0
    struct iovec iov[PG_IOV_MAX];
1081
0
    int     iovcnt;
1082
0
    pgoff_t   seekpos;
1083
0
    ssize_t   nbytes;
1084
0
    MdfdVec    *v;
1085
0
    BlockNumber nblocks_this_segment;
1086
0
    size_t    transferred_this_segment;
1087
0
    size_t    size_this_segment;
1088
1089
0
    v = _mdfd_getseg(reln, forknum, blocknum, skipFsync,
1090
0
             EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY);
1091
1092
0
    seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
1093
1094
0
    Assert(seekpos < (pgoff_t) BLCKSZ * RELSEG_SIZE);
1095
1096
0
    nblocks_this_segment =
1097
0
      Min(nblocks,
1098
0
        RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
1099
0
    nblocks_this_segment = Min(nblocks_this_segment, lengthof(iov));
1100
1101
0
    if (nblocks_this_segment != nblocks)
1102
0
      elog(ERROR, "write crosses segment boundary");
1103
1104
0
    iovcnt = buffers_to_iovec(iov, unconstify(void **, buffers), nblocks_this_segment);
1105
0
    size_this_segment = nblocks_this_segment * BLCKSZ;
1106
0
    transferred_this_segment = 0;
1107
1108
    /*
1109
     * Inner loop to continue after a short write.  If the reason is that
1110
     * we're out of disk space, a future attempt should get an ENOSPC
1111
     * error from the kernel.
1112
     */
1113
0
    for (;;)
1114
0
    {
1115
0
      TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
1116
0
                         reln->smgr_rlocator.locator.spcOid,
1117
0
                         reln->smgr_rlocator.locator.dbOid,
1118
0
                         reln->smgr_rlocator.locator.relNumber,
1119
0
                         reln->smgr_rlocator.backend);
1120
0
      nbytes = FileWriteV(v->mdfd_vfd, iov, iovcnt, seekpos,
1121
0
                WAIT_EVENT_DATA_FILE_WRITE);
1122
0
      TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
1123
0
                        reln->smgr_rlocator.locator.spcOid,
1124
0
                        reln->smgr_rlocator.locator.dbOid,
1125
0
                        reln->smgr_rlocator.locator.relNumber,
1126
0
                        reln->smgr_rlocator.backend,
1127
0
                        nbytes,
1128
0
                        size_this_segment - transferred_this_segment);
1129
1130
#ifdef SIMULATE_SHORT_WRITE
1131
      nbytes = Min(nbytes, 4096);
1132
#endif
1133
1134
0
      if (nbytes < 0)
1135
0
      {
1136
0
        bool    enospc = errno == ENOSPC;
1137
1138
0
        ereport(ERROR,
1139
0
            (errcode_for_file_access(),
1140
0
             errmsg("could not write blocks %u..%u in file \"%s\": %m",
1141
0
                blocknum,
1142
0
                blocknum + nblocks_this_segment - 1,
1143
0
                FilePathName(v->mdfd_vfd)),
1144
0
             enospc ? errhint("Check free disk space.") : 0));
1145
0
      }
1146
1147
      /* One loop should usually be enough. */
1148
0
      transferred_this_segment += nbytes;
1149
0
      Assert(transferred_this_segment <= size_this_segment);
1150
0
      if (transferred_this_segment == size_this_segment)
1151
0
        break;
1152
1153
      /* Adjust position and iovecs after a short write. */
1154
0
      seekpos += nbytes;
1155
0
      iovcnt = compute_remaining_iovec(iov, iov, iovcnt, nbytes);
1156
0
    }
1157
1158
0
    if (!skipFsync && !SmgrIsTemp(reln))
1159
0
      register_dirty_segment(reln, forknum, v);
1160
1161
0
    nblocks -= nblocks_this_segment;
1162
0
    buffers += nblocks_this_segment;
1163
0
    blocknum += nblocks_this_segment;
1164
0
  }
1165
0
}
1166
1167
1168
/*
1169
 * mdwriteback() -- Tell the kernel to write pages back to storage.
1170
 *
1171
 * This accepts a range of blocks because flushing several pages at once is
1172
 * considerably more efficient than doing so individually.
1173
 */
1174
void
1175
mdwriteback(SMgrRelation reln, ForkNumber forknum,
1176
      BlockNumber blocknum, BlockNumber nblocks)
1177
0
{
1178
0
  Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
1179
1180
  /*
1181
   * Issue flush requests in as few requests as possible; have to split at
1182
   * segment boundaries though, since those are actually separate files.
1183
   */
1184
0
  while (nblocks > 0)
1185
0
  {
1186
0
    BlockNumber nflush = nblocks;
1187
0
    pgoff_t   seekpos;
1188
0
    MdfdVec    *v;
1189
0
    int     segnum_start,
1190
0
          segnum_end;
1191
1192
0
    v = _mdfd_getseg(reln, forknum, blocknum, true /* not used */ ,
1193
0
             EXTENSION_DONT_OPEN);
1194
1195
    /*
1196
     * We might be flushing buffers of already removed relations, that's
1197
     * ok, just ignore that case.  If the segment file wasn't open already
1198
     * (ie from a recent mdwrite()), then we don't want to re-open it, to
1199
     * avoid a race with PROCSIGNAL_BARRIER_SMGRRELEASE that might leave
1200
     * us with a descriptor to a file that is about to be unlinked.
1201
     */
1202
0
    if (!v)
1203
0
      return;
1204
1205
    /* compute offset inside the current segment */
1206
0
    segnum_start = blocknum / RELSEG_SIZE;
1207
1208
    /* compute number of desired writes within the current segment */
1209
0
    segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
1210
0
    if (segnum_start != segnum_end)
1211
0
      nflush = RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE));
1212
1213
0
    Assert(nflush >= 1);
1214
0
    Assert(nflush <= nblocks);
1215
1216
0
    seekpos = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
1217
1218
0
    FileWriteback(v->mdfd_vfd, seekpos, (pgoff_t) BLCKSZ * nflush, WAIT_EVENT_DATA_FILE_FLUSH);
1219
1220
0
    nblocks -= nflush;
1221
0
    blocknum += nflush;
1222
0
  }
1223
0
}
1224
1225
/*
1226
 * mdnblocks() -- Get the number of blocks stored in a relation.
1227
 *
1228
 * Important side effect: all active segments of the relation are opened
1229
 * and added to the md_seg_fds array.  If this routine has not been
1230
 * called, then only segments up to the last one actually touched
1231
 * are present in the array.
1232
 */
1233
BlockNumber
1234
mdnblocks(SMgrRelation reln, ForkNumber forknum)
1235
0
{
1236
0
  MdfdVec    *v;
1237
0
  BlockNumber nblocks;
1238
0
  BlockNumber segno;
1239
1240
0
  mdopenfork(reln, forknum, EXTENSION_FAIL);
1241
1242
  /* mdopen has opened the first segment */
1243
0
  Assert(reln->md_num_open_segs[forknum] > 0);
1244
1245
  /*
1246
   * Start from the last open segments, to avoid redundant seeks.  We have
1247
   * previously verified that these segments are exactly RELSEG_SIZE long,
1248
   * and it's useless to recheck that each time.
1249
   *
1250
   * NOTE: this assumption could only be wrong if another backend has
1251
   * truncated the relation.  We rely on higher code levels to handle that
1252
   * scenario by closing and re-opening the md fd, which is handled via
1253
   * relcache flush.  (Since the checkpointer doesn't participate in
1254
   * relcache flush, it could have segment entries for inactive segments;
1255
   * that's OK because the checkpointer never needs to compute relation
1256
   * size.)
1257
   */
1258
0
  segno = reln->md_num_open_segs[forknum] - 1;
1259
0
  v = &reln->md_seg_fds[forknum][segno];
1260
1261
0
  for (;;)
1262
0
  {
1263
0
    nblocks = _mdnblocks(reln, forknum, v);
1264
0
    if (nblocks > ((BlockNumber) RELSEG_SIZE))
1265
0
      elog(FATAL, "segment too big");
1266
0
    if (nblocks < ((BlockNumber) RELSEG_SIZE))
1267
0
      return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;
1268
1269
    /*
1270
     * If segment is exactly RELSEG_SIZE, advance to next one.
1271
     */
1272
0
    segno++;
1273
1274
    /*
1275
     * We used to pass O_CREAT here, but that has the disadvantage that it
1276
     * might create a segment which has vanished through some operating
1277
     * system misadventure.  In such a case, creating the segment here
1278
     * undermines _mdfd_getseg's attempts to notice and report an error
1279
     * upon access to a missing segment.
1280
     */
1281
0
    v = _mdfd_openseg(reln, forknum, segno, 0);
1282
0
    if (v == NULL)
1283
0
      return segno * ((BlockNumber) RELSEG_SIZE);
1284
0
  }
1285
0
}
1286
1287
/*
1288
 * mdtruncate() -- Truncate relation to specified number of blocks.
1289
 *
1290
 * Guaranteed not to allocate memory, so it can be used in a critical section.
1291
 * Caller must have called smgrnblocks() to obtain curnblk while holding a
1292
 * sufficient lock to prevent a change in relation size, and not used any smgr
1293
 * functions for this relation or handled interrupts in between.  This makes
1294
 * sure we have opened all active segments, so that truncate loop will get
1295
 * them all!
1296
 *
1297
 * If nblocks > curnblk, the request is ignored when we are InRecovery,
1298
 * otherwise, an error is raised.
1299
 */
1300
void
1301
mdtruncate(SMgrRelation reln, ForkNumber forknum,
1302
       BlockNumber curnblk, BlockNumber nblocks)
1303
0
{
1304
0
  BlockNumber priorblocks;
1305
0
  int     curopensegs;
1306
1307
0
  if (nblocks > curnblk)
1308
0
  {
1309
    /* Bogus request ... but no complaint if InRecovery */
1310
0
    if (InRecovery)
1311
0
      return;
1312
0
    ereport(ERROR,
1313
0
        (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
1314
0
            relpath(reln->smgr_rlocator, forknum).str,
1315
0
            nblocks, curnblk)));
1316
0
  }
1317
0
  if (nblocks == curnblk)
1318
0
    return;         /* no work */
1319
1320
  /*
1321
   * Truncate segments, starting at the last one. Starting at the end makes
1322
   * managing the memory for the fd array easier, should there be errors.
1323
   */
1324
0
  curopensegs = reln->md_num_open_segs[forknum];
1325
0
  while (curopensegs > 0)
1326
0
  {
1327
0
    MdfdVec    *v;
1328
1329
0
    priorblocks = (curopensegs - 1) * RELSEG_SIZE;
1330
1331
0
    v = &reln->md_seg_fds[forknum][curopensegs - 1];
1332
1333
0
    if (priorblocks > nblocks)
1334
0
    {
1335
      /*
1336
       * This segment is no longer active. We truncate the file, but do
1337
       * not delete it, for reasons explained in the header comments.
1338
       */
1339
0
      if (FileTruncate(v->mdfd_vfd, 0, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0)
1340
0
        ereport(ERROR,
1341
0
            (errcode_for_file_access(),
1342
0
             errmsg("could not truncate file \"%s\": %m",
1343
0
                FilePathName(v->mdfd_vfd))));
1344
1345
0
      if (!SmgrIsTemp(reln))
1346
0
        register_dirty_segment(reln, forknum, v);
1347
1348
      /* we never drop the 1st segment */
1349
0
      Assert(v != &reln->md_seg_fds[forknum][0]);
1350
1351
0
      FileClose(v->mdfd_vfd);
1352
0
      _fdvec_resize(reln, forknum, curopensegs - 1);
1353
0
    }
1354
0
    else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
1355
0
    {
1356
      /*
1357
       * This is the last segment we want to keep. Truncate the file to
1358
       * the right length. NOTE: if nblocks is exactly a multiple K of
1359
       * RELSEG_SIZE, we will truncate the K+1st segment to 0 length but
1360
       * keep it. This adheres to the invariant given in the header
1361
       * comments.
1362
       */
1363
0
      BlockNumber lastsegblocks = nblocks - priorblocks;
1364
1365
0
      if (FileTruncate(v->mdfd_vfd, (pgoff_t) lastsegblocks * BLCKSZ, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0)
1366
0
        ereport(ERROR,
1367
0
            (errcode_for_file_access(),
1368
0
             errmsg("could not truncate file \"%s\" to %u blocks: %m",
1369
0
                FilePathName(v->mdfd_vfd),
1370
0
                nblocks)));
1371
0
      if (!SmgrIsTemp(reln))
1372
0
        register_dirty_segment(reln, forknum, v);
1373
0
    }
1374
0
    else
1375
0
    {
1376
      /*
1377
       * We still need this segment, so nothing to do for this and any
1378
       * earlier segment.
1379
       */
1380
0
      break;
1381
0
    }
1382
0
    curopensegs--;
1383
0
  }
1384
0
}
1385
1386
/*
1387
 * mdregistersync() -- Mark whole relation as needing fsync
1388
 */
1389
void
1390
mdregistersync(SMgrRelation reln, ForkNumber forknum)
1391
0
{
1392
0
  int     segno;
1393
0
  int     min_inactive_seg;
1394
1395
  /*
1396
   * NOTE: mdnblocks makes sure we have opened all active segments, so that
1397
   * the loop below will get them all!
1398
   */
1399
0
  mdnblocks(reln, forknum);
1400
1401
0
  min_inactive_seg = segno = reln->md_num_open_segs[forknum];
1402
1403
  /*
1404
   * Temporarily open inactive segments, then close them after sync.  There
1405
   * may be some inactive segments left opened after error, but that is
1406
   * harmless.  We don't bother to clean them up and take a risk of further
1407
   * trouble.  The next mdclose() will soon close them.
1408
   */
1409
0
  while (_mdfd_openseg(reln, forknum, segno, 0) != NULL)
1410
0
    segno++;
1411
1412
0
  while (segno > 0)
1413
0
  {
1414
0
    MdfdVec    *v = &reln->md_seg_fds[forknum][segno - 1];
1415
1416
0
    register_dirty_segment(reln, forknum, v);
1417
1418
    /* Close inactive segments immediately */
1419
0
    if (segno > min_inactive_seg)
1420
0
    {
1421
0
      FileClose(v->mdfd_vfd);
1422
0
      _fdvec_resize(reln, forknum, segno - 1);
1423
0
    }
1424
1425
0
    segno--;
1426
0
  }
1427
0
}
1428
1429
/*
1430
 * mdimmedsync() -- Immediately sync a relation to stable storage.
1431
 *
1432
 * Note that only writes already issued are synced; this routine knows
1433
 * nothing of dirty buffers that may exist inside the buffer manager.  We
1434
 * sync active and inactive segments; smgrDoPendingSyncs() relies on this.
1435
 * Consider a relation skipping WAL.  Suppose a checkpoint syncs blocks of
1436
 * some segment, then mdtruncate() renders that segment inactive.  If we
1437
 * crash before the next checkpoint syncs the newly-inactive segment, that
1438
 * segment may survive recovery, reintroducing unwanted data into the table.
1439
 */
1440
void
1441
mdimmedsync(SMgrRelation reln, ForkNumber forknum)
1442
0
{
1443
0
  int     segno;
1444
0
  int     min_inactive_seg;
1445
1446
  /*
1447
   * NOTE: mdnblocks makes sure we have opened all active segments, so that
1448
   * the loop below will get them all!
1449
   */
1450
0
  mdnblocks(reln, forknum);
1451
1452
0
  min_inactive_seg = segno = reln->md_num_open_segs[forknum];
1453
1454
  /*
1455
   * Temporarily open inactive segments, then close them after sync.  There
1456
   * may be some inactive segments left opened after fsync() error, but that
1457
   * is harmless.  We don't bother to clean them up and take a risk of
1458
   * further trouble.  The next mdclose() will soon close them.
1459
   */
1460
0
  while (_mdfd_openseg(reln, forknum, segno, 0) != NULL)
1461
0
    segno++;
1462
1463
0
  while (segno > 0)
1464
0
  {
1465
0
    MdfdVec    *v = &reln->md_seg_fds[forknum][segno - 1];
1466
1467
    /*
1468
     * fsyncs done through mdimmedsync() should be tracked in a separate
1469
     * IOContext than those done through mdsyncfiletag() to differentiate
1470
     * between unavoidable client backend fsyncs (e.g. those done during
1471
     * index build) and those which ideally would have been done by the
1472
     * checkpointer. Since other IO operations bypassing the buffer
1473
     * manager could also be tracked in such an IOContext, wait until
1474
     * these are also tracked to track immediate fsyncs.
1475
     */
1476
0
    if (FileSync(v->mdfd_vfd, WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC) < 0)
1477
0
      ereport(data_sync_elevel(ERROR),
1478
0
          (errcode_for_file_access(),
1479
0
           errmsg("could not fsync file \"%s\": %m",
1480
0
              FilePathName(v->mdfd_vfd))));
1481
1482
    /* Close inactive segments immediately */
1483
0
    if (segno > min_inactive_seg)
1484
0
    {
1485
0
      FileClose(v->mdfd_vfd);
1486
0
      _fdvec_resize(reln, forknum, segno - 1);
1487
0
    }
1488
1489
0
    segno--;
1490
0
  }
1491
0
}
1492
1493
int
1494
mdfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off)
1495
0
{
1496
0
  MdfdVec    *v = mdopenfork(reln, forknum, EXTENSION_FAIL);
1497
1498
0
  v = _mdfd_getseg(reln, forknum, blocknum, false,
1499
0
           EXTENSION_FAIL);
1500
1501
0
  *off = (pgoff_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
1502
1503
0
  Assert(*off < (pgoff_t) BLCKSZ * RELSEG_SIZE);
1504
1505
0
  return FileGetRawDesc(v->mdfd_vfd);
1506
0
}
1507
1508
/*
1509
 * register_dirty_segment() -- Mark a relation segment as needing fsync
1510
 *
1511
 * If there is a local pending-ops table, just make an entry in it for
1512
 * ProcessSyncRequests to process later.  Otherwise, try to pass off the
1513
 * fsync request to the checkpointer process.  If that fails, just do the
1514
 * fsync locally before returning (we hope this will not happen often
1515
 * enough to be a performance problem).
1516
 */
1517
static void
1518
register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
1519
0
{
1520
0
  FileTag   tag;
1521
1522
0
  INIT_MD_FILETAG(tag, reln->smgr_rlocator.locator, forknum, seg->mdfd_segno);
1523
1524
  /* Temp relations should never be fsync'd */
1525
0
  Assert(!SmgrIsTemp(reln));
1526
1527
0
  if (!RegisterSyncRequest(&tag, SYNC_REQUEST, false /* retryOnError */ ))
1528
0
  {
1529
0
    instr_time  io_start;
1530
1531
0
    ereport(DEBUG1,
1532
0
        (errmsg_internal("could not forward fsync request because request queue is full")));
1533
1534
0
    io_start = pgstat_prepare_io_time(track_io_timing);
1535
1536
0
    if (FileSync(seg->mdfd_vfd, WAIT_EVENT_DATA_FILE_SYNC) < 0)
1537
0
      ereport(data_sync_elevel(ERROR),
1538
0
          (errcode_for_file_access(),
1539
0
           errmsg("could not fsync file \"%s\": %m",
1540
0
              FilePathName(seg->mdfd_vfd))));
1541
1542
    /*
1543
     * We have no way of knowing if the current IOContext is
1544
     * IOCONTEXT_NORMAL or IOCONTEXT_[BULKREAD, BULKWRITE, VACUUM] at this
1545
     * point, so count the fsync as being in the IOCONTEXT_NORMAL
1546
     * IOContext. This is probably okay, because the number of backend
1547
     * fsyncs doesn't say anything about the efficacy of the
1548
     * BufferAccessStrategy. And counting both fsyncs done in
1549
     * IOCONTEXT_NORMAL and IOCONTEXT_[BULKREAD, BULKWRITE, VACUUM] under
1550
     * IOCONTEXT_NORMAL is likely clearer when investigating the number of
1551
     * backend fsyncs.
1552
     */
1553
0
    pgstat_count_io_op_time(IOOBJECT_RELATION, IOCONTEXT_NORMAL,
1554
0
                IOOP_FSYNC, io_start, 1, 0);
1555
0
  }
1556
0
}
1557
1558
/*
1559
 * register_unlink_tombstone() -- Schedule a tombstone file to be deleted
1560
 *
1561
 * A tombstone file is an empty first segment of a relation that has already
1562
 * been dropped (see mdunlink()).  This function schedules it to be deleted
1563
 * after the next checkpoint.
1564
 */
1565
static void
1566
register_unlink_tombstone(RelFileLocatorBackend rlocator)
1567
0
{
1568
0
  FileTag   tag;
1569
1570
0
  INIT_MD_FILETAG(tag, rlocator.locator, MAIN_FORKNUM, 0);
1571
1572
  /* Should never be used with temp relations */
1573
0
  Assert(!RelFileLocatorBackendIsTemp(rlocator));
1574
1575
0
  RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ );
1576
0
}
1577
1578
/*
1579
 * register_forget_request() -- forget any fsyncs for a relation fork's segment
1580
 */
1581
static void
1582
register_forget_request(RelFileLocatorBackend rlocator, ForkNumber forknum,
1583
            BlockNumber segno)
1584
0
{
1585
0
  FileTag   tag;
1586
1587
0
  INIT_MD_FILETAG(tag, rlocator.locator, forknum, segno);
1588
1589
0
  RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */ );
1590
0
}
1591
1592
/*
1593
 * ForgetDatabaseSyncRequests -- forget any fsyncs and unlinks for a DB
1594
 */
1595
void
1596
ForgetDatabaseSyncRequests(Oid dbid)
1597
0
{
1598
0
  FileTag   tag;
1599
0
  RelFileLocator rlocator;
1600
1601
0
  rlocator.dbOid = dbid;
1602
0
  rlocator.spcOid = 0;
1603
0
  rlocator.relNumber = 0;
1604
1605
0
  INIT_MD_FILETAG(tag, rlocator, InvalidForkNumber, InvalidBlockNumber);
1606
1607
0
  RegisterSyncRequest(&tag, SYNC_FILTER_REQUEST, true /* retryOnError */ );
1608
0
}
1609
1610
/*
1611
 * DropRelationFiles -- drop files of all given relations
1612
 */
1613
void
1614
DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
1615
0
{
1616
0
  SMgrRelation *srels;
1617
0
  int     i;
1618
1619
0
  srels = palloc_array(SMgrRelation, ndelrels);
1620
0
  for (i = 0; i < ndelrels; i++)
1621
0
  {
1622
0
    SMgrRelation srel = smgropen(delrels[i], INVALID_PROC_NUMBER);
1623
1624
0
    if (isRedo)
1625
0
    {
1626
0
      ForkNumber  fork;
1627
1628
0
      for (fork = 0; fork <= MAX_FORKNUM; fork++)
1629
0
        XLogDropRelation(delrels[i], fork);
1630
0
    }
1631
0
    srels[i] = srel;
1632
0
  }
1633
1634
0
  smgrdounlinkall(srels, ndelrels, isRedo);
1635
1636
0
  for (i = 0; i < ndelrels; i++)
1637
0
    smgrclose(srels[i]);
1638
0
  pfree(srels);
1639
0
}
1640
1641
1642
/*
1643
 * _fdvec_resize() -- Resize the fork's open segments array
1644
 */
1645
static void
1646
_fdvec_resize(SMgrRelation reln,
1647
        ForkNumber forknum,
1648
        int nseg)
1649
0
{
1650
0
  if (nseg == 0)
1651
0
  {
1652
0
    if (reln->md_num_open_segs[forknum] > 0)
1653
0
    {
1654
0
      pfree(reln->md_seg_fds[forknum]);
1655
0
      reln->md_seg_fds[forknum] = NULL;
1656
0
    }
1657
0
  }
1658
0
  else if (reln->md_num_open_segs[forknum] == 0)
1659
0
  {
1660
0
    reln->md_seg_fds[forknum] =
1661
0
      MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg);
1662
0
  }
1663
0
  else if (nseg > reln->md_num_open_segs[forknum])
1664
0
  {
1665
    /*
1666
     * It doesn't seem worthwhile complicating the code to amortize
1667
     * repalloc() calls.  Those are far faster than PathNameOpenFile() or
1668
     * FileClose(), and the memory context internally will sometimes avoid
1669
     * doing an actual reallocation.
1670
     */
1671
0
    reln->md_seg_fds[forknum] = repalloc_array(reln->md_seg_fds[forknum], MdfdVec, nseg);
1672
0
  }
1673
0
  else
1674
0
  {
1675
    /*
1676
     * We don't reallocate a smaller array, because we want mdtruncate()
1677
     * to be able to promise that it won't allocate memory, so that it is
1678
     * allowed in a critical section.  This means that a bit of space in
1679
     * the array is now wasted, until the next time we add a segment and
1680
     * reallocate.
1681
     */
1682
0
  }
1683
1684
0
  reln->md_num_open_segs[forknum] = nseg;
1685
0
}
1686
1687
/*
1688
 * Return the filename for the specified segment of the relation. The
1689
 * returned string is palloc'd.
1690
 */
1691
static MdPathStr
1692
_mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
1693
0
{
1694
0
  RelPathStr  path;
1695
0
  MdPathStr fullpath;
1696
1697
0
  path = relpath(reln->smgr_rlocator, forknum);
1698
1699
0
  if (segno > 0)
1700
0
    sprintf(fullpath.str, "%s.%u", path.str, segno);
1701
0
  else
1702
0
    strcpy(fullpath.str, path.str);
1703
1704
0
  return fullpath;
1705
0
}
1706
1707
/*
1708
 * Open the specified segment of the relation,
1709
 * and make a MdfdVec object for it.  Returns NULL on failure.
1710
 */
1711
static MdfdVec *
1712
_mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
1713
        int oflags)
1714
0
{
1715
0
  MdfdVec    *v;
1716
0
  File    fd;
1717
0
  MdPathStr fullpath;
1718
1719
0
  fullpath = _mdfd_segpath(reln, forknum, segno);
1720
1721
  /* open the file */
1722
0
  fd = PathNameOpenFile(fullpath.str, _mdfd_open_flags() | oflags);
1723
1724
0
  if (fd < 0)
1725
0
    return NULL;
1726
1727
  /*
1728
   * Segments are always opened in order from lowest to highest, so we must
1729
   * be adding a new one at the end.
1730
   */
1731
0
  Assert(segno == reln->md_num_open_segs[forknum]);
1732
1733
0
  _fdvec_resize(reln, forknum, segno + 1);
1734
1735
  /* fill the entry */
1736
0
  v = &reln->md_seg_fds[forknum][segno];
1737
0
  v->mdfd_vfd = fd;
1738
0
  v->mdfd_segno = segno;
1739
1740
0
  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
1741
1742
  /* all done */
1743
0
  return v;
1744
0
}
1745
1746
/*
1747
 * _mdfd_getseg() -- Find the segment of the relation holding the
1748
 *           specified block.
1749
 *
1750
 * If the segment doesn't exist, we ereport, return NULL, or create the
1751
 * segment, according to "behavior".  Note: skipFsync is only used in the
1752
 * EXTENSION_CREATE case.
1753
 */
1754
static MdfdVec *
1755
_mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
1756
       bool skipFsync, int behavior)
1757
0
{
1758
0
  MdfdVec    *v;
1759
0
  BlockNumber targetseg;
1760
0
  BlockNumber nextsegno;
1761
1762
  /* some way to handle non-existent segments needs to be specified */
1763
0
  Assert(behavior &
1764
0
       (EXTENSION_FAIL | EXTENSION_CREATE | EXTENSION_RETURN_NULL |
1765
0
      EXTENSION_DONT_OPEN));
1766
1767
0
  targetseg = blkno / ((BlockNumber) RELSEG_SIZE);
1768
1769
  /* if an existing and opened segment, we're done */
1770
0
  if (targetseg < reln->md_num_open_segs[forknum])
1771
0
  {
1772
0
    v = &reln->md_seg_fds[forknum][targetseg];
1773
0
    return v;
1774
0
  }
1775
1776
  /* The caller only wants the segment if we already had it open. */
1777
0
  if (behavior & EXTENSION_DONT_OPEN)
1778
0
    return NULL;
1779
1780
  /*
1781
   * The target segment is not yet open. Iterate over all the segments
1782
   * between the last opened and the target segment. This way missing
1783
   * segments either raise an error, or get created (according to
1784
   * 'behavior'). Start with either the last opened, or the first segment if
1785
   * none was opened before.
1786
   */
1787
0
  if (reln->md_num_open_segs[forknum] > 0)
1788
0
    v = &reln->md_seg_fds[forknum][reln->md_num_open_segs[forknum] - 1];
1789
0
  else
1790
0
  {
1791
0
    v = mdopenfork(reln, forknum, behavior);
1792
0
    if (!v)
1793
0
      return NULL;   /* if behavior & EXTENSION_RETURN_NULL */
1794
0
  }
1795
1796
0
  for (nextsegno = reln->md_num_open_segs[forknum];
1797
0
     nextsegno <= targetseg; nextsegno++)
1798
0
  {
1799
0
    BlockNumber nblocks = _mdnblocks(reln, forknum, v);
1800
0
    int     flags = 0;
1801
1802
0
    Assert(nextsegno == v->mdfd_segno + 1);
1803
1804
0
    if (nblocks > ((BlockNumber) RELSEG_SIZE))
1805
0
      elog(FATAL, "segment too big");
1806
1807
0
    if ((behavior & EXTENSION_CREATE) ||
1808
0
      (InRecovery && (behavior & EXTENSION_CREATE_RECOVERY)))
1809
0
    {
1810
      /*
1811
       * Normally we will create new segments only if authorized by the
1812
       * caller (i.e., we are doing mdextend()).  But when doing WAL
1813
       * recovery, create segments anyway; this allows cases such as
1814
       * replaying WAL data that has a write into a high-numbered
1815
       * segment of a relation that was later deleted. We want to go
1816
       * ahead and create the segments so we can finish out the replay.
1817
       *
1818
       * We have to maintain the invariant that segments before the last
1819
       * active segment are of size RELSEG_SIZE; therefore, if
1820
       * extending, pad them out with zeroes if needed.  (This only
1821
       * matters if in recovery, or if the caller is extending the
1822
       * relation discontiguously, but that can happen in hash indexes.)
1823
       */
1824
0
      if (nblocks < ((BlockNumber) RELSEG_SIZE))
1825
0
      {
1826
0
        char     *zerobuf = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE,
1827
0
                           MCXT_ALLOC_ZERO);
1828
1829
0
        mdextend(reln, forknum,
1830
0
             nextsegno * ((BlockNumber) RELSEG_SIZE) - 1,
1831
0
             zerobuf, skipFsync);
1832
0
        pfree(zerobuf);
1833
0
      }
1834
0
      flags = O_CREAT;
1835
0
    }
1836
0
    else if (nblocks < ((BlockNumber) RELSEG_SIZE))
1837
0
    {
1838
      /*
1839
       * When not extending, only open the next segment if the current
1840
       * one is exactly RELSEG_SIZE.  If not (this branch), either
1841
       * return NULL or fail.
1842
       */
1843
0
      if (behavior & EXTENSION_RETURN_NULL)
1844
0
      {
1845
        /*
1846
         * Some callers discern between reasons for _mdfd_getseg()
1847
         * returning NULL based on errno. As there's no failing
1848
         * syscall involved in this case, explicitly set errno to
1849
         * ENOENT, as that seems the closest interpretation.
1850
         */
1851
0
        errno = ENOENT;
1852
0
        return NULL;
1853
0
      }
1854
1855
0
      ereport(ERROR,
1856
0
          (errcode_for_file_access(),
1857
0
           errmsg("could not open file \"%s\" (target block %u): previous segment is only %u blocks",
1858
0
              _mdfd_segpath(reln, forknum, nextsegno).str,
1859
0
              blkno, nblocks)));
1860
0
    }
1861
1862
0
    v = _mdfd_openseg(reln, forknum, nextsegno, flags);
1863
1864
0
    if (v == NULL)
1865
0
    {
1866
0
      if ((behavior & EXTENSION_RETURN_NULL) &&
1867
0
        FILE_POSSIBLY_DELETED(errno))
1868
0
        return NULL;
1869
0
      ereport(ERROR,
1870
0
          (errcode_for_file_access(),
1871
0
           errmsg("could not open file \"%s\" (target block %u): %m",
1872
0
              _mdfd_segpath(reln, forknum, nextsegno).str,
1873
0
              blkno)));
1874
0
    }
1875
0
  }
1876
1877
0
  return v;
1878
0
}
1879
1880
/*
1881
 * Get number of blocks present in a single disk file
1882
 */
1883
static BlockNumber
1884
_mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
1885
0
{
1886
0
  pgoff_t   len;
1887
1888
0
  len = FileSize(seg->mdfd_vfd);
1889
0
  if (len < 0)
1890
0
    ereport(ERROR,
1891
0
        (errcode_for_file_access(),
1892
0
         errmsg("could not seek to end of file \"%s\": %m",
1893
0
            FilePathName(seg->mdfd_vfd))));
1894
  /* note that this calculation will ignore any partial block at EOF */
1895
0
  return (BlockNumber) (len / BLCKSZ);
1896
0
}
1897
1898
/*
1899
 * Sync a file to disk, given a file tag.  Write the path into an output
1900
 * buffer so the caller can use it in error messages.
1901
 *
1902
 * Return 0 on success, -1 on failure, with errno set.
1903
 */
1904
int
1905
mdsyncfiletag(const FileTag *ftag, char *path)
1906
0
{
1907
0
  SMgrRelation reln = smgropen(ftag->rlocator, INVALID_PROC_NUMBER);
1908
0
  File    file;
1909
0
  instr_time  io_start;
1910
0
  bool    need_to_close;
1911
0
  int     result,
1912
0
        save_errno;
1913
1914
  /* See if we already have the file open, or need to open it. */
1915
0
  if (ftag->segno < reln->md_num_open_segs[ftag->forknum])
1916
0
  {
1917
0
    file = reln->md_seg_fds[ftag->forknum][ftag->segno].mdfd_vfd;
1918
0
    strlcpy(path, FilePathName(file), MAXPGPATH);
1919
0
    need_to_close = false;
1920
0
  }
1921
0
  else
1922
0
  {
1923
0
    MdPathStr p;
1924
1925
0
    p = _mdfd_segpath(reln, ftag->forknum, ftag->segno);
1926
0
    strlcpy(path, p.str, MD_PATH_STR_MAXLEN);
1927
1928
0
    file = PathNameOpenFile(path, _mdfd_open_flags());
1929
0
    if (file < 0)
1930
0
      return -1;
1931
0
    need_to_close = true;
1932
0
  }
1933
1934
0
  io_start = pgstat_prepare_io_time(track_io_timing);
1935
1936
  /* Sync the file. */
1937
0
  result = FileSync(file, WAIT_EVENT_DATA_FILE_SYNC);
1938
0
  save_errno = errno;
1939
1940
0
  if (need_to_close)
1941
0
    FileClose(file);
1942
1943
0
  pgstat_count_io_op_time(IOOBJECT_RELATION, IOCONTEXT_NORMAL,
1944
0
              IOOP_FSYNC, io_start, 1, 0);
1945
1946
0
  errno = save_errno;
1947
0
  return result;
1948
0
}
1949
1950
/*
1951
 * Unlink a file, given a file tag.  Write the path into an output
1952
 * buffer so the caller can use it in error messages.
1953
 *
1954
 * Return 0 on success, -1 on failure, with errno set.
1955
 */
1956
int
1957
mdunlinkfiletag(const FileTag *ftag, char *path)
1958
0
{
1959
0
  RelPathStr  p;
1960
1961
  /* We only unlink tombstone files through this mechanism */
1962
0
  Assert(ftag->forknum == MAIN_FORKNUM && ftag->segno == 0);
1963
1964
  /* Compute the path. */
1965
0
  p = relpathperm(ftag->rlocator, MAIN_FORKNUM);
1966
0
  strlcpy(path, p.str, MAXPGPATH);
1967
1968
  /* Try to unlink the file. */
1969
0
  return unlink(path);
1970
0
}
1971
1972
/*
1973
 * Check if a given candidate request matches a given tag, when processing
1974
 * a SYNC_FILTER_REQUEST request.  This will be called for all pending
1975
 * requests to find out whether to forget them.
1976
 */
1977
bool
1978
mdfiletagmatches(const FileTag *ftag, const FileTag *candidate)
1979
0
{
1980
  /*
1981
   * For now we only use filter requests as a way to drop all scheduled
1982
   * callbacks relating to a given database, when dropping the database.
1983
   * We'll return true for all candidates that have the same database OID as
1984
   * the ftag from the SYNC_FILTER_REQUEST request, so they're forgotten.
1985
   */
1986
0
  return ftag->rlocator.dbOid == candidate->rlocator.dbOid;
1987
0
}
1988
1989
/*
1990
 * AIO completion callback for mdstartreadv().
1991
 */
1992
static PgAioResult
1993
md_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data)
1994
0
{
1995
0
  PgAioTargetData *td = pgaio_io_get_target_data(ioh);
1996
0
  PgAioResult result = prior_result;
1997
1998
0
  if (prior_result.result < 0)
1999
0
  {
2000
0
    result.status = PGAIO_RS_ERROR;
2001
0
    result.id = PGAIO_HCB_MD_READV;
2002
    /* For "hard" errors, track the error number in error_data */
2003
0
    result.error_data = -prior_result.result;
2004
0
    result.result = 0;
2005
2006
    /*
2007
     * Immediately log a message about the IO error, but only to the
2008
     * server log. The reason to do so immediately is that the originator
2009
     * might not process the query result immediately (because it is busy
2010
     * doing another part of query processing) or at all (e.g. if it was
2011
     * cancelled or errored out due to another IO also failing).  The
2012
     * definer of the IO will emit an ERROR when processing the IO's
2013
     * results
2014
     */
2015
0
    pgaio_result_report(result, td, LOG_SERVER_ONLY);
2016
2017
0
    return result;
2018
0
  }
2019
2020
  /*
2021
   * As explained above smgrstartreadv(), the smgr API operates on the level
2022
   * of blocks, rather than bytes. Convert.
2023
   */
2024
0
  result.result /= BLCKSZ;
2025
2026
0
  Assert(result.result <= td->smgr.nblocks);
2027
2028
0
  if (result.result == 0)
2029
0
  {
2030
    /* consider 0 blocks read a failure */
2031
0
    result.status = PGAIO_RS_ERROR;
2032
0
    result.id = PGAIO_HCB_MD_READV;
2033
0
    result.error_data = 0;
2034
2035
    /* see comment above the "hard error" case */
2036
0
    pgaio_result_report(result, td, LOG_SERVER_ONLY);
2037
2038
0
    return result;
2039
0
  }
2040
2041
0
  if (result.status != PGAIO_RS_ERROR &&
2042
0
    result.result < td->smgr.nblocks)
2043
0
  {
2044
    /* partial reads should be retried at upper level */
2045
0
    result.status = PGAIO_RS_PARTIAL;
2046
0
    result.id = PGAIO_HCB_MD_READV;
2047
0
  }
2048
2049
0
  return result;
2050
0
}
2051
2052
/*
2053
 * AIO error reporting callback for mdstartreadv().
2054
 *
2055
 * Errors are encoded as follows:
2056
 * - PgAioResult.error_data != 0 encodes IO that failed with that errno
2057
 * - PgAioResult.error_data == 0 encodes IO that didn't read all data
2058
 */
2059
static void
2060
md_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel)
2061
0
{
2062
0
  RelPathStr  path;
2063
2064
0
  path = relpathbackend(td->smgr.rlocator,
2065
0
              td->smgr.is_temp ? MyProcNumber : INVALID_PROC_NUMBER,
2066
0
              td->smgr.forkNum);
2067
2068
0
  if (result.error_data != 0)
2069
0
  {
2070
    /* for errcode_for_file_access() and %m */
2071
0
    errno = result.error_data;
2072
2073
0
    ereport(elevel,
2074
0
        errcode_for_file_access(),
2075
0
        errmsg("could not read blocks %u..%u in file \"%s\": %m",
2076
0
             td->smgr.blockNum,
2077
0
             td->smgr.blockNum + td->smgr.nblocks - 1,
2078
0
             path.str));
2079
0
  }
2080
0
  else
2081
0
  {
2082
    /*
2083
     * NB: This will typically only be output in debug messages, while
2084
     * retrying a partial IO.
2085
     */
2086
0
    ereport(elevel,
2087
0
        errcode(ERRCODE_DATA_CORRUPTED),
2088
0
        errmsg("could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes",
2089
0
             td->smgr.blockNum,
2090
0
             td->smgr.blockNum + td->smgr.nblocks - 1,
2091
0
             path.str,
2092
0
             result.result * (size_t) BLCKSZ,
2093
0
             td->smgr.nblocks * (size_t) BLCKSZ));
2094
0
  }
2095
0
}