Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * smgr.c
4 : * public interface routines to storage manager switch.
5 : *
6 : * All file system operations in POSTGRES dispatch through these
7 : * routines.
8 : *
9 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
10 : * Portions Copyright (c) 1994, Regents of the University of California
11 : *
12 : *
13 : * IDENTIFICATION
14 : * src/backend/storage/smgr/smgr.c
15 : *
16 : *-------------------------------------------------------------------------
17 : */
18 : #include "postgres.h"
19 :
20 : #include "commands/tablespace.h"
21 : #include "storage/bufmgr.h"
22 : #include "storage/ipc.h"
23 : #include "storage/smgr.h"
24 : #include "utils/hsearch.h"
25 : #include "utils/inval.h"
26 :
27 :
28 : /*
29 : * This struct of function pointers defines the API between smgr.c and
30 : * any individual storage manager module. Note that smgr subfunctions are
31 : * generally expected to report problems via elog(ERROR). An exception is
32 : * that smgr_unlink should use elog(WARNING), rather than erroring out,
33 : * because we normally unlink relations during post-commit/abort cleanup,
34 : * and so it's too late to raise an error. Also, various conditions that
35 : * would normally be errors should be allowed during bootstrap and/or WAL
36 : * recovery --- see comments in md.c for details.
37 : */
38 : typedef struct f_smgr
39 : {
40 : void (*smgr_init) (void); /* may be NULL */
41 : void (*smgr_shutdown) (void); /* may be NULL */
42 : void (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
43 : void (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
44 : bool isRedo);
45 : bool (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
46 : void (*smgr_unlink) (RelFileNodeBackend rnode, ForkNumber forknum,
47 : bool isRedo);
48 : void (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
49 : BlockNumber blocknum, char *buffer, bool skipFsync);
50 : void (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
51 : BlockNumber blocknum);
52 : void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
53 : BlockNumber blocknum, char *buffer);
54 : void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
55 : BlockNumber blocknum, char *buffer, bool skipFsync);
56 : void (*smgr_writeback) (SMgrRelation reln, ForkNumber forknum,
57 : BlockNumber blocknum, BlockNumber nblocks);
58 : BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
59 : void (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
60 : BlockNumber nblocks);
61 : void (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
62 : void (*smgr_pre_ckpt) (void); /* may be NULL */
63 : void (*smgr_sync) (void); /* may be NULL */
64 : void (*smgr_post_ckpt) (void); /* may be NULL */
65 : } f_smgr;
66 :
67 :
68 : static const f_smgr smgrsw[] = {
69 : /* magnetic disk */
70 : {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend,
71 : mdprefetch, mdread, mdwrite, mdwriteback, mdnblocks, mdtruncate,
72 : mdimmedsync, mdpreckpt, mdsync, mdpostckpt
73 : }
74 : };
75 :
76 : static const int NSmgr = lengthof(smgrsw);
77 :
78 :
79 : /*
80 : * Each backend has a hashtable that stores all extant SMgrRelation objects.
81 : * In addition, "unowned" SMgrRelation objects are chained together in a list.
82 : */
83 : static HTAB *SMgrRelationHash = NULL;
84 :
85 : static SMgrRelation first_unowned_reln = NULL;
86 :
87 : /* local function prototypes */
88 : static void smgrshutdown(int code, Datum arg);
89 : static void add_to_unowned_list(SMgrRelation reln);
90 : static void remove_from_unowned_list(SMgrRelation reln);
91 :
92 :
93 : /*
94 : * smgrinit(), smgrshutdown() -- Initialize or shut down storage
95 : * managers.
96 : *
97 : * Note: smgrinit is called during backend startup (normal or standalone
98 : * case), *not* during postmaster start. Therefore, any resources created
99 : * here or destroyed in smgrshutdown are backend-local.
100 : */
101 : void
102 344 : smgrinit(void)
103 : {
104 : int i;
105 :
106 688 : for (i = 0; i < NSmgr; i++)
107 : {
108 344 : if (smgrsw[i].smgr_init)
109 344 : (*(smgrsw[i].smgr_init)) ();
110 : }
111 :
112 : /* register the shutdown proc */
113 344 : on_proc_exit(smgrshutdown, 0);
114 344 : }
115 :
116 : /*
117 : * on_proc_exit hook for smgr cleanup during backend shutdown
118 : */
119 : static void
120 344 : smgrshutdown(int code, Datum arg)
121 : {
122 : int i;
123 :
124 688 : for (i = 0; i < NSmgr; i++)
125 : {
126 344 : if (smgrsw[i].smgr_shutdown)
127 0 : (*(smgrsw[i].smgr_shutdown)) ();
128 : }
129 344 : }
130 :
131 : /*
132 : * smgropen() -- Return an SMgrRelation object, creating it if need be.
133 : *
134 : * This does not attempt to actually open the underlying file.
135 : */
136 : SMgrRelation
137 47746 : smgropen(RelFileNode rnode, BackendId backend)
138 : {
139 : RelFileNodeBackend brnode;
140 : SMgrRelation reln;
141 : bool found;
142 :
143 47746 : if (SMgrRelationHash == NULL)
144 : {
145 : /* First time through: initialize the hash table */
146 : HASHCTL ctl;
147 :
148 339 : MemSet(&ctl, 0, sizeof(ctl));
149 339 : ctl.keysize = sizeof(RelFileNodeBackend);
150 339 : ctl.entrysize = sizeof(SMgrRelationData);
151 339 : SMgrRelationHash = hash_create("smgr relation table", 400,
152 : &ctl, HASH_ELEM | HASH_BLOBS);
153 339 : first_unowned_reln = NULL;
154 : }
155 :
156 : /* Look up or create an entry */
157 47746 : brnode.node = rnode;
158 47746 : brnode.backend = backend;
159 47746 : reln = (SMgrRelation) hash_search(SMgrRelationHash,
160 : (void *) &brnode,
161 : HASH_ENTER, &found);
162 :
163 : /* Initialize it if not present before */
164 47746 : if (!found)
165 : {
166 : int forknum;
167 :
168 : /* hash_search already filled in the lookup key */
169 34514 : reln->smgr_owner = NULL;
170 34514 : reln->smgr_targblock = InvalidBlockNumber;
171 34514 : reln->smgr_fsm_nblocks = InvalidBlockNumber;
172 34514 : reln->smgr_vm_nblocks = InvalidBlockNumber;
173 34514 : reln->smgr_which = 0; /* we only have md.c at present */
174 :
175 : /* mark it not open */
176 172570 : for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
177 138056 : reln->md_num_open_segs[forknum] = 0;
178 :
179 : /* it has no owner yet */
180 34514 : add_to_unowned_list(reln);
181 : }
182 :
183 47746 : return reln;
184 : }
185 :
186 : /*
187 : * smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
188 : *
189 : * There can be only one owner at a time; this is sufficient since currently
190 : * the only such owners exist in the relcache.
191 : */
192 : void
193 30411 : smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
194 : {
195 : /* We don't support "disowning" an SMgrRelation here, use smgrclearowner */
196 30411 : Assert(owner != NULL);
197 :
198 : /*
199 : * First, unhook any old owner. (Normally there shouldn't be any, but it
200 : * seems possible that this can happen during swap_relation_files()
201 : * depending on the order of processing. It's ok to close the old
202 : * relcache entry early in that case.)
203 : *
204 : * If there isn't an old owner, then the reln should be in the unowned
205 : * list, and we need to remove it.
206 : */
207 30411 : if (reln->smgr_owner)
208 0 : *(reln->smgr_owner) = NULL;
209 : else
210 30411 : remove_from_unowned_list(reln);
211 :
212 : /* Now establish the ownership relationship. */
213 30411 : reln->smgr_owner = owner;
214 30411 : *owner = reln;
215 30411 : }
216 :
217 : /*
218 : * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object
219 : * if one exists
220 : */
221 : void
222 0 : smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
223 : {
224 : /* Do nothing if the SMgrRelation object is not owned by the owner */
225 0 : if (reln->smgr_owner != owner)
226 0 : return;
227 :
228 : /* unset the owner's reference */
229 0 : *owner = NULL;
230 :
231 : /* unset our reference to the owner */
232 0 : reln->smgr_owner = NULL;
233 :
234 0 : add_to_unowned_list(reln);
235 : }
236 :
237 : /*
238 : * add_to_unowned_list -- link an SMgrRelation onto the unowned list
239 : *
240 : * Check remove_from_unowned_list()'s comments for performance
241 : * considerations.
242 : */
243 : static void
244 34514 : add_to_unowned_list(SMgrRelation reln)
245 : {
246 : /* place it at head of the list (to make smgrsetowner cheap) */
247 34514 : reln->next_unowned_reln = first_unowned_reln;
248 34514 : first_unowned_reln = reln;
249 34514 : }
250 :
251 : /*
252 : * remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
253 : *
254 : * If the reln is not present in the list, nothing happens. Typically this
255 : * would be caller error, but there seems no reason to throw an error.
256 : *
257 : * In the worst case this could be rather slow; but in all the cases that seem
258 : * likely to be performance-critical, the reln being sought will actually be
259 : * first in the list. Furthermore, the number of unowned relns touched in any
260 : * one transaction shouldn't be all that high typically. So it doesn't seem
261 : * worth expending the additional space and management logic needed for a
262 : * doubly-linked list.
263 : */
264 : static void
265 33994 : remove_from_unowned_list(SMgrRelation reln)
266 : {
267 : SMgrRelation *link;
268 : SMgrRelation cur;
269 :
270 83438 : for (link = &first_unowned_reln, cur = *link;
271 : cur != NULL;
272 15450 : link = &cur->next_unowned_reln, cur = *link)
273 : {
274 49444 : if (cur == reln)
275 : {
276 33994 : *link = cur->next_unowned_reln;
277 33994 : cur->next_unowned_reln = NULL;
278 33994 : break;
279 : }
280 : }
281 33994 : }
282 :
283 : /*
284 : * smgrexists() -- Does the underlying file for a fork exist?
285 : */
286 : bool
287 10547 : smgrexists(SMgrRelation reln, ForkNumber forknum)
288 : {
289 10547 : return (*(smgrsw[reln->smgr_which].smgr_exists)) (reln, forknum);
290 : }
291 :
292 : /*
293 : * smgrclose() -- Close and delete an SMgrRelation object.
294 : */
295 : void
296 16802 : smgrclose(SMgrRelation reln)
297 : {
298 : SMgrRelation *owner;
299 : ForkNumber forknum;
300 :
301 84010 : for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
302 67208 : (*(smgrsw[reln->smgr_which].smgr_close)) (reln, forknum);
303 :
304 16802 : owner = reln->smgr_owner;
305 :
306 16802 : if (!owner)
307 3583 : remove_from_unowned_list(reln);
308 :
309 16802 : if (hash_search(SMgrRelationHash,
310 16802 : (void *) &(reln->smgr_rnode),
311 : HASH_REMOVE, NULL) == NULL)
312 0 : elog(ERROR, "SMgrRelation hashtable corrupted");
313 :
314 : /*
315 : * Unhook the owner pointer, if any. We do this last since in the remote
316 : * possibility of failure above, the SMgrRelation object will still exist.
317 : */
318 16802 : if (owner)
319 13219 : *owner = NULL;
320 16802 : }
321 :
322 : /*
323 : * smgrcloseall() -- Close all existing SMgrRelation objects.
324 : */
325 : void
326 140 : smgrcloseall(void)
327 : {
328 : HASH_SEQ_STATUS status;
329 : SMgrRelation reln;
330 :
331 : /* Nothing to do if hashtable not set up */
332 140 : if (SMgrRelationHash == NULL)
333 144 : return;
334 :
335 136 : hash_seq_init(&status, SMgrRelationHash);
336 :
337 537 : while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
338 265 : smgrclose(reln);
339 : }
340 :
341 : /*
342 : * smgrclosenode() -- Close SMgrRelation object for given RelFileNode,
343 : * if one exists.
344 : *
345 : * This has the same effects as smgrclose(smgropen(rnode)), but it avoids
346 : * uselessly creating a hashtable entry only to drop it again when no
347 : * such entry exists already.
348 : */
349 : void
350 20294 : smgrclosenode(RelFileNodeBackend rnode)
351 : {
352 : SMgrRelation reln;
353 :
354 : /* Nothing to do if hashtable not set up */
355 20294 : if (SMgrRelationHash == NULL)
356 20303 : return;
357 :
358 20285 : reln = (SMgrRelation) hash_search(SMgrRelationHash,
359 : (void *) &rnode,
360 : HASH_FIND, NULL);
361 20285 : if (reln != NULL)
362 494 : smgrclose(reln);
363 : }
364 :
365 : /*
366 : * smgrcreate() -- Create a new relation.
367 : *
368 : * Given an already-created (but presumably unused) SMgrRelation,
369 : * cause the underlying disk file or other storage for the fork
370 : * to be created.
371 : *
372 : * If isRedo is true, it is okay for the underlying file to exist
373 : * already because we are in a WAL replay sequence.
374 : */
375 : void
376 4479 : smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
377 : {
378 : /*
379 : * Exit quickly in WAL replay mode if we've already opened the file. If
380 : * it's open, it surely must exist.
381 : */
382 4479 : if (isRedo && reln->md_num_open_segs[forknum] > 0)
383 4479 : return;
384 :
385 : /*
386 : * We may be using the target table space for the first time in this
387 : * database, so create a per-database subdirectory if needed.
388 : *
389 : * XXX this is a fairly ugly violation of module layering, but this seems
390 : * to be the best place to put the check. Maybe TablespaceCreateDbspace
391 : * should be here and not in commands/tablespace.c? But that would imply
392 : * importing a lot of stuff that smgr.c oughtn't know, either.
393 : */
394 4479 : TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode,
395 : reln->smgr_rnode.node.dbNode,
396 : isRedo);
397 :
398 4479 : (*(smgrsw[reln->smgr_which].smgr_create)) (reln, forknum, isRedo);
399 : }
400 :
401 : /*
402 : * smgrdounlink() -- Immediately unlink all forks of a relation.
403 : *
404 : * All forks of the relation are removed from the store. This should
405 : * not be used during transactional operations, since it can't be undone.
406 : *
407 : * If isRedo is true, it is okay for the underlying file(s) to be gone
408 : * already.
409 : *
410 : * This is equivalent to calling smgrdounlinkfork for each fork, but
411 : * it's significantly quicker so should be preferred when possible.
412 : */
413 : void
414 1 : smgrdounlink(SMgrRelation reln, bool isRedo)
415 : {
416 1 : RelFileNodeBackend rnode = reln->smgr_rnode;
417 1 : int which = reln->smgr_which;
418 : ForkNumber forknum;
419 :
420 : /* Close the forks at smgr level */
421 5 : for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
422 4 : (*(smgrsw[which].smgr_close)) (reln, forknum);
423 :
424 : /*
425 : * Get rid of any remaining buffers for the relation. bufmgr will just
426 : * drop them without bothering to write the contents.
427 : */
428 1 : DropRelFileNodesAllBuffers(&rnode, 1);
429 :
430 : /*
431 : * It'd be nice to tell the stats collector to forget it immediately, too.
432 : * But we can't because we don't know the OID (and in cases involving
433 : * relfilenode swaps, it's not always clear which table OID to forget,
434 : * anyway).
435 : */
436 :
437 : /*
438 : * Send a shared-inval message to force other backends to close any
439 : * dangling smgr references they may have for this rel. We should do this
440 : * before starting the actual unlinking, in case we fail partway through
441 : * that step. Note that the sinval message will eventually come back to
442 : * this backend, too, and thereby provide a backstop that we closed our
443 : * own smgr rel.
444 : */
445 1 : CacheInvalidateSmgr(rnode);
446 :
447 : /*
448 : * Delete the physical file(s).
449 : *
450 : * Note: smgr_unlink must treat deletion failure as a WARNING, not an
451 : * ERROR, because we've already decided to commit or abort the current
452 : * xact.
453 : */
454 1 : (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
455 1 : }
456 :
457 : /*
458 : * smgrdounlinkall() -- Immediately unlink all forks of all given relations
459 : *
460 : * All forks of all given relations are removed from the store. This
461 : * should not be used during transactional operations, since it can't be
462 : * undone.
463 : *
464 : * If isRedo is true, it is okay for the underlying file(s) to be gone
465 : * already.
466 : *
467 : * This is equivalent to calling smgrdounlink for each relation, but it's
468 : * significantly quicker so should be preferred when possible.
469 : */
470 : void
471 1031 : smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
472 : {
473 1031 : int i = 0;
474 : RelFileNodeBackend *rnodes;
475 : ForkNumber forknum;
476 :
477 1031 : if (nrels == 0)
478 1031 : return;
479 :
480 : /*
481 : * create an array which contains all relations to be dropped, and close
482 : * each relation's forks at the smgr level while at it
483 : */
484 1031 : rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
485 4211 : for (i = 0; i < nrels; i++)
486 : {
487 3180 : RelFileNodeBackend rnode = rels[i]->smgr_rnode;
488 3180 : int which = rels[i]->smgr_which;
489 :
490 3180 : rnodes[i] = rnode;
491 :
492 : /* Close the forks at smgr level */
493 15900 : for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
494 12720 : (*(smgrsw[which].smgr_close)) (rels[i], forknum);
495 : }
496 :
497 : /*
498 : * Get rid of any remaining buffers for the relations. bufmgr will just
499 : * drop them without bothering to write the contents.
500 : */
501 1031 : DropRelFileNodesAllBuffers(rnodes, nrels);
502 :
503 : /*
504 : * It'd be nice to tell the stats collector to forget them immediately,
505 : * too. But we can't because we don't know the OIDs.
506 : */
507 :
508 : /*
509 : * Send a shared-inval message to force other backends to close any
510 : * dangling smgr references they may have for these rels. We should do
511 : * this before starting the actual unlinking, in case we fail partway
512 : * through that step. Note that the sinval messages will eventually come
513 : * back to this backend, too, and thereby provide a backstop that we
514 : * closed our own smgr rel.
515 : */
516 4211 : for (i = 0; i < nrels; i++)
517 3180 : CacheInvalidateSmgr(rnodes[i]);
518 :
519 : /*
520 : * Delete the physical file(s).
521 : *
522 : * Note: smgr_unlink must treat deletion failure as a WARNING, not an
523 : * ERROR, because we've already decided to commit or abort the current
524 : * xact.
525 : */
526 :
527 4211 : for (i = 0; i < nrels; i++)
528 : {
529 3180 : int which = rels[i]->smgr_which;
530 :
531 15900 : for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
532 12720 : (*(smgrsw[which].smgr_unlink)) (rnodes[i], forknum, isRedo);
533 : }
534 :
535 1031 : pfree(rnodes);
536 : }
537 :
538 : /*
539 : * smgrdounlinkfork() -- Immediately unlink one fork of a relation.
540 : *
541 : * The specified fork of the relation is removed from the store. This
542 : * should not be used during transactional operations, since it can't be
543 : * undone.
544 : *
545 : * If isRedo is true, it is okay for the underlying file to be gone
546 : * already.
547 : */
548 : void
549 0 : smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo)
550 : {
551 0 : RelFileNodeBackend rnode = reln->smgr_rnode;
552 0 : int which = reln->smgr_which;
553 :
554 : /* Close the fork at smgr level */
555 0 : (*(smgrsw[which].smgr_close)) (reln, forknum);
556 :
557 : /*
558 : * Get rid of any remaining buffers for the fork. bufmgr will just drop
559 : * them without bothering to write the contents.
560 : */
561 0 : DropRelFileNodeBuffers(rnode, forknum, 0);
562 :
563 : /*
564 : * It'd be nice to tell the stats collector to forget it immediately, too.
565 : * But we can't because we don't know the OID (and in cases involving
566 : * relfilenode swaps, it's not always clear which table OID to forget,
567 : * anyway).
568 : */
569 :
570 : /*
571 : * Send a shared-inval message to force other backends to close any
572 : * dangling smgr references they may have for this rel. We should do this
573 : * before starting the actual unlinking, in case we fail partway through
574 : * that step. Note that the sinval message will eventually come back to
575 : * this backend, too, and thereby provide a backstop that we closed our
576 : * own smgr rel.
577 : */
578 0 : CacheInvalidateSmgr(rnode);
579 :
580 : /*
581 : * Delete the physical file(s).
582 : *
583 : * Note: smgr_unlink must treat deletion failure as a WARNING, not an
584 : * ERROR, because we've already decided to commit or abort the current
585 : * xact.
586 : */
587 0 : (*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
588 0 : }
589 :
590 : /*
591 : * smgrextend() -- Add a new block to a file.
592 : *
593 : * The semantics are nearly the same as smgrwrite(): write at the
594 : * specified position. However, this is to be used for the case of
595 : * extending a relation (i.e., blocknum is at or beyond the current
596 : * EOF). Note that we assume writing a block beyond current EOF
597 : * causes intervening file space to become filled with zeroes.
598 : */
599 : void
600 18586 : smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
601 : char *buffer, bool skipFsync)
602 : {
603 18586 : (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, forknum, blocknum,
604 : buffer, skipFsync);
605 18586 : }
606 :
607 : /*
608 : * smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
609 : */
610 : void
611 0 : smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
612 : {
613 0 : (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum);
614 0 : }
615 :
616 : /*
617 : * smgrread() -- read a particular block from a relation into the supplied
618 : * buffer.
619 : *
620 : * This routine is called from the buffer manager in order to
621 : * instantiate pages in the shared buffer cache. All storage managers
622 : * return pages in the format that POSTGRES expects.
623 : */
624 : void
625 4439 : smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
626 : char *buffer)
627 : {
628 4439 : (*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
629 4439 : }
630 :
631 : /*
632 : * smgrwrite() -- Write the supplied buffer out.
633 : *
634 : * This is to be used only for updating already-existing blocks of a
635 : * relation (ie, those before the current EOF). To extend a relation,
636 : * use smgrextend().
637 : *
638 : * This is not a synchronous write -- the block is not necessarily
639 : * on disk at return, only dumped out to the kernel. However,
640 : * provisions will be made to fsync the write before the next checkpoint.
641 : *
642 : * skipFsync indicates that the caller will make other provisions to
643 : * fsync the relation, so we needn't bother. Temporary relations also
644 : * do not require fsync.
645 : */
646 : void
647 8838 : smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
648 : char *buffer, bool skipFsync)
649 : {
650 8838 : (*(smgrsw[reln->smgr_which].smgr_write)) (reln, forknum, blocknum,
651 : buffer, skipFsync);
652 8838 : }
653 :
654 :
655 : /*
656 : * smgrwriteback() -- Trigger kernel writeback for the supplied range of
657 : * blocks.
658 : */
659 : void
660 1477 : smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
661 : BlockNumber nblocks)
662 : {
663 1477 : (*(smgrsw[reln->smgr_which].smgr_writeback)) (reln, forknum, blocknum,
664 : nblocks);
665 1477 : }
666 :
667 : /*
668 : * smgrnblocks() -- Calculate the number of blocks in the
669 : * supplied relation.
670 : */
671 : BlockNumber
672 84151 : smgrnblocks(SMgrRelation reln, ForkNumber forknum)
673 : {
674 84151 : return (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln, forknum);
675 : }
676 :
677 : /*
678 : * smgrtruncate() -- Truncate supplied relation to the specified number
679 : * of blocks
680 : *
681 : * The truncation is done immediately, so this can't be rolled back.
682 : */
683 : void
684 46 : smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
685 : {
686 : /*
687 : * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
688 : * just drop them without bothering to write the contents.
689 : */
690 46 : DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
691 :
692 : /*
693 : * Send a shared-inval message to force other backends to close any smgr
694 : * references they may have for this rel. This is useful because they
695 : * might have open file pointers to segments that got removed, and/or
696 : * smgr_targblock variables pointing past the new rel end. (The inval
697 : * message will come back to our backend, too, causing a
698 : * probably-unnecessary local smgr flush. But we don't expect that this
699 : * is a performance-critical path.) As in the unlink code, we want to be
700 : * sure the message is sent before we start changing things on-disk.
701 : */
702 46 : CacheInvalidateSmgr(reln->smgr_rnode);
703 :
704 : /*
705 : * Do the truncation.
706 : */
707 46 : (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks);
708 46 : }
709 :
710 : /*
711 : * smgrimmedsync() -- Force the specified relation to stable storage.
712 : *
713 : * Synchronously force all previous writes to the specified relation
714 : * down to disk.
715 : *
716 : * This is useful for building completely new relations (eg, new
717 : * indexes). Instead of incrementally WAL-logging the index build
718 : * steps, we can just write completed index pages to disk with smgrwrite
719 : * or smgrextend, and then fsync the completed index file before
720 : * committing the transaction. (This is sufficient for purposes of
721 : * crash recovery, since it effectively duplicates forcing a checkpoint
722 : * for the completed index. But it is *not* sufficient if one wishes
723 : * to use the WAL log for PITR or replication purposes: in that case
724 : * we have to make WAL entries as well.)
725 : *
726 : * The preceding writes should specify skipFsync = true to avoid
727 : * duplicative fsyncs.
728 : *
729 : * Note that you need to do FlushRelationBuffers() first if there is
730 : * any possibility that there are dirty buffers for the relation;
731 : * otherwise the sync is not very meaningful.
732 : */
733 : void
734 1264 : smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
735 : {
736 1264 : (*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln, forknum);
737 1264 : }
738 :
739 :
740 : /*
741 : * smgrpreckpt() -- Prepare for checkpoint.
742 : */
743 : void
744 11 : smgrpreckpt(void)
745 : {
746 : int i;
747 :
748 22 : for (i = 0; i < NSmgr; i++)
749 : {
750 11 : if (smgrsw[i].smgr_pre_ckpt)
751 11 : (*(smgrsw[i].smgr_pre_ckpt)) ();
752 : }
753 11 : }
754 :
755 : /*
756 : * smgrsync() -- Sync files to disk during checkpoint.
757 : */
758 : void
759 11 : smgrsync(void)
760 : {
761 : int i;
762 :
763 22 : for (i = 0; i < NSmgr; i++)
764 : {
765 11 : if (smgrsw[i].smgr_sync)
766 11 : (*(smgrsw[i].smgr_sync)) ();
767 : }
768 11 : }
769 :
770 : /*
771 : * smgrpostckpt() -- Post-checkpoint cleanup.
772 : */
773 : void
774 11 : smgrpostckpt(void)
775 : {
776 : int i;
777 :
778 22 : for (i = 0; i < NSmgr; i++)
779 : {
780 11 : if (smgrsw[i].smgr_post_ckpt)
781 11 : (*(smgrsw[i].smgr_post_ckpt)) ();
782 : }
783 11 : }
784 :
785 : /*
786 : * AtEOXact_SMgr
787 : *
788 : * This routine is called during transaction commit or abort (it doesn't
789 : * particularly care which). All transient SMgrRelation objects are closed.
790 : *
791 : * We do this as a compromise between wanting transient SMgrRelations to
792 : * live awhile (to amortize the costs of blind writes of multiple blocks)
793 : * and needing them to not live forever (since we're probably holding open
794 : * a kernel file descriptor for the underlying file, and we need to ensure
795 : * that gets closed reasonably soon if the file gets deleted).
796 : */
797 : void
798 26218 : AtEOXact_SMgr(void)
799 : {
800 : /*
801 : * Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
802 : * one from the list.
803 : */
804 52436 : while (first_unowned_reln != NULL)
805 : {
806 0 : Assert(first_unowned_reln->smgr_owner == NULL);
807 0 : smgrclose(first_unowned_reln);
808 : }
809 26218 : }
|