xref: /titanic_44/usr/src/uts/common/cpr/cpr_misc.c (revision fbcec90110655a00a2d5c9bdfaf87c7b476a4902)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/errno.h>
30 #include <sys/cpuvar.h>
31 #include <sys/vfs.h>
32 #include <sys/vnode.h>
33 #include <sys/pathname.h>
34 #include <sys/callb.h>
35 #include <sys/fs/ufs_inode.h>
36 #include <vm/anon.h>
37 #include <sys/fs/swapnode.h>	/* for swapfs_minfree */
38 #include <sys/kmem.h>
39 #include <sys/cpr.h>
40 #include <sys/conf.h>
41 
42 /*
43  * CPR miscellaneous support routines
44  */
45 #define	cpr_open(path, mode,  vpp)	(vn_open(path, UIO_SYSSPACE, \
46 		mode, 0600, vpp, CRCREAT, 0))
47 #define	cpr_rdwr(rw, vp, basep, cnt)	(vn_rdwr(rw, vp,  (caddr_t)(basep), \
48 		cnt, 0LL, UIO_SYSSPACE, 0, (rlim64_t)MAXOFF_T, CRED(), \
49 		(ssize_t *)NULL))
50 
51 extern void clkset(time_t);
52 extern cpu_t *i_cpr_bootcpu(void);
53 extern caddr_t i_cpr_map_setup(void);
54 extern void i_cpr_free_memory_resources(void);
55 
56 extern kmutex_t cpr_slock;
57 extern size_t cpr_buf_size;
58 extern char *cpr_buf;
59 extern size_t cpr_pagedata_size;
60 extern char *cpr_pagedata;
61 extern int cpr_bufs_allocated;
62 extern int cpr_bitmaps_allocated;
63 
64 static struct cprconfig cprconfig;
65 static int cprconfig_loaded = 0;
66 static int cpr_statefile_ok(vnode_t *, int);
67 static int cpr_p_online(cpu_t *, int);
68 static void cpr_save_mp_state(void);
69 int cpr_is_ufs(struct vfs *);
70 
71 char cpr_default_path[] = CPR_DEFAULT;
72 
73 #define	COMPRESS_PERCENT 40	/* approx compression ratio in percent */
74 #define	SIZE_RATE	115	/* increase size by 15% */
75 #define	INTEGRAL	100	/* for integer math */
76 
77 
78 /*
79  * cmn_err() followed by a 1/4 second delay; this gives the
80  * logging service a chance to flush messages and helps avoid
81  * intermixing output from prom_printf().
82  */
83 /*PRINTFLIKE2*/
84 void
85 cpr_err(int ce, const char *fmt, ...)
86 {
87 	va_list adx;
88 
89 	va_start(adx, fmt);
90 	vcmn_err(ce, fmt, adx);
91 	va_end(adx);
92 	drv_usecwait(MICROSEC >> 2);
93 }
94 
95 
96 int
97 cpr_init(int fcn)
98 {
99 	/*
100 	 * Allow only one suspend/resume process.
101 	 */
102 	if (mutex_tryenter(&cpr_slock) == 0)
103 		return (EBUSY);
104 
105 	CPR->c_flags = 0;
106 	CPR->c_substate = 0;
107 	CPR->c_cprboot_magic = 0;
108 	CPR->c_alloc_cnt = 0;
109 
110 	CPR->c_fcn = fcn;
111 	if (fcn == AD_CPR_REUSABLE)
112 		CPR->c_flags |= C_REUSABLE;
113 	else
114 		CPR->c_flags |= C_SUSPENDING;
115 	if (fcn != AD_CPR_NOCOMPRESS && fcn != AD_CPR_TESTNOZ)
116 		CPR->c_flags |= C_COMPRESSING;
117 	/*
118 	 * reserve CPR_MAXCONTIG virtual pages for cpr_dump()
119 	 */
120 	CPR->c_mapping_area = i_cpr_map_setup();
121 	if (CPR->c_mapping_area == 0) {		/* no space in kernelmap */
122 		cpr_err(CE_CONT, "Unable to alloc from kernelmap.\n");
123 		mutex_exit(&cpr_slock);
124 		return (EAGAIN);
125 	}
126 	if (cpr_debug & CPR_DEBUG3)
127 		cpr_err(CE_CONT, "Reserved virtual range from 0x%p for writing "
128 		    "kas\n", (void *)CPR->c_mapping_area);
129 
130 	return (0);
131 }
132 
133 /*
134  * This routine releases any resources used during the checkpoint.
135  */
136 void
137 cpr_done(void)
138 {
139 	cpr_stat_cleanup();
140 	i_cpr_bitmap_cleanup();
141 
142 	/*
143 	 * Free pages used by cpr buffers.
144 	 */
145 	if (cpr_buf) {
146 		kmem_free(cpr_buf, cpr_buf_size);
147 		cpr_buf = NULL;
148 	}
149 	if (cpr_pagedata) {
150 		kmem_free(cpr_pagedata, cpr_pagedata_size);
151 		cpr_pagedata = NULL;
152 	}
153 
154 	i_cpr_free_memory_resources();
155 	mutex_exit(&cpr_slock);
156 	cpr_err(CE_CONT, "System has been resumed.\n");
157 }
158 
159 
160 /*
161  * reads config data into cprconfig
162  */
163 static int
164 cpr_get_config(void)
165 {
166 	static char config_path[] = CPR_CONFIG;
167 	struct cprconfig *cf = &cprconfig;
168 	struct vnode *vp;
169 	char *fmt;
170 	int err;
171 
172 	if (cprconfig_loaded)
173 		return (0);
174 
175 	fmt = "cannot %s config file \"%s\", error %d\n";
176 	if (err = vn_open(config_path, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0)) {
177 		cpr_err(CE_CONT, fmt, "open", config_path, err);
178 		return (err);
179 	}
180 
181 	err = cpr_rdwr(UIO_READ, vp, cf, sizeof (*cf));
182 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED());
183 	VN_RELE(vp);
184 	if (err) {
185 		cpr_err(CE_CONT, fmt, "read", config_path, err);
186 		return (err);
187 	}
188 
189 	if (cf->cf_magic == CPR_CONFIG_MAGIC)
190 		cprconfig_loaded = 1;
191 	else {
192 		cpr_err(CE_CONT, "invalid config file \"%s\", "
193 		    "rerun pmconfig(1M)\n", config_path);
194 		err = EINVAL;
195 	}
196 
197 	return (err);
198 }
199 
200 
201 /*
202  * concat fs and path fields of the cprconfig structure;
203  * returns pointer to the base of static data
204  */
205 static char *
206 cpr_cprconfig_to_path(void)
207 {
208 	static char full_path[MAXNAMELEN];
209 	struct cprconfig *cf = &cprconfig;
210 	char *ptr;
211 
212 	/*
213 	 * build /fs/path without extra '/'
214 	 */
215 	(void) strcpy(full_path, cf->cf_fs);
216 	if (strcmp(cf->cf_fs, "/"))
217 		(void) strcat(full_path, "/");
218 	ptr = cf->cf_path;
219 	if (*ptr == '/')
220 		ptr++;
221 	(void) strcat(full_path, ptr);
222 	return (full_path);
223 }
224 
225 
226 /*
227  * Verify that the information in the configuration file regarding the
228  * location for the statefile is still valid, depending on cf_type.
229  * for CFT_UFS, cf_fs must still be a mounted filesystem, it must be
230  *	mounted on the same device as when pmconfig was last run,
231  *	and the translation of that device to a node in the prom's
232  *	device tree must be the same as when pmconfig was last run.
233  * for CFT_SPEC, cf_path must be the path to a block special file,
234  *	it must have no file system mounted on it,
235  *	and the translation of that device to a node in the prom's
236  *	device tree must be the same as when pmconfig was last run.
237  */
238 static int
239 cpr_verify_statefile_path(void)
240 {
241 	struct cprconfig *cf = &cprconfig;
242 	static const char long_name[] = "Statefile pathname is too long.\n";
243 	static const char lookup_fmt[] = "Lookup failed for "
244 	    "cpr statefile device %s.\n";
245 	static const char path_chg_fmt[] = "Device path for statefile "
246 	    "has changed from %s to %s.\t%s\n";
247 	static const char rerun[] = "Please rerun pmconfig(1m).";
248 	struct vfs *vfsp = NULL, *vfsp_save = rootvfs;
249 	ufsvfs_t *ufsvfsp = (ufsvfs_t *)rootvfs->vfs_data;
250 	ufsvfs_t *ufsvfsp_save = ufsvfsp;
251 	int error;
252 	struct vnode *vp;
253 	char *slash, *tail, *longest;
254 	char *errstr;
255 	int found = 0;
256 	union {
257 		char un_devpath[OBP_MAXPATHLEN];
258 		char un_sfpath[MAXNAMELEN];
259 	} un;
260 #define	devpath	un.un_devpath
261 #define	sfpath	un.un_sfpath
262 
263 	ASSERT(cprconfig_loaded);
264 	/*
265 	 * We need not worry about locking or the timing of releasing
266 	 * the vnode, since we are single-threaded now.
267 	 */
268 
269 	switch (cf->cf_type) {
270 	case CFT_SPEC:
271 		if (strlen(cf->cf_path) > sizeof (sfpath)) {
272 			cpr_err(CE_CONT, long_name);
273 			return (ENAMETOOLONG);
274 		}
275 		if ((error = lookupname(cf->cf_devfs,
276 		    UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0) {
277 			cpr_err(CE_CONT, lookup_fmt, cf->cf_devfs);
278 			return (error);
279 		}
280 		if (vp->v_type != VBLK)
281 			errstr = "statefile must be a block device";
282 		else if (vfs_devismounted(vp->v_rdev))
283 			errstr = "statefile device must not "
284 			    "have a file system mounted on it";
285 		else if (IS_SWAPVP(vp))
286 			errstr = "statefile device must not "
287 			    "be configured as swap file";
288 		else
289 			errstr = NULL;
290 
291 		VN_RELE(vp);
292 		if (errstr) {
293 			cpr_err(CE_CONT, "%s.\n", errstr);
294 			return (ENOTSUP);
295 		}
296 
297 		error = i_devname_to_promname(cf->cf_devfs, devpath,
298 		    OBP_MAXPATHLEN);
299 		if (error || strcmp(devpath, cf->cf_dev_prom)) {
300 			cpr_err(CE_CONT, path_chg_fmt,
301 			    cf->cf_dev_prom, devpath, rerun);
302 		}
303 		return (error);
304 	case CFT_UFS:
305 		break;		/* don't indent all the original code */
306 	default:
307 		cpr_err(CE_PANIC, "invalid cf_type");
308 	}
309 
310 	/*
311 	 * The original code for UFS statefile
312 	 */
313 	if (strlen(cf->cf_fs) + strlen(cf->cf_path) + 2 > sizeof (sfpath)) {
314 		cpr_err(CE_CONT, long_name);
315 		return (ENAMETOOLONG);
316 	}
317 
318 	bzero(sfpath, sizeof (sfpath));
319 	(void) strcpy(sfpath, cpr_cprconfig_to_path());
320 
321 	if (*sfpath != '/') {
322 		cpr_err(CE_CONT, "Statefile pathname %s "
323 		    "must begin with a /\n", sfpath);
324 		return (EINVAL);
325 	}
326 
327 	/*
328 	 * Find the longest prefix of the statefile pathname which
329 	 * is the mountpoint of a filesystem.  This string must
330 	 * match the cf_fs field we read from the config file.  Other-
331 	 * wise the user has changed things without running pmconfig.
332 	 */
333 	tail = longest = sfpath + 1;	/* pt beyond the leading "/" */
334 	while ((slash = strchr(tail, '/')) != NULL) {
335 		*slash = '\0';	  /* temporarily terminate the string */
336 		if ((error = lookupname(sfpath,
337 		    UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0) {
338 			*slash = '/';
339 			cpr_err(CE_CONT, "A directory in the "
340 			    "statefile path %s was not found.\n", sfpath);
341 			VN_RELE(vp);
342 
343 			return (error);
344 		}
345 
346 		vfs_list_read_lock();
347 		vfsp = rootvfs;
348 		do {
349 			ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
350 			if (ufsvfsp != NULL && ufsvfsp->vfs_root == vp) {
351 				found = 1;
352 				break;
353 			}
354 			vfsp = vfsp->vfs_next;
355 		} while (vfsp != rootvfs);
356 		vfs_list_unlock();
357 
358 		/*
359 		 * If we have found a filesystem mounted on the current
360 		 * path prefix, remember the end of the string in
361 		 * "longest".  If it happens to be the the exact fs
362 		 * saved in the configuration file, save the current
363 		 * ufsvfsp so we can make additional checks further down.
364 		 */
365 		if (found) {
366 			longest = slash;
367 			if (strcmp(cf->cf_fs, sfpath) == 0) {
368 				ufsvfsp_save = ufsvfsp;
369 				vfsp_save = vfsp;
370 			}
371 			found = 0;
372 		}
373 
374 		VN_RELE(vp);
375 		*slash = '/';
376 		tail = slash + 1;
377 	}
378 	*longest = '\0';
379 	if (cpr_is_ufs(vfsp_save) == 0 || strcmp(cf->cf_fs, sfpath)) {
380 		cpr_err(CE_CONT, "Filesystem containing "
381 		    "the statefile when pmconfig was run (%s) has "
382 		    "changed to %s. %s\n", cf->cf_fs, sfpath, rerun);
383 		return (EINVAL);
384 	}
385 
386 	if ((error = lookupname(cf->cf_devfs,
387 	    UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0) {
388 		cpr_err(CE_CONT, lookup_fmt, cf->cf_devfs);
389 		return (error);
390 	}
391 
392 	if (ufsvfsp_save->vfs_devvp->v_rdev != vp->v_rdev) {
393 		cpr_err(CE_CONT, "Filesystem containing "
394 		    "statefile no longer mounted on device %s. "
395 		    "See power.conf(4).", cf->cf_devfs);
396 		VN_RELE(vp);
397 		return (ENXIO);
398 	}
399 	VN_RELE(vp);
400 
401 	error = i_devname_to_promname(cf->cf_devfs, devpath, OBP_MAXPATHLEN);
402 	if (error || strcmp(devpath, cf->cf_dev_prom)) {
403 		cpr_err(CE_CONT, path_chg_fmt,
404 		    cf->cf_dev_prom, devpath, rerun);
405 		return (error);
406 	}
407 
408 	return (0);
409 }
410 
411 /*
412  * Make sure that the statefile can be used as a block special statefile
413  * (meaning that is exists and has nothing mounted on it)
414  * Returns errno if not a valid statefile.
415  */
416 int
417 cpr_check_spec_statefile(void)
418 {
419 	int err;
420 
421 	if (err = cpr_get_config())
422 		return (err);
423 	ASSERT(cprconfig.cf_type == CFT_SPEC);
424 
425 	if (cprconfig.cf_devfs == NULL)
426 		return (ENXIO);
427 
428 	return (cpr_verify_statefile_path());
429 
430 }
431 
432 int
433 cpr_alloc_statefile(int alloc_retry)
434 {
435 	register int rc = 0;
436 	char *str;
437 
438 	/*
439 	 * Statefile size validation. If checkpoint the first time, disk blocks
440 	 * allocation will be done; otherwise, just do file size check.
441 	 * if statefile allocation is being retried, C_VP will be inited
442 	 */
443 	if (alloc_retry) {
444 		str = "\n-->Retrying statefile allocation...";
445 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG7))
446 			prom_printf(str);
447 		if (C_VP->v_type != VBLK)
448 			(void) VOP_DUMPCTL(C_VP, DUMP_FREE, NULL);
449 	} else {
450 		/*
451 		 * Open an exiting file for writing, the state file needs to be
452 		 * pre-allocated since we can't and don't want to do allocation
453 		 * during checkpoint (too much of the OS is disabled).
454 		 *    - do a preliminary size checking here, if it is too small,
455 		 *	allocate more space internally and retry.
456 		 *    - check the vp to make sure it's the right type.
457 		 */
458 		char *path = cpr_build_statefile_path();
459 
460 		if (path == NULL)
461 			return (ENXIO);
462 		else if (rc = cpr_verify_statefile_path())
463 			return (rc);
464 
465 		if (rc = vn_open(path, UIO_SYSSPACE,
466 		    FCREAT|FWRITE, 0600, &C_VP, CRCREAT, 0)) {
467 			cpr_err(CE_WARN, "cannot open statefile %s", path);
468 			return (rc);
469 		}
470 	}
471 
472 	/*
473 	 * Only ufs and block special statefiles supported
474 	 */
475 	if (C_VP->v_type != VREG && C_VP->v_type != VBLK) {
476 		cpr_err(CE_CONT,
477 		    "Statefile must be regular file or block special file.");
478 		return (EACCES);
479 	}
480 
481 	if (rc = cpr_statefile_ok(C_VP, alloc_retry))
482 		return (rc);
483 
484 	if (C_VP->v_type != VBLK) {
485 		/*
486 		 * sync out the fs change due to the statefile reservation.
487 		 */
488 		(void) VFS_SYNC(C_VP->v_vfsp, 0, CRED());
489 
490 		/*
491 		 * Validate disk blocks allocation for the state file.
492 		 * Ask the file system prepare itself for the dump operation.
493 		 */
494 		if (rc = VOP_DUMPCTL(C_VP, DUMP_ALLOC, NULL)) {
495 			cpr_err(CE_CONT, "Error allocating "
496 			    "blocks for cpr statefile.");
497 			return (rc);
498 		}
499 	}
500 	return (0);
501 }
502 
503 
504 /*
505  * Lookup device size and return available space in bytes.
506  * NOTE: Since prop_op(9E) can't tell the difference between a character
507  * and a block reference, it is ok to ask for "Size" instead of "Nblocks".
508  */
509 size_t
510 cpr_get_devsize(dev_t dev)
511 {
512 	size_t bytes = 0;
513 
514 	bytes = cdev_Size(dev);
515 	if (bytes == 0)
516 		bytes = cdev_size(dev);
517 
518 	if (bytes > CPR_SPEC_OFFSET)
519 		bytes -= CPR_SPEC_OFFSET;
520 	else
521 		bytes = 0;
522 
523 	return (bytes);
524 }
525 
526 
527 /*
528  * increase statefile size
529  */
530 static int
531 cpr_grow_statefile(vnode_t *vp, u_longlong_t newsize)
532 {
533 	extern uchar_t cpr_pagecopy[];
534 	struct inode *ip = VTOI(vp);
535 	u_longlong_t offset;
536 	int error, increase;
537 	ssize_t resid;
538 
539 	rw_enter(&ip->i_contents, RW_READER);
540 	increase = (ip->i_size < newsize);
541 	offset = ip->i_size;
542 	rw_exit(&ip->i_contents);
543 
544 	if (increase == 0)
545 		return (0);
546 
547 	/*
548 	 * write to each logical block to reserve disk space
549 	 */
550 	error = 0;
551 	cpr_pagecopy[0] = '1';
552 	for (; offset < newsize; offset += ip->i_fs->fs_bsize) {
553 		if (error = vn_rdwr(UIO_WRITE, vp, (caddr_t)cpr_pagecopy,
554 		    ip->i_fs->fs_bsize, (offset_t)offset, UIO_SYSSPACE, 0,
555 		    (rlim64_t)MAXOFF_T, CRED(), &resid)) {
556 			if (error == ENOSPC) {
557 				cpr_err(CE_WARN, "error %d while reserving "
558 				    "disk space for statefile %s\n"
559 				    "wanted %lld bytes, file is %lld short",
560 				    error, cpr_cprconfig_to_path(),
561 				    newsize, newsize - offset);
562 			}
563 			break;
564 		}
565 	}
566 	return (error);
567 }
568 
569 
570 /*
571  * do a simple estimate of the space needed to hold the statefile
572  * taking compression into account, but be fairly conservative
573  * so we have a better chance of completing; when dump fails,
574  * the retry cost is fairly high.
575  *
576  * Do disk blocks allocation for the state file if no space has
577  * been allocated yet. Since the state file will not be removed,
578  * allocation should only be done once.
579  */
580 static int
581 cpr_statefile_ok(vnode_t *vp, int alloc_retry)
582 {
583 	extern size_t cpr_bitmap_size;
584 	struct inode *ip = VTOI(vp);
585 	const int UCOMP_RATE = 20; /* comp. ratio*10 for user pages */
586 	u_longlong_t size, isize, ksize, raw_data;
587 	char *str, *est_fmt;
588 	size_t space;
589 	int error;
590 
591 	/*
592 	 * number of pages short for swapping.
593 	 */
594 	STAT->cs_nosw_pages = k_anoninfo.ani_mem_resv;
595 	if (STAT->cs_nosw_pages < 0)
596 		STAT->cs_nosw_pages = 0;
597 
598 	str = "cpr_statefile_ok:";
599 
600 	CPR_DEBUG(CPR_DEBUG9, "Phys swap: max=%lu resv=%lu\n",
601 	    k_anoninfo.ani_max, k_anoninfo.ani_phys_resv);
602 	CPR_DEBUG(CPR_DEBUG9, "Mem swap: max=%ld resv=%lu\n",
603 	    MAX(availrmem - swapfs_minfree, 0),
604 	    k_anoninfo.ani_mem_resv);
605 	CPR_DEBUG(CPR_DEBUG9, "Total available swap: %ld\n",
606 	    CURRENT_TOTAL_AVAILABLE_SWAP);
607 
608 	/*
609 	 * try increasing filesize by 15%
610 	 */
611 	if (alloc_retry) {
612 		/*
613 		 * block device doesn't get any bigger
614 		 */
615 		if (vp->v_type == VBLK) {
616 			if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))
617 				prom_printf(
618 				    "Retry statefile on special file\n");
619 			return (ENOMEM);
620 		} else {
621 			rw_enter(&ip->i_contents, RW_READER);
622 			size = (ip->i_size * SIZE_RATE) / INTEGRAL;
623 			rw_exit(&ip->i_contents);
624 		}
625 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))
626 			prom_printf("Retry statefile size = %lld\n", size);
627 	} else {
628 		u_longlong_t cpd_size;
629 		pgcnt_t npages, nback;
630 		int ndvram;
631 
632 		ndvram = 0;
633 		(void) callb_execute_class(CB_CL_CPR_FB,
634 		    (int)(uintptr_t)&ndvram);
635 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))
636 			prom_printf("ndvram size = %d\n", ndvram);
637 
638 		/*
639 		 * estimate 1 cpd_t for every (CPR_MAXCONTIG / 2) pages
640 		 */
641 		npages = cpr_count_kpages(REGULAR_BITMAP, cpr_nobit);
642 		cpd_size = sizeof (cpd_t) * (npages / (CPR_MAXCONTIG / 2));
643 		raw_data = cpd_size + cpr_bitmap_size;
644 		ksize = ndvram + mmu_ptob(npages);
645 
646 		est_fmt = "%s estimated size with "
647 		    "%scompression %lld, ksize %lld\n";
648 		nback = mmu_ptob(STAT->cs_nosw_pages);
649 		if (CPR->c_flags & C_COMPRESSING) {
650 			size = ((ksize * COMPRESS_PERCENT) / INTEGRAL) +
651 			    raw_data + ((nback * 10) / UCOMP_RATE);
652 			CPR_DEBUG(CPR_DEBUG1, est_fmt, str, "", size, ksize);
653 		} else {
654 			size = ksize + raw_data + nback;
655 			CPR_DEBUG(CPR_DEBUG1, est_fmt, str, "no ",
656 			    size, ksize);
657 		}
658 	}
659 
660 	/*
661 	 * All this is much simpler for a block device
662 	 */
663 	if (vp->v_type == VBLK) {
664 		space = cpr_get_devsize(vp->v_rdev);
665 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))
666 			prom_printf("statefile dev size %lu\n", space);
667 
668 		/*
669 		 * Export the estimated filesize info, this value will be
670 		 * compared before dumping out the statefile in the case of
671 		 * no compression.
672 		 */
673 		STAT->cs_est_statefsz = size;
674 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))
675 			prom_printf("%s Estimated statefile size %llu, "
676 			    "space %lu\n", str, size, space);
677 		if (size > space) {
678 			cpr_err(CE_CONT, "Statefile partition too small.");
679 			return (ENOMEM);
680 		}
681 		return (0);
682 	} else {
683 		if (CPR->c_alloc_cnt++ > C_MAX_ALLOC_RETRY) {
684 			cpr_err(CE_CONT, "Statefile allocation retry failed\n");
685 			return (ENOMEM);
686 		}
687 
688 		/*
689 		 * Estimate space needed for the state file.
690 		 *
691 		 * State file size in bytes:
692 		 * 	kernel size + non-cache pte seg +
693 		 *	bitmap size + cpr state file headers size
694 		 * (round up to fs->fs_bsize)
695 		 */
696 		size = blkroundup(ip->i_fs, size);
697 
698 		/*
699 		 * Export the estimated filesize info, this value will be
700 		 * compared before dumping out the statefile in the case of
701 		 * no compression.
702 		 */
703 		STAT->cs_est_statefsz = size;
704 		error = cpr_grow_statefile(vp, size);
705 		if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) {
706 			rw_enter(&ip->i_contents, RW_READER);
707 			isize = ip->i_size;
708 			rw_exit(&ip->i_contents);
709 			prom_printf("%s Estimated statefile size %lld, "
710 			    "i_size %lld\n", str, size, isize);
711 		}
712 
713 		return (error);
714 	}
715 }
716 
717 
718 void
719 cpr_statef_close(void)
720 {
721 	if (C_VP) {
722 		if (!cpr_reusable_mode)
723 			(void) VOP_DUMPCTL(C_VP, DUMP_FREE, NULL);
724 		(void) VOP_CLOSE(C_VP, FWRITE, 1, (offset_t)0, CRED());
725 		VN_RELE(C_VP);
726 		C_VP = 0;
727 	}
728 }
729 
730 
731 /*
732  * open cpr default file and display error
733  */
734 int
735 cpr_open_deffile(int mode, vnode_t **vpp)
736 {
737 	int error;
738 
739 	if (error = cpr_open(cpr_default_path, mode, vpp))
740 		cpr_err(CE_CONT, "cannot open \"%s\", error %d\n",
741 		    cpr_default_path, error);
742 	return (error);
743 }
744 
745 
746 /*
747  * write cdef_t to disk.  This contains the original values of prom
748  * properties that we modify.  We fill in the magic number of the file
749  * here as a signal to the booter code that the state file is valid.
750  * Be sure the file gets synced, since we may be shutting down the OS.
751  */
752 int
753 cpr_write_deffile(cdef_t *cdef)
754 {
755 	struct vnode *vp;
756 	char *str;
757 	int rc;
758 
759 	if (rc = cpr_open_deffile(FCREAT|FWRITE, &vp))
760 		return (rc);
761 
762 	if (rc = cpr_rdwr(UIO_WRITE, vp, cdef, sizeof (*cdef)))
763 		str = "write";
764 	else if (rc = VOP_FSYNC(vp, FSYNC, CRED()))
765 		str = "fsync";
766 	(void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED());
767 	VN_RELE(vp);
768 
769 	if (rc) {
770 		cpr_err(CE_WARN, "%s error %d, file \"%s\"",
771 		    str, rc, cpr_default_path);
772 	}
773 	return (rc);
774 }
775 
776 /*
777  * Clear the magic number in the defaults file.  This tells the booter
778  * program that the state file is not current and thus prevents
779  * any attempt to restore from an obsolete state file.
780  */
781 void
782 cpr_clear_definfo(void)
783 {
784 	struct vnode *vp;
785 	cmini_t mini;
786 
787 	if ((CPR->c_cprboot_magic != CPR_DEFAULT_MAGIC) ||
788 	    cpr_open_deffile(FCREAT|FWRITE, &vp))
789 		return;
790 	mini.magic = mini.reusable = 0;
791 	(void) cpr_rdwr(UIO_WRITE, vp, &mini, sizeof (mini));
792 	(void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED());
793 	VN_RELE(vp);
794 }
795 
796 /*
797  * If the cpr default file is invalid, then we must not be in reusable mode
798  * if it is valid, it tells us our mode
799  */
800 int
801 cpr_get_reusable_mode(void)
802 {
803 	struct vnode *vp;
804 	cmini_t mini;
805 	int rc;
806 
807 	if (cpr_open(cpr_default_path, FREAD, &vp))
808 		return (0);
809 
810 	rc = cpr_rdwr(UIO_READ, vp, &mini, sizeof (mini));
811 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED());
812 	VN_RELE(vp);
813 	if (rc == 0 && mini.magic == CPR_DEFAULT_MAGIC)
814 		return (mini.reusable);
815 
816 	return (0);
817 }
818 
819 /*
820  * clock/time related routines
821  */
822 static time_t   cpr_time_stamp;
823 
824 
825 void
826 cpr_tod_get(cpr_time_t *ctp)
827 {
828 	timestruc_t ts;
829 
830 	mutex_enter(&tod_lock);
831 	ts = tod_get();
832 	mutex_exit(&tod_lock);
833 	ctp->tv_sec = (time32_t)ts.tv_sec;
834 	ctp->tv_nsec = (int32_t)ts.tv_nsec;
835 }
836 
837 void
838 cpr_tod_fault_reset(void)
839 {
840 	mutex_enter(&tod_lock);
841 	tod_fault_reset();
842 	mutex_exit(&tod_lock);
843 }
844 
845 void
846 cpr_save_time(void)
847 {
848 	cpr_time_stamp = gethrestime_sec();
849 }
850 
851 /*
852  * correct time based on saved time stamp or hardware clock
853  */
854 void
855 cpr_restore_time(void)
856 {
857 	clkset(cpr_time_stamp);
858 }
859 
860 /*
861  * CPU ONLINE/OFFLINE CODE
862  */
863 int
864 cpr_mp_offline(void)
865 {
866 	cpu_t *cp, *bootcpu;
867 	int rc = 0;
868 	int brought_up_boot = 0;
869 
870 	/*
871 	 * Do nothing for UP.
872 	 */
873 	if (ncpus == 1)
874 		return (0);
875 
876 	mutex_enter(&cpu_lock);
877 
878 	cpr_save_mp_state();
879 
880 	bootcpu = i_cpr_bootcpu();
881 	if (!CPU_ACTIVE(bootcpu)) {
882 		if ((rc = cpr_p_online(bootcpu, CPU_CPR_ONLINE))) {
883 			mutex_exit(&cpu_lock);
884 			return (rc);
885 		}
886 		brought_up_boot = 1;
887 	}
888 
889 	cp = cpu_list;
890 	do {
891 		if (cp == bootcpu)
892 			continue;
893 		if (cp->cpu_flags & CPU_OFFLINE)
894 			continue;
895 		if ((rc = cpr_p_online(cp, CPU_CPR_OFFLINE))) {
896 			mutex_exit(&cpu_lock);
897 			return (rc);
898 		}
899 	} while ((cp = cp->cpu_next) != cpu_list);
900 	if (brought_up_boot && (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)))
901 		prom_printf("changed cpu %p to state %d\n",
902 		    bootcpu, CPU_CPR_ONLINE);
903 	mutex_exit(&cpu_lock);
904 
905 	return (rc);
906 }
907 
908 int
909 cpr_mp_online(void)
910 {
911 	cpu_t *cp, *bootcpu = CPU;
912 	int rc = 0;
913 
914 	/*
915 	 * Do nothing for UP.
916 	 */
917 	if (ncpus == 1)
918 		return (0);
919 
920 	/*
921 	 * cpr_save_mp_state() sets CPU_CPR_ONLINE in cpu_cpr_flags
922 	 * to indicate a cpu was online at the time of cpr_suspend();
923 	 * now restart those cpus that were marked as CPU_CPR_ONLINE
924 	 * and actually are offline.
925 	 */
926 	mutex_enter(&cpu_lock);
927 	for (cp = bootcpu->cpu_next; cp != bootcpu; cp = cp->cpu_next) {
928 		/*
929 		 * Clear the CPU_FROZEN flag in all cases.
930 		 */
931 		cp->cpu_flags &= ~CPU_FROZEN;
932 
933 		if (CPU_CPR_IS_OFFLINE(cp))
934 			continue;
935 		if (CPU_ACTIVE(cp))
936 			continue;
937 		if ((rc = cpr_p_online(cp, CPU_CPR_ONLINE))) {
938 			mutex_exit(&cpu_lock);
939 			return (rc);
940 		}
941 	}
942 
943 	/*
944 	 * turn off the boot cpu if it was offlined
945 	 */
946 	if (CPU_CPR_IS_OFFLINE(bootcpu)) {
947 		if ((rc = cpr_p_online(bootcpu, CPU_CPR_OFFLINE))) {
948 			mutex_exit(&cpu_lock);
949 			return (rc);
950 		}
951 	}
952 	mutex_exit(&cpu_lock);
953 	return (0);
954 }
955 
956 static void
957 cpr_save_mp_state(void)
958 {
959 	cpu_t *cp;
960 
961 	ASSERT(MUTEX_HELD(&cpu_lock));
962 
963 	cp = cpu_list;
964 	do {
965 		cp->cpu_cpr_flags &= ~CPU_CPR_ONLINE;
966 		if (CPU_ACTIVE(cp))
967 			CPU_SET_CPR_FLAGS(cp, CPU_CPR_ONLINE);
968 	} while ((cp = cp->cpu_next) != cpu_list);
969 }
970 
971 /*
972  * change cpu to online/offline
973  */
974 static int
975 cpr_p_online(cpu_t *cp, int state)
976 {
977 	int rc;
978 
979 	ASSERT(MUTEX_HELD(&cpu_lock));
980 
981 	switch (state) {
982 	case CPU_CPR_ONLINE:
983 		rc = cpu_online(cp);
984 		break;
985 	case CPU_CPR_OFFLINE:
986 		rc = cpu_offline(cp, CPU_FORCED);
987 		break;
988 	}
989 	if (rc) {
990 		cpr_err(CE_WARN, "Failed to change processor %d to "
991 		    "state %d, (errno %d)", cp->cpu_id, state, rc);
992 	}
993 	return (rc);
994 }
995 
996 /*
997  * Construct the pathname of the state file and return a pointer to
998  * caller.  Read the config file to get the mount point of the
999  * filesystem and the pathname within fs.
1000  */
1001 char *
1002 cpr_build_statefile_path(void)
1003 {
1004 	struct cprconfig *cf = &cprconfig;
1005 
1006 	if (cpr_get_config())
1007 		return (NULL);
1008 
1009 	switch (cf->cf_type) {
1010 	case CFT_UFS:
1011 		if (strlen(cf->cf_path) + strlen(cf->cf_fs) >= MAXNAMELEN - 1) {
1012 			cpr_err(CE_CONT, "Statefile path is too long.\n");
1013 			return (NULL);
1014 		}
1015 		return (cpr_cprconfig_to_path());
1016 	case CFT_SPEC:
1017 		return (cf->cf_devfs);
1018 	default:
1019 		cpr_err(CE_PANIC, "invalid statefile type");
1020 		/*NOTREACHED*/
1021 		return (NULL);
1022 	}
1023 }
1024 
1025 int
1026 cpr_statefile_is_spec(void)
1027 {
1028 	if (cpr_get_config())
1029 		return (0);
1030 	return (cprconfig.cf_type == CFT_SPEC);
1031 }
1032 
1033 char *
1034 cpr_get_statefile_prom_path(void)
1035 {
1036 	struct cprconfig *cf = &cprconfig;
1037 
1038 	ASSERT(cprconfig_loaded);
1039 	ASSERT(cf->cf_magic == CPR_CONFIG_MAGIC);
1040 	ASSERT(cf->cf_type == CFT_SPEC);
1041 	return (cf->cf_dev_prom);
1042 }
1043 
1044 
1045 /*
1046  * XXX The following routines need to be in the vfs source code.
1047  */
1048 
1049 int
1050 cpr_is_ufs(struct vfs *vfsp)
1051 {
1052 	char *fsname;
1053 
1054 	fsname = vfssw[vfsp->vfs_fstype].vsw_name;
1055 	return (strcmp(fsname, "ufs") == 0);
1056 }
1057 
1058 /*
1059  * This is a list of file systems that are allowed to be writeable when a
1060  * reusable statefile checkpoint is taken.  They must not have any state that
1061  * cannot be restored to consistency by simply rebooting using the checkpoint.
1062  * (In contrast to ufs, cachefs and pcfs which have disk state that could get
1063  * out of sync with the in-kernel data).
1064  */
1065 int
1066 cpr_reusable_mount_check(void)
1067 {
1068 	struct vfs *vfsp;
1069 	char *fsname;
1070 	char **cpp;
1071 	static char *cpr_writeok_fss[] = {
1072 		"autofs", "devfs", "fd", "lofs", "mntfs", "namefs", "nfs",
1073 		"proc", "tmpfs", "ctfs", "objfs", "dev", NULL
1074 	};
1075 
1076 	vfs_list_read_lock();
1077 	vfsp = rootvfs;
1078 	do {
1079 		if (vfsp->vfs_flag & VFS_RDONLY) {
1080 			vfsp = vfsp->vfs_next;
1081 			continue;
1082 		}
1083 		fsname = vfssw[vfsp->vfs_fstype].vsw_name;
1084 		for (cpp = cpr_writeok_fss; *cpp; cpp++) {
1085 			if (strcmp(fsname, *cpp) == 0)
1086 				break;
1087 		}
1088 		/*
1089 		 * if the inner loop reached the NULL terminator,
1090 		 * the current fs-type does not match any OK-type
1091 		 */
1092 		if (*cpp == NULL) {
1093 			cpr_err(CE_CONT, "a filesystem of type %s is "
1094 			    "mounted read/write.\nReusable statefile requires "
1095 			    "no writeable filesystem of this type be mounted\n",
1096 			    fsname);
1097 			vfs_list_unlock();
1098 			return (EINVAL);
1099 		}
1100 		vfsp = vfsp->vfs_next;
1101 	} while (vfsp != rootvfs);
1102 	vfs_list_unlock();
1103 	return (0);
1104 }
1105 
1106 /*
1107  * Force a fresh read of the cprinfo per uadmin 3 call
1108  */
1109 void
1110 cpr_forget_cprconfig(void)
1111 {
1112 	cprconfig_loaded = 0;
1113 }
1114 
1115 
1116 /*
1117  * return statefile offset in DEV_BSIZE units
1118  */
1119 int
1120 cpr_statefile_offset(void)
1121 {
1122 	return (cpr_statefile_is_spec() ? btod(CPR_SPEC_OFFSET) : 0);
1123 }
1124