1 /*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996, 2013 Oracle and/or its affiliates. All rights reserved.
5 *
6 * $Id$
7 */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/db_page.h"
13 #include "dbinc/db_swap.h"
14 #include "dbinc/btree.h"
15 #include "dbinc/hash.h"
16 #include "dbinc/qam.h"
17
18 /*
19 * __db_upgrade_pp --
20 * DB->upgrade pre/post processing.
21 *
22 * PUBLIC: int __db_upgrade_pp __P((DB *, const char *, u_int32_t));
23 */
24 int
__db_upgrade_pp(dbp,fname,flags)25 __db_upgrade_pp(dbp, fname, flags)
26 DB *dbp;
27 const char *fname;
28 u_int32_t flags;
29 {
30 #ifdef HAVE_UPGRADE_SUPPORT
31 DB_THREAD_INFO *ip;
32 ENV *env;
33 int ret;
34
35 env = dbp->env;
36
37 /*
38 * !!!
39 * The actual argument checking is simple, do it inline.
40 */
41 if ((ret = __db_fchk(env, "DB->upgrade", flags, DB_DUPSORT)) != 0)
42 return (ret);
43
44 ENV_ENTER(env, ip);
45 ret = __db_upgrade(dbp, fname, flags);
46 ENV_LEAVE(env, ip);
47 return (ret);
48 #else
49 COMPQUIET(dbp, NULL);
50 COMPQUIET(fname, NULL);
51 COMPQUIET(flags, 0);
52
53 __db_errx(dbp->env, DB_STR("0665", "upgrade not supported"));
54 return (EINVAL);
55 #endif
56 }
57
58 #ifdef HAVE_UPGRADE_SUPPORT
59 static int (* const func_31_list[P_PAGETYPE_MAX])
60 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)) = {
61 NULL, /* P_INVALID */
62 NULL, /* __P_DUPLICATE */
63 __ham_31_hash, /* P_HASH_UNSORTED */
64 NULL, /* P_IBTREE */
65 NULL, /* P_IRECNO */
66 __bam_31_lbtree, /* P_LBTREE */
67 NULL, /* P_LRECNO */
68 NULL, /* P_OVERFLOW */
69 __ham_31_hashmeta, /* P_HASHMETA */
70 __bam_31_btreemeta, /* P_BTREEMETA */
71 NULL, /* P_QAMMETA */
72 NULL, /* P_QAMDATA */
73 NULL, /* P_LDUP */
74 NULL, /* P_HASH */
75 NULL, /* P_HEAPMETA */
76 NULL, /* P_HEAP */
77 NULL, /* P_IHEAP */
78 };
79
80 static int (* const func_46_list[P_PAGETYPE_MAX])
81 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)) = {
82 NULL, /* P_INVALID */
83 NULL, /* __P_DUPLICATE */
84 __ham_46_hash, /* P_HASH_UNSORTED */
85 NULL, /* P_IBTREE */
86 NULL, /* P_IRECNO */
87 NULL, /* P_LBTREE */
88 NULL, /* P_LRECNO */
89 NULL, /* P_OVERFLOW */
90 __ham_46_hashmeta, /* P_HASHMETA */
91 NULL, /* P_BTREEMETA */
92 NULL, /* P_QAMMETA */
93 NULL, /* P_QAMDATA */
94 NULL, /* P_LDUP */
95 NULL, /* P_HASH */
96 NULL, /* P_HEAPMETA */
97 NULL, /* P_HEAP */
98 NULL, /* P_IHEAP */
99 };
100
101 static int __db_page_pass __P((DB *, char *, u_int32_t, int (* const [])
102 (DB *, char *, u_int32_t, DB_FH *, PAGE *, int *), DB_FH *));
103 static int __db_set_lastpgno __P((DB *, char *, DB_FH *));
104
105 /*
106 * __db_upgrade --
107 * Upgrade an existing database.
108 *
109 * PUBLIC: int __db_upgrade __P((DB *, const char *, u_int32_t));
110 */
111 int
__db_upgrade(dbp,fname,flags)112 __db_upgrade(dbp, fname, flags)
113 DB *dbp;
114 const char *fname;
115 u_int32_t flags;
116 {
117 DBMETA *meta;
118 DB_FH *fhp;
119 ENV *env;
120 size_t n;
121 int ret, t_ret, use_mp_open;
122 u_int8_t mbuf[256], tmpflags;
123 char *real_name;
124
125 use_mp_open = 0;
126 env = dbp->env;
127 fhp = NULL;
128
129 /* Get the real backing file name. */
130 if ((ret = __db_appname(env,
131 DB_APP_DATA, fname, NULL, &real_name)) != 0)
132 return (ret);
133
134 /* Open the file. */
135 if ((ret = __os_open(env, real_name, 0, 0, 0, &fhp)) != 0) {
136 __db_err(env, ret, "%s", real_name);
137 return (ret);
138 }
139
140 /* Initialize the feedback. */
141 if (dbp->db_feedback != NULL)
142 dbp->db_feedback(dbp, DB_UPGRADE, 0);
143
144 /*
145 * Read the metadata page. We read 256 bytes, which is larger than
146 * any access method's metadata page and smaller than any disk sector.
147 */
148 if ((ret = __os_read(env, fhp, mbuf, sizeof(mbuf), &n)) != 0)
149 goto err;
150
151 switch (((DBMETA *)mbuf)->magic) {
152 case DB_BTREEMAGIC:
153 switch (((DBMETA *)mbuf)->version) {
154 case 6:
155 /*
156 * Before V7 not all pages had page types, so we do the
157 * single meta-data page by hand.
158 */
159 if ((ret =
160 __bam_30_btreemeta(dbp, real_name, mbuf)) != 0)
161 goto err;
162 if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0)
163 goto err;
164 if ((ret = __os_write(env, fhp, mbuf, 256, &n)) != 0)
165 goto err;
166 /* FALLTHROUGH */
167 case 7:
168 /*
169 * We need the page size to do more. Rip it out of
170 * the meta-data page.
171 */
172 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
173
174 if ((ret = __db_page_pass(
175 dbp, real_name, flags, func_31_list, fhp)) != 0)
176 goto err;
177 /* FALLTHROUGH */
178 case 8:
179 if ((ret =
180 __db_set_lastpgno(dbp, real_name, fhp)) != 0)
181 goto err;
182 /* FALLTHROUGH */
183 case 9:
184 break;
185 default:
186 __db_errx(env, DB_STR_A("0666",
187 "%s: unsupported btree version: %lu", "%s %lu"),
188 real_name, (u_long)((DBMETA *)mbuf)->version);
189 ret = DB_OLD_VERSION;
190 goto err;
191 }
192 break;
193 case DB_HASHMAGIC:
194 switch (((DBMETA *)mbuf)->version) {
195 case 4:
196 case 5:
197 /*
198 * Before V6 not all pages had page types, so we do the
199 * single meta-data page by hand.
200 */
201 if ((ret =
202 __ham_30_hashmeta(dbp, real_name, mbuf)) != 0)
203 goto err;
204 if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0)
205 goto err;
206 if ((ret = __os_write(env, fhp, mbuf, 256, &n)) != 0)
207 goto err;
208
209 /*
210 * Before V6, we created hash pages one by one as they
211 * were needed, using hashhdr.ovfl_point to reserve
212 * a block of page numbers for them. A consequence
213 * of this was that, if no overflow pages had been
214 * created, the current doubling might extend past
215 * the end of the database file.
216 *
217 * In DB 3.X, we now create all the hash pages
218 * belonging to a doubling atomically; it's not
219 * safe to just save them for later, because when
220 * we create an overflow page we'll just create
221 * a new last page (whatever that may be). Grow
222 * the database to the end of the current doubling.
223 */
224 if ((ret =
225 __ham_30_sizefix(dbp, fhp, real_name, mbuf)) != 0)
226 goto err;
227 /* FALLTHROUGH */
228 case 6:
229 /*
230 * We need the page size to do more. Rip it out of
231 * the meta-data page.
232 */
233 memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
234
235 if ((ret = __db_page_pass(
236 dbp, real_name, flags, func_31_list, fhp)) != 0)
237 goto err;
238 /* FALLTHROUGH */
239 case 7:
240 if ((ret =
241 __db_set_lastpgno(dbp, real_name, fhp)) != 0)
242 goto err;
243 /* FALLTHROUGH */
244 case 8:
245 /*
246 * Any upgrade that has proceeded this far has metadata
247 * pages compatible with hash version 8 metadata pages,
248 * so casting mbuf to a dbmeta is safe.
249 * If a newer revision moves the pagesize, checksum or
250 * encrypt_alg flags in the metadata, then the
251 * extraction of the fields will need to use hard coded
252 * offsets.
253 */
254 meta = (DBMETA*)mbuf;
255 /*
256 * We need the page size to do more. Extract it from
257 * the meta-data page.
258 */
259 memcpy(&dbp->pgsize, &meta->pagesize,
260 sizeof(u_int32_t));
261 /*
262 * Rip out metadata and encrypt_alg fields from the
263 * metadata page. So the upgrade can know how big
264 * the page metadata pre-amble is. Any upgrade that has
265 * proceeded this far has metadata pages compatible
266 * with hash version 8 metadata pages, so extracting
267 * the fields is safe.
268 */
269 memcpy(&tmpflags, &meta->metaflags, sizeof(u_int8_t));
270 if (FLD_ISSET(tmpflags, DBMETA_CHKSUM))
271 F_SET(dbp, DB_AM_CHKSUM);
272 memcpy(&tmpflags, &meta->encrypt_alg, sizeof(u_int8_t));
273 if (tmpflags != 0) {
274 if (!CRYPTO_ON(dbp->env)) {
275 __db_errx(env, DB_STR("0667",
276 "Attempt to upgrade an encrypted database without providing a password."));
277 ret = EINVAL;
278 goto err;
279 }
280 F_SET(dbp, DB_AM_ENCRYPT);
281 }
282
283 /*
284 * This is ugly. It is necessary to have a usable
285 * mpool in the dbp to upgrade from an unsorted
286 * to a sorted hash database. The mpool file is used
287 * to resolve offpage key items, which are needed to
288 * determine sort order. Having mpool open and access
289 * the file does not affect the page pass, since the
290 * page pass only updates DB_HASH_UNSORTED pages
291 * in-place, and the mpool file is only used to read
292 * OFFPAGE items.
293 */
294 use_mp_open = 1;
295 if ((ret = __os_closehandle(env, fhp)) != 0)
296 return (ret);
297 dbp->type = DB_HASH;
298 if ((ret = __env_mpool(dbp, fname,
299 DB_AM_NOT_DURABLE | DB_AM_VERIFYING)) != 0)
300 return (ret);
301 fhp = dbp->mpf->fhp;
302
303 /* Do the actual conversion pass. */
304 if ((ret = __db_page_pass(
305 dbp, real_name, flags, func_46_list, fhp)) != 0)
306 goto err;
307
308 /* FALLTHROUGH */
309 case 9:
310 break;
311 default:
312 __db_errx(env, DB_STR_A("0668",
313 "%s: unsupported hash version: %lu", "%s %lu"),
314 real_name, (u_long)((DBMETA *)mbuf)->version);
315 ret = DB_OLD_VERSION;
316 goto err;
317 }
318 break;
319 case DB_HEAPMAGIC:
320 /*
321 * There's no upgrade needed for Heap yet.
322 */
323 break;
324 case DB_QAMMAGIC:
325 switch (((DBMETA *)mbuf)->version) {
326 case 1:
327 /*
328 * If we're in a Queue database, the only page that
329 * needs upgrading is the meta-database page, don't
330 * bother with a full pass.
331 */
332 if ((ret = __qam_31_qammeta(dbp, real_name, mbuf)) != 0)
333 return (ret);
334 /* FALLTHROUGH */
335 case 2:
336 if ((ret = __qam_32_qammeta(dbp, real_name, mbuf)) != 0)
337 return (ret);
338 if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0)
339 goto err;
340 if ((ret = __os_write(env, fhp, mbuf, 256, &n)) != 0)
341 goto err;
342 /* FALLTHROUGH */
343 case 3:
344 case 4:
345 break;
346 default:
347 __db_errx(env, DB_STR_A("0669",
348 "%s: unsupported queue version: %lu",
349 "%s %lu"), real_name,
350 (u_long)((DBMETA *)mbuf)->version);
351 ret = DB_OLD_VERSION;
352 goto err;
353 }
354 break;
355 default:
356 M_32_SWAP(((DBMETA *)mbuf)->magic);
357 switch (((DBMETA *)mbuf)->magic) {
358 case DB_BTREEMAGIC:
359 case DB_HASHMAGIC:
360 case DB_HEAPMAGIC:
361 case DB_QAMMAGIC:
362 __db_errx(env, DB_STR_A("0670",
363 "%s: DB->upgrade only supported on native byte-order systems",
364 "%s"), real_name);
365 break;
366 default:
367 __db_errx(env, DB_STR_A("0671",
368 "%s: unrecognized file type", "%s"), real_name);
369 break;
370 }
371 ret = EINVAL;
372 goto err;
373 }
374
375 ret = __os_fsync(env, fhp);
376
377 /*
378 * If mp_open was used, then rely on the database close to clean up
379 * any file handles.
380 */
381 err: if (use_mp_open == 0 && fhp != NULL &&
382 (t_ret = __os_closehandle(env, fhp)) != 0 && ret == 0)
383 ret = t_ret;
384 __os_free(env, real_name);
385
386 /* We're done. */
387 if (dbp->db_feedback != NULL)
388 dbp->db_feedback(dbp, DB_UPGRADE, 100);
389
390 return (ret);
391 }
392
393 /*
394 * __db_page_pass --
395 * Walk the pages of the database, upgrading whatever needs it.
396 */
397 static int
__db_page_pass(dbp,real_name,flags,fl,fhp)398 __db_page_pass(dbp, real_name, flags, fl, fhp)
399 DB *dbp;
400 char *real_name;
401 u_int32_t flags;
402 int (* const fl[P_PAGETYPE_MAX])
403 __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
404 DB_FH *fhp;
405 {
406 ENV *env;
407 PAGE *page;
408 db_pgno_t i, pgno_last;
409 size_t n;
410 int dirty, ret;
411
412 env = dbp->env;
413
414 /* Determine the last page of the file. */
415 if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
416 return (ret);
417
418 /* Allocate memory for a single page. */
419 if ((ret = __os_malloc(env, dbp->pgsize, &page)) != 0)
420 return (ret);
421
422 /* Walk the file, calling the underlying conversion functions. */
423 for (i = 0; i < pgno_last; ++i) {
424 if (dbp->db_feedback != NULL)
425 dbp->db_feedback(
426 dbp, DB_UPGRADE, (int)((i * 100)/pgno_last));
427 if ((ret = __os_seek(env, fhp, i, dbp->pgsize, 0)) != 0)
428 break;
429 if ((ret = __os_read(env, fhp, page, dbp->pgsize, &n)) != 0)
430 break;
431 dirty = 0;
432 /* Always decrypt the page. */
433 if ((ret = __db_decrypt_pg(env, dbp, page)) != 0)
434 break;
435 if (fl[TYPE(page)] != NULL && (ret = fl[TYPE(page)]
436 (dbp, real_name, flags, fhp, page, &dirty)) != 0)
437 break;
438 if (dirty) {
439 if ((ret = __db_encrypt_and_checksum_pg(
440 env, dbp, page)) != 0)
441 break;
442 if ((ret =
443 __os_seek(env, fhp, i, dbp->pgsize, 0)) != 0)
444 break;
445 if ((ret = __os_write(env,
446 fhp, page, dbp->pgsize, &n)) != 0)
447 break;
448 }
449 }
450
451 __os_free(dbp->env, page);
452 return (ret);
453 }
454
455 /*
456 * __db_lastpgno --
457 * Return the current last page number of the file.
458 *
459 * PUBLIC: int __db_lastpgno __P((DB *, char *, DB_FH *, db_pgno_t *));
460 */
461 int
__db_lastpgno(dbp,real_name,fhp,pgno_lastp)462 __db_lastpgno(dbp, real_name, fhp, pgno_lastp)
463 DB *dbp;
464 char *real_name;
465 DB_FH *fhp;
466 db_pgno_t *pgno_lastp;
467 {
468 ENV *env;
469 db_pgno_t pgno_last;
470 u_int32_t mbytes, bytes;
471 int ret;
472
473 env = dbp->env;
474
475 if ((ret = __os_ioinfo(env,
476 real_name, fhp, &mbytes, &bytes, NULL)) != 0) {
477 __db_err(env, ret, "%s", real_name);
478 return (ret);
479 }
480
481 /* Page sizes have to be a power-of-two. */
482 if (bytes % dbp->pgsize != 0) {
483 __db_errx(env, DB_STR_A("0672",
484 "%s: file size not a multiple of the pagesize", "%s"),
485 real_name);
486 return (EINVAL);
487 }
488 pgno_last = mbytes * (MEGABYTE / dbp->pgsize);
489 pgno_last += bytes / dbp->pgsize;
490
491 *pgno_lastp = pgno_last;
492 return (0);
493 }
494
495 /*
496 * __db_set_lastpgno --
497 * Update the meta->last_pgno field.
498 *
499 * Code assumes that we do not have checksums/crypto on the page.
500 */
501 static int
__db_set_lastpgno(dbp,real_name,fhp)502 __db_set_lastpgno(dbp, real_name, fhp)
503 DB *dbp;
504 char *real_name;
505 DB_FH *fhp;
506 {
507 DBMETA meta;
508 ENV *env;
509 int ret;
510 size_t n;
511
512 env = dbp->env;
513 if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0)
514 return (ret);
515 if ((ret = __os_read(env, fhp, &meta, sizeof(meta), &n)) != 0)
516 return (ret);
517 dbp->pgsize = meta.pagesize;
518 if ((ret = __db_lastpgno(dbp, real_name, fhp, &meta.last_pgno)) != 0)
519 return (ret);
520 if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0)
521 return (ret);
522 if ((ret = __os_write(env, fhp, &meta, sizeof(meta), &n)) != 0)
523 return (ret);
524
525 return (0);
526 }
527 #endif /* HAVE_UPGRADE_SUPPORT */
528