PostgreSQL Source Code: src/bin/pg_upgrade/file.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

11

12#include <sys/stat.h>

13#include <limits.h>

14#include <fcntl.h>

15#ifdef HAVE_COPYFILE_H

16#include <copyfile.h>

17#endif

18#ifdef __linux__

19#include <sys/ioctl.h>

20#include <linux/fs.h>

21#endif

22

29

30

31

32

33

34

35

36

37

38void

39cloneFile(const char *src, const char *dst,

40 const char *schemaName, const char *relName)

41{

42#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)

43 if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0)

44 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m",

45 schemaName, relName, src, dst);

46#elif defined(__linux__) && defined(FICLONE)

47 int src_fd;

48 int dest_fd;

49

50 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)

51 pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %m",

52 schemaName, relName, src);

53

54 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

56 pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %m",

57 schemaName, relName, dst);

58

59 if (ioctl(dest_fd, FICLONE, src_fd) < 0)

60 {

61 int save_errno = errno;

62

63 unlink(dst);

64

65 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",

66 schemaName, relName, src, dst, strerror(save_errno));

67 }

68

71#endif

72}

73

74

75

76

77

78

79

80

81void

82copyFile(const char *src, const char *dst,

83 const char *schemaName, const char *relName)

84{

85#ifndef WIN32

86 int src_fd;

87 int dest_fd;

88 char *buffer;

89

90 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)

91 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",

92 schemaName, relName, src);

93

94 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

96 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",

97 schemaName, relName, dst);

98

99

100#define COPY_BUF_SIZE (50 * BLCKSZ)

101

103

104

105 while (true)

106 {

108

109 if (nbytes < 0)

110 pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",

111 schemaName, relName, src);

112

113 if (nbytes == 0)

114 break;

115

116 errno = 0;

117 if (write(dest_fd, buffer, nbytes) != nbytes)

118 {

119

120 if (errno == 0)

121 errno = ENOSPC;

122 pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",

123 schemaName, relName, dst);

124 }

125 }

126

130

131#else

132

133 if (CopyFile(src, dst, true) == 0)

134 {

136 pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m",

137 schemaName, relName, src, dst);

138 }

139

140#endif

141}

142

143

144

145

146

147

148

149

150void

152 const char *schemaName, const char *relName)

153{

154#ifdef HAVE_COPY_FILE_RANGE

155 int src_fd;

156 int dest_fd;

157 ssize_t nbytes;

158

159 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)

160 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",

161 schemaName, relName, src);

162

163 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

165 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",

166 schemaName, relName, dst);

167

168 do

169 {

170 nbytes = copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0);

171 if (nbytes < 0)

172 pg_fatal("error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m",

173 schemaName, relName, src, dst);

174 }

175 while (nbytes > 0);

176

179#endif

180}

181

182

183

184

185

186

187

188

189void

190linkFile(const char *src, const char *dst,

191 const char *schemaName, const char *relName)

192{

193 if (link(src, dst) < 0)

194 pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m",

195 schemaName, relName, src, dst);

196}

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215void

217 const char *schemaName, const char *relName)

218{

219 int src_fd;

220 int dst_fd;

223 ssize_t totalBytesRead = 0;

224 ssize_t src_filesize;

225 int rewriteVmBytesPerPage;

227 struct stat statbuf;

228

229

231

232 if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0)

233 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",

234 schemaName, relName, fromfile);

235

236 if (fstat(src_fd, &statbuf) != 0)

237 pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m",

238 schemaName, relName, fromfile);

239

240 if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

242 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",

243 schemaName, relName, tofile);

244

245

246 src_filesize = statbuf.st_size;

247

248

249

250

251

252

253

254 while (totalBytesRead < src_filesize)

255 {

256 ssize_t bytesRead;

257 char *old_cur;

258 char *old_break;

259 char *old_blkend;

261 bool old_lastblk;

262

263 if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ)

264 {

265 if (bytesRead < 0)

266 pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",

267 schemaName, relName, fromfile);

268 else

269 pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"",

270 schemaName, relName, fromfile);

271 }

272

273 totalBytesRead += BLCKSZ;

