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