274 old_lastblk = (totalBytesRead == src_filesize);

275

276

278

279

280

281

282

283

284

286 old_blkend = buffer.data + bytesRead;

287 old_break = old_cur + rewriteVmBytesPerPage;

288

289 while (old_break <= old_blkend)

290 {

291 char *new_cur;

292 bool empty = true;

293 bool old_lastpart;

294

295

297

298

299 old_lastpart = old_lastblk && (old_break == old_blkend);

300

302

303

304 while (old_cur < old_break)

305 {

307 uint16 new_vmbits = 0;

308 int i;

309

310

312 {

313 if (byte & (1 << i))

314 {

315 empty = false;

316 new_vmbits |=

318 }

319 }

320

321

322 new_cur[0] = (char) (new_vmbits & 0xFF);

323 new_cur[1] = (char) (new_vmbits >> 8);

324

325 old_cur++;

327 }

328

329

330 if (old_lastpart && empty)

331 break;

332

333

337

338 errno = 0;

339 if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ)

340 {

341

342 if (errno == 0)

343 errno = ENOSPC;

344 pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",

345 schemaName, relName, tofile);

346 }

347

348

349 old_break += rewriteVmBytesPerPage;

350 new_blkno++;

351 }

352 }

353

354

357}

358

359void

361{

364

367 unlink(new_link_file);

368

369#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)

370 if (copyfile(existing_file, new_link_file, NULL, COPYFILE_CLONE_FORCE) < 0)

371 pg_fatal("could not clone file between old and new data directories: %m");

372#elif defined(__linux__) && defined(FICLONE)

373 {

374 int src_fd;

375 int dest_fd;

376

377 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)

378 pg_fatal("could not open file \"%s\": %m",

379 existing_file);

380

381 if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

383 pg_fatal("could not create file \"%s\": %m",

384 new_link_file);

385

386 if (ioctl(dest_fd, FICLONE, src_fd) < 0)

387 pg_fatal("could not clone file between old and new data directories: %m");

388

391 }

392#else

393 pg_fatal("file cloning not supported on this platform");

394#endif

395

396 unlink(new_link_file);

397}

398

399void

401{

404

406 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.copy_file_range_test", new_cluster.pgdata);

407 unlink(new_link_file);

408

409#if defined(HAVE_COPY_FILE_RANGE)

410 {

411 int src_fd;

412 int dest_fd;

413

414 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)

415 pg_fatal("could not open file \"%s\": %m",

416 existing_file);

417

418 if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,

420 pg_fatal("could not create file \"%s\": %m",

421 new_link_file);

422

423 if (copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0) < 0)

424 pg_fatal("could not copy file range between old and new data directories: %m");

425

428 }

429#else

430 pg_fatal("copy_file_range not supported on this platform");

431#endif

432

433 unlink(new_link_file);

434}

435

436void

438{

441

444 unlink(new_link_file);

445

446 if (link(existing_file, new_link_file) < 0)

447 {

449 pg_fatal("could not create hard link between old and new data directories: %m\n"

450 "In link mode the old and new data directories must be on the same file system.");

452 pg_fatal("could not create hard link between old and new data directories: %m\n"

453 "In swap mode the old and new data directories must be on the same file system.");

454 else

455 pg_fatal("unrecognized transfer mode");

456 }

457

458 unlink(new_link_file);

459}

PageHeaderData * PageHeader

#define SizeOfPageHeaderData

uint16 pg_checksum_page(char *page, BlockNumber blkno)

void * pg_malloc(size_t size)

void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName)

void check_file_clone(void)

void rewriteVisibilityMap(const char *fromfile, const char *tofile, const char *schemaName, const char *relName)

void check_hard_link(transferMode transfer_mode)

void cloneFile(const char *src, const char *dst, const char *schemaName, const char *relName)

void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName)

void copyFile(const char *src, const char *dst, const char *schemaName, const char *relName)

void check_copy_file_range(void)

uint32 data_checksum_version

#define BITS_PER_HEAPBLOCK

#define VISIBILITYMAP_ALL_VISIBLE

void _dosmaperr(unsigned long)

int link(const char *src, const char *dst)