17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d1a180b0Smaheshvs * Common Development and Distribution License (the "License").
6d1a180b0Smaheshvs * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
2123a1cceaSRoger A. Faulkner
227c478bd9Sstevel@tonic-gate /*
2323a1cceaSRoger A. Faulkner * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bd9Sstevel@tonic-gate * The Regents of the University of California
327c478bd9Sstevel@tonic-gate * All Rights Reserved
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
357c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
367c478bd9Sstevel@tonic-gate * contributors.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * The maximum supported file system size (in sectors) is the
417c478bd9Sstevel@tonic-gate * number of frags that can be represented in an int32_t field
427c478bd9Sstevel@tonic-gate * (INT_MAX) times the maximum number of sectors per frag. Since
437c478bd9Sstevel@tonic-gate * the maximum frag size is MAXBSIZE, the maximum number of sectors
447c478bd9Sstevel@tonic-gate * per frag is MAXBSIZE/DEV_BSIZE.
457c478bd9Sstevel@tonic-gate */
467c478bd9Sstevel@tonic-gate #define FS_MAX (((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate * make file system for cylinder-group style file systems
507c478bd9Sstevel@tonic-gate *
517c478bd9Sstevel@tonic-gate * usage:
527c478bd9Sstevel@tonic-gate *
537c478bd9Sstevel@tonic-gate * mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
547c478bd9Sstevel@tonic-gate * [-o specific_options] special size
557c478bd9Sstevel@tonic-gate * [nsect ntrack bsize fsize cpg minfree rps nbpi opt apc rotdelay
567c478bd9Sstevel@tonic-gate * 2 3 4 5 6 7 8 9 10 11 12
577c478bd9Sstevel@tonic-gate * nrpos maxcontig mtb]
587c478bd9Sstevel@tonic-gate * 13 14 15
597c478bd9Sstevel@tonic-gate *
607c478bd9Sstevel@tonic-gate * where specific_options are:
617c478bd9Sstevel@tonic-gate * N - no create
627c478bd9Sstevel@tonic-gate * nsect - The number of sectors per track
637c478bd9Sstevel@tonic-gate * ntrack - The number of tracks per cylinder
647c478bd9Sstevel@tonic-gate * bsize - block size
657c478bd9Sstevel@tonic-gate * fragsize - fragment size
667c478bd9Sstevel@tonic-gate * cgsize - The number of disk cylinders per cylinder group.
677c478bd9Sstevel@tonic-gate * free - minimum free space
687c478bd9Sstevel@tonic-gate * rps - rotational speed (rev/sec).
697c478bd9Sstevel@tonic-gate * nbpi - number of data bytes per allocated inode
707c478bd9Sstevel@tonic-gate * opt - optimization (space, time)
717c478bd9Sstevel@tonic-gate * apc - number of alternates
727c478bd9Sstevel@tonic-gate * gap - gap size
737c478bd9Sstevel@tonic-gate * nrpos - number of rotational positions
747c478bd9Sstevel@tonic-gate * maxcontig - maximum number of logical blocks that will be
757c478bd9Sstevel@tonic-gate * allocated contiguously before inserting rotational delay
767c478bd9Sstevel@tonic-gate * mtb - if "y", set up file system for eventual growth to over a
777c478bd9Sstevel@tonic-gate * a terabyte
787c478bd9Sstevel@tonic-gate * -P Do not grow the file system, but print on stdout the maximal
797c478bd9Sstevel@tonic-gate * size in sectors to which the file system can be increased. The calculated
807c478bd9Sstevel@tonic-gate * size is limited by the value provided by the operand size.
817c478bd9Sstevel@tonic-gate *
827c478bd9Sstevel@tonic-gate * Note that -P is a project-private interface and together with -G intended
837c478bd9Sstevel@tonic-gate * to be used only by the growfs script. It is therefore purposely not
847c478bd9Sstevel@tonic-gate * documented in the man page.
857c478bd9Sstevel@tonic-gate * The -P option is covered by PSARC case 2003/422.
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate * The following constants set the defaults used for the number
907c478bd9Sstevel@tonic-gate * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
917c478bd9Sstevel@tonic-gate *
927c478bd9Sstevel@tonic-gate * NSECT NTRAK
937c478bd9Sstevel@tonic-gate * 72MB CDC 18 9
947c478bd9Sstevel@tonic-gate * 30MB CDC 18 5
957c478bd9Sstevel@tonic-gate * 720KB Diskette 9 2
966451fdbcSvsakar *
976451fdbcSvsakar * However the defaults will be different for disks larger than CHSLIMIT.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate #define DFLNSECT 32
1017c478bd9Sstevel@tonic-gate #define DFLNTRAK 16
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1046451fdbcSvsakar * The following default sectors and tracks values are used for
1056451fdbcSvsakar * non-efi disks that are larger than the CHS addressing limit. The
1066451fdbcSvsakar * existing default cpg of 16 (DESCPG) holds good for larger disks too.
1076451fdbcSvsakar */
1086451fdbcSvsakar #define DEF_SECTORS_EFI 128
1096451fdbcSvsakar #define DEF_TRACKS_EFI 48
1106451fdbcSvsakar
1116451fdbcSvsakar /*
1126451fdbcSvsakar * The maximum number of cylinders in a group depends upon how much
1136451fdbcSvsakar * information can be stored on a single cylinder. The default is to
1146451fdbcSvsakar * use 16 cylinders per group. This is effectively tradition - it was
1156451fdbcSvsakar * the largest value acceptable under SunOs 4.1
1166451fdbcSvsakar */
1176451fdbcSvsakar #define DESCPG 16 /* desired fs_cpg */
1186451fdbcSvsakar
1196451fdbcSvsakar /*
1207c478bd9Sstevel@tonic-gate * The following two constants set the default block and fragment sizes.
1217c478bd9Sstevel@tonic-gate * Both constants must be a power of 2 and meet the following constraints:
1227c478bd9Sstevel@tonic-gate * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
1237c478bd9Sstevel@tonic-gate * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
1247c478bd9Sstevel@tonic-gate * DESBLKSIZE / DESFRAGSIZE <= 8
1257c478bd9Sstevel@tonic-gate */
1267c478bd9Sstevel@tonic-gate #define DESBLKSIZE 8192
1277c478bd9Sstevel@tonic-gate #define DESFRAGSIZE 1024
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate * MINFREE gives the minimum acceptable percentage of file system
1317c478bd9Sstevel@tonic-gate * blocks which may be free. If the freelist drops below this level
1327c478bd9Sstevel@tonic-gate * only the superuser may continue to allocate blocks. This may
1337c478bd9Sstevel@tonic-gate * be set to 0 if no reserve of free blocks is deemed necessary,
1347c478bd9Sstevel@tonic-gate * however throughput drops by fifty percent if the file system
1357c478bd9Sstevel@tonic-gate * is run at between 90% and 100% full; thus the default value of
1367c478bd9Sstevel@tonic-gate * fs_minfree is 10%. With 10% free space, fragmentation is not a
1377c478bd9Sstevel@tonic-gate * problem, so we choose to optimize for time.
1387c478bd9Sstevel@tonic-gate */
1397c478bd9Sstevel@tonic-gate #define MINFREE 10
1407c478bd9Sstevel@tonic-gate #define DEFAULTOPT FS_OPTTIME
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate * ROTDELAY gives the minimum number of milliseconds to initiate
1447c478bd9Sstevel@tonic-gate * another disk transfer on the same cylinder. It is no longer used
1457c478bd9Sstevel@tonic-gate * and will always default to 0.
1467c478bd9Sstevel@tonic-gate */
1477c478bd9Sstevel@tonic-gate #define ROTDELAY 0
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate * MAXBLKPG determines the maximum number of data blocks which are
1517c478bd9Sstevel@tonic-gate * placed in a single cylinder group. The default is one indirect
1527c478bd9Sstevel@tonic-gate * block worth of data blocks.
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate #define MAXBLKPG(bsize) ((bsize) / sizeof (daddr32_t))
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate * Each file system has a number of inodes statically allocated.
1587c478bd9Sstevel@tonic-gate * We allocate one inode slot per NBPI bytes, expecting this
1597c478bd9Sstevel@tonic-gate * to be far more than we will ever need.
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate #define NBPI 2048 /* Number Bytes Per Inode */
1627c478bd9Sstevel@tonic-gate #define MTB_NBPI (MB) /* Number Bytes Per Inode for multi-terabyte */
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate * Disks are assumed to rotate at 60HZ, unless otherwise specified.
1667c478bd9Sstevel@tonic-gate */
1677c478bd9Sstevel@tonic-gate #define DEFHZ 60
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * Cylinder group related limits.
1717c478bd9Sstevel@tonic-gate *
1727c478bd9Sstevel@tonic-gate * For each cylinder we keep track of the availability of blocks at different
1737c478bd9Sstevel@tonic-gate * rotational positions, so that we can lay out the data to be picked
1747c478bd9Sstevel@tonic-gate * up with minimum rotational latency. NRPOS is the number of rotational
1757c478bd9Sstevel@tonic-gate * positions which we distinguish. With NRPOS 8 the resolution of our
1767c478bd9Sstevel@tonic-gate * summary information is 2ms for a typical 3600 rpm drive.
1777c478bd9Sstevel@tonic-gate */
1787c478bd9Sstevel@tonic-gate #define NRPOS 8 /* number distinct rotational positions */
1797c478bd9Sstevel@tonic-gate
1806451fdbcSvsakar #ifdef DEBUG
1816451fdbcSvsakar #define dprintf(x) printf x
1826451fdbcSvsakar #else
1836451fdbcSvsakar #define dprintf(x)
1846451fdbcSvsakar #endif
1856451fdbcSvsakar
1866451fdbcSvsakar /*
1876451fdbcSvsakar * For the -N option, when calculating the backup superblocks, do not print
1886451fdbcSvsakar * them if we are not really sure. We may have to try an alternate method of
1896451fdbcSvsakar * arriving at the superblocks. So defer printing till a handful of superblocks
1906451fdbcSvsakar * look good.
1916451fdbcSvsakar */
1926451fdbcSvsakar #define tprintf(x) if (Nflag && retry) \
1936d24e334Svsakar (void) strncat(tmpbuf, x, strlen(x)); \
1946451fdbcSvsakar else \
1956451fdbcSvsakar (void) fprintf(stderr, x);
1966451fdbcSvsakar
1976451fdbcSvsakar #define ALTSB 32 /* Location of first backup superblock */
1986451fdbcSvsakar
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * range_check "user_supplied" flag values.
2017c478bd9Sstevel@tonic-gate */
2027c478bd9Sstevel@tonic-gate #define RC_DEFAULT 0
2037c478bd9Sstevel@tonic-gate #define RC_KEYWORD 1
2047c478bd9Sstevel@tonic-gate #define RC_POSITIONAL 2
2057c478bd9Sstevel@tonic-gate
206303bf60bSsdebnath /*
207303bf60bSsdebnath * ufs hole
208303bf60bSsdebnath */
209303bf60bSsdebnath #define UFS_HOLE -1
210303bf60bSsdebnath
2117c478bd9Sstevel@tonic-gate #ifndef STANDALONE
2127c478bd9Sstevel@tonic-gate #include <stdio.h>
2137c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
2147c478bd9Sstevel@tonic-gate #endif
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate #include <stdlib.h>
2177c478bd9Sstevel@tonic-gate #include <unistd.h>
2187c478bd9Sstevel@tonic-gate #include <malloc.h>
2197c478bd9Sstevel@tonic-gate #include <string.h>
2207c478bd9Sstevel@tonic-gate #include <strings.h>
2217c478bd9Sstevel@tonic-gate #include <ctype.h>
2227c478bd9Sstevel@tonic-gate #include <errno.h>
2237c478bd9Sstevel@tonic-gate #include <sys/param.h>
2247c478bd9Sstevel@tonic-gate #include <time.h>
2257c478bd9Sstevel@tonic-gate #include <sys/types.h>
2267c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
2277c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
2287c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
2297c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
2307c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
2317c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
2327c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
2337c478bd9Sstevel@tonic-gate #include <sys/filio.h>
2347c478bd9Sstevel@tonic-gate #include <limits.h>
2357c478bd9Sstevel@tonic-gate #include <sys/int_const.h>
2367c478bd9Sstevel@tonic-gate #include <signal.h>
2377c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
2387c478bd9Sstevel@tonic-gate #include "roll_log.h"
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate #define bcopy(f, t, n) (void) memcpy(t, f, n)
2417c478bd9Sstevel@tonic-gate #define bzero(s, n) (void) memset(s, 0, n)
2427c478bd9Sstevel@tonic-gate #define bcmp(s, d, n) memcmp(s, d, n)
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate #define index(s, r) strchr(s, r)
2457c478bd9Sstevel@tonic-gate #define rindex(s, r) strrchr(s, r)
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
2487c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
2497c478bd9Sstevel@tonic-gate #include <locale.h>
2507c478bd9Sstevel@tonic-gate #include <fcntl.h>
2517c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> /* for ENDIAN defines */
2527c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
2557c478bd9Sstevel@tonic-gate #include <sys/asynch.h>
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate extern offset_t llseek();
2587c478bd9Sstevel@tonic-gate extern char *getfullblkname();
2597c478bd9Sstevel@tonic-gate extern long lrand48();
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate extern int optind;
2627c478bd9Sstevel@tonic-gate extern char *optarg;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate * The size of a cylinder group is calculated by CGSIZE. The maximum size
2677c478bd9Sstevel@tonic-gate * is limited by the fact that cylinder groups are at most one block.
2687c478bd9Sstevel@tonic-gate * Its size is derived from the size of the maps maintained in the
2697c478bd9Sstevel@tonic-gate * cylinder group and the (struct cg) size.
2707c478bd9Sstevel@tonic-gate */
2717c478bd9Sstevel@tonic-gate #define CGSIZE(fs) \
2727c478bd9Sstevel@tonic-gate /* base cg */ (sizeof (struct cg) + \
2737c478bd9Sstevel@tonic-gate /* blktot size */ (fs)->fs_cpg * sizeof (long) + \
2747c478bd9Sstevel@tonic-gate /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
2757c478bd9Sstevel@tonic-gate /* inode map */ howmany((fs)->fs_ipg, NBBY) + \
2767c478bd9Sstevel@tonic-gate /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate * We limit the size of the inode map to be no more than a
2807c478bd9Sstevel@tonic-gate * third of the cylinder group space, since we must leave at
2817c478bd9Sstevel@tonic-gate * least an equal amount of space for the block map.
2827c478bd9Sstevel@tonic-gate *
2837c478bd9Sstevel@tonic-gate * N.B.: MAXIpG must be a multiple of INOPB(fs).
2847c478bd9Sstevel@tonic-gate */
2857c478bd9Sstevel@tonic-gate #define MAXIpG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * Same as MAXIpG, but parameterized by the block size (b) and the
2897c478bd9Sstevel@tonic-gate * cylinder group divisor (d), which is the reciprocal of the fraction of the
2907c478bd9Sstevel@tonic-gate * cylinder group overhead block that is used for the inode map. So for
2917c478bd9Sstevel@tonic-gate * example, if d = 5, the macro's computation assumes that 1/5 of the
2927c478bd9Sstevel@tonic-gate * cylinder group overhead block can be dedicated to the inode map.
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate #define MAXIpG_B(b, d) roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate #define UMASK 0755
2977c478bd9Sstevel@tonic-gate #define MAXINOPB (MAXBSIZE / sizeof (struct dinode))
2987c478bd9Sstevel@tonic-gate #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
2997c478bd9Sstevel@tonic-gate #define MB (1024*1024)
3007c478bd9Sstevel@tonic-gate #define BETWEEN(x, l, h) ((x) >= (l) && (x) <= (h))
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate * Used to set the inode generation number. Since both inodes and dinodes
3047c478bd9Sstevel@tonic-gate * are dealt with, we really need a pointer to an icommon here.
3057c478bd9Sstevel@tonic-gate */
3067c478bd9Sstevel@tonic-gate #define IRANDOMIZE(icp) (icp)->ic_gen = lrand48();
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * Flags for number()
3107c478bd9Sstevel@tonic-gate */
3117c478bd9Sstevel@tonic-gate #define ALLOW_PERCENT 0x01 /* allow trailing `%' on number */
3127c478bd9Sstevel@tonic-gate #define ALLOW_MS1 0x02 /* allow trailing `ms', state 1 */
3137c478bd9Sstevel@tonic-gate #define ALLOW_MS2 0x04 /* allow trailing `ms', state 2 */
3147c478bd9Sstevel@tonic-gate #define ALLOW_END_ONLY 0x08 /* must be at end of number & suffixes */
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate #define MAXAIO 1000 /* maximum number of outstanding I/O's we'll manage */
3177c478bd9Sstevel@tonic-gate #define BLOCK 1 /* block in aiowait */
3187c478bd9Sstevel@tonic-gate #define NOBLOCK 0 /* don't block in aiowait */
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate #define RELEASE 1 /* free an aio buffer after use */
3217c478bd9Sstevel@tonic-gate #define SAVE 0 /* don't free the buffer */
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate typedef struct aio_trans {
3247c478bd9Sstevel@tonic-gate aio_result_t resultbuf;
3257c478bd9Sstevel@tonic-gate diskaddr_t bno;
3267c478bd9Sstevel@tonic-gate char *buffer;
3277c478bd9Sstevel@tonic-gate int size;
3287c478bd9Sstevel@tonic-gate int release;
3297c478bd9Sstevel@tonic-gate struct aio_trans *next;
3307c478bd9Sstevel@tonic-gate } aio_trans;
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate typedef struct aio_results {
3337c478bd9Sstevel@tonic-gate int max;
3347c478bd9Sstevel@tonic-gate int outstanding;
3357c478bd9Sstevel@tonic-gate int maxpend;
3367c478bd9Sstevel@tonic-gate aio_trans *trans;
3377c478bd9Sstevel@tonic-gate } aio_results;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate int aio_inited = 0;
3407c478bd9Sstevel@tonic-gate aio_results results;
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate * Allow up to MAXBUF aio requests that each have a unique buffer.
3447c478bd9Sstevel@tonic-gate * More aio's might be done, but not using memory through the getbuf()
3457c478bd9Sstevel@tonic-gate * interface. This can be raised, but you run into the potential of
3467c478bd9Sstevel@tonic-gate * using more memory than is physically available on the machine,
3477c478bd9Sstevel@tonic-gate * and if you start swapping, you can forget about performance.
3487c478bd9Sstevel@tonic-gate * To prevent this, we also limit the total memory used for a given
3497c478bd9Sstevel@tonic-gate * type of buffer to MAXBUFMEM.
3507c478bd9Sstevel@tonic-gate *
3517c478bd9Sstevel@tonic-gate * Tests indicate a cylinder group's worth of inodes takes:
3527c478bd9Sstevel@tonic-gate *
3537c478bd9Sstevel@tonic-gate * NBPI Size of Inode Buffer
3547c478bd9Sstevel@tonic-gate * 2k 1688k
3557c478bd9Sstevel@tonic-gate * 8k 424k
3567c478bd9Sstevel@tonic-gate *
3577c478bd9Sstevel@tonic-gate * initcg() stores all the inodes for a cylinder group in one buffer,
3587c478bd9Sstevel@tonic-gate * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate #define MAXBUF 20
3617c478bd9Sstevel@tonic-gate #define MAXBUFMEM (8 * 1024 * 1024)
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate * header information for buffers managed by getbuf() and freebuf()
3657c478bd9Sstevel@tonic-gate */
3667c478bd9Sstevel@tonic-gate typedef struct bufhdr {
3677c478bd9Sstevel@tonic-gate struct bufhdr *head;
3687c478bd9Sstevel@tonic-gate struct bufhdr *next;
3697c478bd9Sstevel@tonic-gate } bufhdr;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate int bufhdrsize;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate bufhdr inodebuf = { NULL, NULL };
3747c478bd9Sstevel@tonic-gate bufhdr cgsumbuf = { NULL, NULL };
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate #define SECTORS_PER_TERABYTE (1LL << 31)
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * The following constant specifies an upper limit for file system size
3797c478bd9Sstevel@tonic-gate * that is actually a lot bigger than we expect to support with UFS. (Since
3807c478bd9Sstevel@tonic-gate * it's specified in sectors, the file system size would be 2**44 * 512,
3817c478bd9Sstevel@tonic-gate * which is 2**53, which is 8192 Terabytes.) However, it's useful
3827c478bd9Sstevel@tonic-gate * for checking the basic sanity of a size value that is input on the
3837c478bd9Sstevel@tonic-gate * command line.
3847c478bd9Sstevel@tonic-gate */
3857c478bd9Sstevel@tonic-gate #define FS_SIZE_UPPER_LIMIT 0x100000000000LL
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate /*
3887c478bd9Sstevel@tonic-gate * Forward declarations
3897c478bd9Sstevel@tonic-gate */
3907c478bd9Sstevel@tonic-gate static char *getbuf(bufhdr *bufhead, int size);
3917c478bd9Sstevel@tonic-gate static void freebuf(char *buf);
3927c478bd9Sstevel@tonic-gate static void freetrans(aio_trans *transp);
3937c478bd9Sstevel@tonic-gate static aio_trans *get_aiop();
3947c478bd9Sstevel@tonic-gate static aio_trans *wait_for_write(int block);
3957c478bd9Sstevel@tonic-gate static void initcg(int cylno);
3967c478bd9Sstevel@tonic-gate static void fsinit();
3977c478bd9Sstevel@tonic-gate static int makedir(struct direct *protodir, int entries);
3987c478bd9Sstevel@tonic-gate static void iput(struct inode *ip);
3997c478bd9Sstevel@tonic-gate static void rdfs(diskaddr_t bno, int size, char *bf);
4007c478bd9Sstevel@tonic-gate static void wtfs(diskaddr_t bno, int size, char *bf);
4017c478bd9Sstevel@tonic-gate static void awtfs(diskaddr_t bno, int size, char *bf, int release);
4027c478bd9Sstevel@tonic-gate static void wtfs_breakup(diskaddr_t bno, int size, char *bf);
4037c478bd9Sstevel@tonic-gate static int isblock(struct fs *fs, unsigned char *cp, int h);
4047c478bd9Sstevel@tonic-gate static void clrblock(struct fs *fs, unsigned char *cp, int h);
4057c478bd9Sstevel@tonic-gate static void setblock(struct fs *fs, unsigned char *cp, int h);
4067c478bd9Sstevel@tonic-gate static void usage();
4077c478bd9Sstevel@tonic-gate static void dump_fscmd(char *fsys, int fsi);
4087c478bd9Sstevel@tonic-gate static uint64_t number(uint64_t d_value, char *param, int flags);
4097c478bd9Sstevel@tonic-gate static int match(char *s);
4107c478bd9Sstevel@tonic-gate static char checkopt(char *optim);
4117c478bd9Sstevel@tonic-gate static char checkmtb(char *mtbarg);
4127c478bd9Sstevel@tonic-gate static void range_check(long *varp, char *name, long minimum,
4137c478bd9Sstevel@tonic-gate long maximum, long def_val, int user_supplied);
4147c478bd9Sstevel@tonic-gate static void range_check_64(uint64_t *varp, char *name, uint64_t minimum,
4157c478bd9Sstevel@tonic-gate uint64_t maximum, uint64_t def_val, int user_supplied);
4167c478bd9Sstevel@tonic-gate static daddr32_t alloc(int size, int mode);
4177c478bd9Sstevel@tonic-gate static diskaddr_t get_max_size(int fd);
4187c478bd9Sstevel@tonic-gate static long get_max_track_size(int fd);
4197c478bd9Sstevel@tonic-gate static void block_sigint(sigset_t *old_mask);
4207c478bd9Sstevel@tonic-gate static void unblock_sigint(sigset_t *old_mask);
4217c478bd9Sstevel@tonic-gate static void recover_from_sigint(int signum);
4227c478bd9Sstevel@tonic-gate static int confirm_abort(void);
42323a1cceaSRoger A. Faulkner static int getaline(FILE *fp, char *loc, int maxlen);
4247c478bd9Sstevel@tonic-gate static void flush_writes(void);
4257c478bd9Sstevel@tonic-gate static long compute_maxcpg(long, long, long, long, long);
4267c478bd9Sstevel@tonic-gate static int in_64bit_mode(void);
4277c478bd9Sstevel@tonic-gate static int validate_size(int fd, diskaddr_t size);
428355d6bb5Sswilcox static void dump_sblock(void);
4297c478bd9Sstevel@tonic-gate
430140e9cb2Sprabahar /*
431140e9cb2Sprabahar * Workaround for mkfs to function properly on disks attached to XMIT 2.X
432140e9cb2Sprabahar * controller. If the address is not aligned at 8 byte boundary, mkfs on
433140e9cb2Sprabahar * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
434140e9cb2Sprabahar */
435140e9cb2Sprabahar #define XMIT_2_X_ALIGN 8
436140e9cb2Sprabahar #pragma align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
437140e9cb2Sprabahar
4387c478bd9Sstevel@tonic-gate union {
4397c478bd9Sstevel@tonic-gate struct fs fs;
4407c478bd9Sstevel@tonic-gate char pad[SBSIZE];
4416451fdbcSvsakar } fsun, altfsun;
4427c478bd9Sstevel@tonic-gate #define sblock fsun.fs
4436451fdbcSvsakar #define altsblock altfsun.fs
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate struct csum *fscs;
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate union cgun {
4487c478bd9Sstevel@tonic-gate struct cg cg;
4497c478bd9Sstevel@tonic-gate char pad[MAXBSIZE];
4507c478bd9Sstevel@tonic-gate } cgun;
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate #define acg cgun.cg
4537c478bd9Sstevel@tonic-gate /*
4547c478bd9Sstevel@tonic-gate * Size of screen in cols in which to fit output
4557c478bd9Sstevel@tonic-gate */
4567c478bd9Sstevel@tonic-gate #define WIDTH 80
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate struct dinode zino[MAXBSIZE / sizeof (struct dinode)];
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate * file descriptors used for rdfs(fsi) and wtfs(fso).
4627c478bd9Sstevel@tonic-gate * Initialized to an illegal file descriptor number.
4637c478bd9Sstevel@tonic-gate */
4647c478bd9Sstevel@tonic-gate int fsi = -1;
4657c478bd9Sstevel@tonic-gate int fso = -1;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate * The BIG parameter is machine dependent. It should be a longlong integer
4697c478bd9Sstevel@tonic-gate * constant that can be used by the number parser to check the validity
4707c478bd9Sstevel@tonic-gate * of numeric parameters.
4717c478bd9Sstevel@tonic-gate */
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate #define BIG 0x7fffffffffffffffLL
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate /* Used to indicate to number() that a bogus value should cause us to exit */
4767c478bd9Sstevel@tonic-gate #define NO_DEFAULT LONG_MIN
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
4796451fdbcSvsakar * INVALIDSBLIMIT is the number of bad backup superblocks that will be
4806451fdbcSvsakar * tolerated before we decide to try arriving at a different set of them
4816451fdbcSvsakar * using a different logic. This is applicable for non-EFI disks only.
4826451fdbcSvsakar */
4836451fdbcSvsakar #define INVALIDSBLIMIT 10
4846451fdbcSvsakar
4856451fdbcSvsakar /*
4867c478bd9Sstevel@tonic-gate * The *_flag variables are used to indicate that the user specified
4877c478bd9Sstevel@tonic-gate * the values, rather than that we made them up ourselves. We can
4887c478bd9Sstevel@tonic-gate * complain about the user giving us bogus values.
4897c478bd9Sstevel@tonic-gate */
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate /* semi-constants */
4927c478bd9Sstevel@tonic-gate long sectorsize = DEV_BSIZE; /* bytes/sector from param.h */
4937c478bd9Sstevel@tonic-gate long bbsize = BBSIZE; /* boot block size */
4947c478bd9Sstevel@tonic-gate long sbsize = SBSIZE; /* superblock size */
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate /* parameters */
4977c478bd9Sstevel@tonic-gate diskaddr_t fssize_db; /* file system size in disk blocks */
4987c478bd9Sstevel@tonic-gate diskaddr_t fssize_frag; /* file system size in frags */
4997c478bd9Sstevel@tonic-gate long cpg; /* cylinders/cylinder group */
5007c478bd9Sstevel@tonic-gate int cpg_flag = RC_DEFAULT;
5017c478bd9Sstevel@tonic-gate long rotdelay = -1; /* rotational delay between blocks */
5027c478bd9Sstevel@tonic-gate int rotdelay_flag = RC_DEFAULT;
5037c478bd9Sstevel@tonic-gate long maxcontig; /* max contiguous blocks to allocate */
5047c478bd9Sstevel@tonic-gate int maxcontig_flag = RC_DEFAULT;
5057c478bd9Sstevel@tonic-gate long nsect = DFLNSECT; /* sectors per track */
5067c478bd9Sstevel@tonic-gate int nsect_flag = RC_DEFAULT;
5077c478bd9Sstevel@tonic-gate long ntrack = DFLNTRAK; /* tracks per cylinder group */
5087c478bd9Sstevel@tonic-gate int ntrack_flag = RC_DEFAULT;
5097c478bd9Sstevel@tonic-gate long bsize = DESBLKSIZE; /* filesystem block size */
5107c478bd9Sstevel@tonic-gate int bsize_flag = RC_DEFAULT;
5117c478bd9Sstevel@tonic-gate long fragsize = DESFRAGSIZE; /* filesystem fragment size */
5127c478bd9Sstevel@tonic-gate int fragsize_flag = RC_DEFAULT;
5137c478bd9Sstevel@tonic-gate long minfree = MINFREE; /* fs_minfree */
5147c478bd9Sstevel@tonic-gate int minfree_flag = RC_DEFAULT;
5157c478bd9Sstevel@tonic-gate long rps = DEFHZ; /* revolutions/second of drive */
5167c478bd9Sstevel@tonic-gate int rps_flag = RC_DEFAULT;
5177c478bd9Sstevel@tonic-gate long nbpi = NBPI; /* number of bytes per inode */
5187c478bd9Sstevel@tonic-gate int nbpi_flag = RC_DEFAULT;
5197c478bd9Sstevel@tonic-gate long nrpos = NRPOS; /* number of rotational positions */
5207c478bd9Sstevel@tonic-gate int nrpos_flag = RC_DEFAULT;
5217c478bd9Sstevel@tonic-gate long apc = 0; /* alternate sectors per cylinder */
5227c478bd9Sstevel@tonic-gate int apc_flag = RC_DEFAULT;
5237c478bd9Sstevel@tonic-gate char opt = 't'; /* optimization style, `t' or `s' */
5247c478bd9Sstevel@tonic-gate char mtb = 'n'; /* multi-terabyte format, 'y' or 'n' */
525d50c8f90Svsakar #define DEFAULT_SECT_TRAK_CPG (nsect_flag == RC_DEFAULT && \
526d50c8f90Svsakar ntrack_flag == RC_DEFAULT && \
527d50c8f90Svsakar cpg_flag == RC_DEFAULT)
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate long debug = 0; /* enable debugging output */
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate int spc_flag = 0; /* alternate sectors specified or */
5327c478bd9Sstevel@tonic-gate /* found */
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate /* global state */
5357c478bd9Sstevel@tonic-gate int Nflag; /* do not write to disk */
5367c478bd9Sstevel@tonic-gate int mflag; /* return the command line used to create this FS */
537355d6bb5Sswilcox int rflag; /* report the superblock in an easily-parsed form */
538355d6bb5Sswilcox int Rflag; /* dump the superblock in binary */
5397c478bd9Sstevel@tonic-gate char *fsys;
5407c478bd9Sstevel@tonic-gate time_t mkfstime;
5417c478bd9Sstevel@tonic-gate char *string;
5426451fdbcSvsakar int label_type;
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate * logging support
5467c478bd9Sstevel@tonic-gate */
5477c478bd9Sstevel@tonic-gate int ismdd; /* true if device is a SVM device */
5487c478bd9Sstevel@tonic-gate int islog; /* true if ufs or SVM logging is enabled */
5497c478bd9Sstevel@tonic-gate int islogok; /* true if ufs/SVM log state is good */
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate static int isufslog; /* true if ufs logging is enabled */
5527c478bd9Sstevel@tonic-gate static int waslog; /* true when ufs logging disabled during grow */
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate /*
5557c478bd9Sstevel@tonic-gate * growfs defines, globals, and forward references
5567c478bd9Sstevel@tonic-gate */
5577c478bd9Sstevel@tonic-gate #define NOTENOUGHSPACE 33
5587c478bd9Sstevel@tonic-gate int grow;
559d50c8f90Svsakar #define GROW_WITH_DEFAULT_TRAK (grow && ntrack_flag == RC_DEFAULT)
560d50c8f90Svsakar
5617c478bd9Sstevel@tonic-gate static int Pflag; /* probe to which size the fs can be grown */
5627c478bd9Sstevel@tonic-gate int ismounted;
5637c478bd9Sstevel@tonic-gate char *directory;
5647c478bd9Sstevel@tonic-gate diskaddr_t grow_fssize;
5657c478bd9Sstevel@tonic-gate long grow_fs_size;
5667c478bd9Sstevel@tonic-gate long grow_fs_ncg;
5677c478bd9Sstevel@tonic-gate diskaddr_t grow_fs_csaddr;
5687c478bd9Sstevel@tonic-gate long grow_fs_cssize;
5697c478bd9Sstevel@tonic-gate int grow_fs_clean;
5707c478bd9Sstevel@tonic-gate struct csum *grow_fscs;
5717c478bd9Sstevel@tonic-gate diskaddr_t grow_sifrag;
5727c478bd9Sstevel@tonic-gate int test;
5737c478bd9Sstevel@tonic-gate int testforce;
5747c478bd9Sstevel@tonic-gate diskaddr_t testfrags;
5757c478bd9Sstevel@tonic-gate int inlockexit;
5767c478bd9Sstevel@tonic-gate int isbad;
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate void lockexit(int);
5797c478bd9Sstevel@tonic-gate void randomgeneration(void);
5807c478bd9Sstevel@tonic-gate void checksummarysize(void);
5816451fdbcSvsakar int checksblock(struct fs, int);
5827c478bd9Sstevel@tonic-gate void growinit(char *);
5837c478bd9Sstevel@tonic-gate void checkdev(char *, char *);
5847c478bd9Sstevel@tonic-gate void checkmount(struct mnttab *, char *);
5857c478bd9Sstevel@tonic-gate struct dinode *gdinode(ino_t);
5867c478bd9Sstevel@tonic-gate int csfraginrange(daddr32_t);
5877c478bd9Sstevel@tonic-gate struct csfrag *findcsfrag(daddr32_t, struct csfrag **);
5887c478bd9Sstevel@tonic-gate void checkindirect(ino_t, daddr32_t *, daddr32_t, int);
5897c478bd9Sstevel@tonic-gate void addcsfrag(ino_t, daddr32_t, struct csfrag **);
5907c478bd9Sstevel@tonic-gate void delcsfrag(daddr32_t, struct csfrag **);
5917c478bd9Sstevel@tonic-gate void checkdirect(ino_t, daddr32_t *, daddr32_t *, int);
5927c478bd9Sstevel@tonic-gate void findcsfragino(void);
5937c478bd9Sstevel@tonic-gate void fixindirect(daddr32_t, int);
5947c478bd9Sstevel@tonic-gate void fixdirect(caddr_t, daddr32_t, daddr32_t *, int);
5957c478bd9Sstevel@tonic-gate void fixcsfragino(void);
5967c478bd9Sstevel@tonic-gate void extendsummaryinfo(void);
5977c478bd9Sstevel@tonic-gate int notenoughspace(void);
5987c478bd9Sstevel@tonic-gate void unalloccsfragino(void);
5997c478bd9Sstevel@tonic-gate void unalloccsfragfree(void);
6007c478bd9Sstevel@tonic-gate void findcsfragfree(void);
6017c478bd9Sstevel@tonic-gate void copycsfragino(void);
6027c478bd9Sstevel@tonic-gate void rdcg(long);
6037c478bd9Sstevel@tonic-gate void wtcg(void);
6047c478bd9Sstevel@tonic-gate void flcg(void);
6057c478bd9Sstevel@tonic-gate void allocfrags(long, daddr32_t *, long *);
6067c478bd9Sstevel@tonic-gate void alloccsfragino(void);
6077c478bd9Sstevel@tonic-gate void alloccsfragfree(void);
6087c478bd9Sstevel@tonic-gate void freefrags(daddr32_t, long, long);
6097c478bd9Sstevel@tonic-gate int findfreerange(long *, long *);
6107c478bd9Sstevel@tonic-gate void resetallocinfo(void);
6117c478bd9Sstevel@tonic-gate void extendcg(long);
6127c478bd9Sstevel@tonic-gate void ulockfs(void);
6137c478bd9Sstevel@tonic-gate void wlockfs(void);
6147c478bd9Sstevel@tonic-gate void clockfs(void);
6157c478bd9Sstevel@tonic-gate void wtsb(void);
6167c478bd9Sstevel@tonic-gate static int64_t checkfragallocated(daddr32_t);
6177c478bd9Sstevel@tonic-gate static struct csum *read_summaryinfo(struct fs *);
6187c478bd9Sstevel@tonic-gate static diskaddr_t probe_summaryinfo();
6197c478bd9Sstevel@tonic-gate
620d1a180b0Smaheshvs int
main(int argc,char * argv[])6217c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
6227c478bd9Sstevel@tonic-gate {
6237c478bd9Sstevel@tonic-gate long i, mincpc, mincpg, ibpcl;
6247c478bd9Sstevel@tonic-gate long cylno, rpos, blk, j, warn = 0;
6257c478bd9Sstevel@tonic-gate long mincpgcnt, maxcpg;
6267c478bd9Sstevel@tonic-gate uint64_t used, bpcg, inospercg;
6277c478bd9Sstevel@tonic-gate long mapcramped, inodecramped;
6287c478bd9Sstevel@tonic-gate long postblsize, rotblsize, totalsbsize;
6297c478bd9Sstevel@tonic-gate FILE *mnttab;
6307c478bd9Sstevel@tonic-gate struct mnttab mntp;
6317c478bd9Sstevel@tonic-gate char *special;
6327c478bd9Sstevel@tonic-gate struct statvfs64 fs;
6336451fdbcSvsakar struct dk_geom dkg;
6347c478bd9Sstevel@tonic-gate struct dk_cinfo dkcinfo;
63565908c77Syu, larry liu - Sun Microsystems - Beijing China struct dk_minfo dkminfo;
6367c478bd9Sstevel@tonic-gate char pbuf[sizeof (uint64_t) * 3 + 1];
6376451fdbcSvsakar char *tmpbuf;
6387c478bd9Sstevel@tonic-gate int width, plen;
6397c478bd9Sstevel@tonic-gate uint64_t num;
6407c478bd9Sstevel@tonic-gate int c, saverr;
6417c478bd9Sstevel@tonic-gate diskaddr_t max_fssize;
6427c478bd9Sstevel@tonic-gate long tmpmaxcontig = -1;
6437c478bd9Sstevel@tonic-gate struct sigaction sigact;
6447c478bd9Sstevel@tonic-gate uint64_t nbytes64;
6457c478bd9Sstevel@tonic-gate int remaining_cg;
6467c478bd9Sstevel@tonic-gate int do_dot = 0;
6478b7c2cdfSws195443 int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0;
6486d24e334Svsakar int invalid_sb_cnt, ret, skip_this_sb, cg_too_small;
6496d24e334Svsakar int geom_nsect, geom_ntrack, geom_cpg;
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
6547c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
6557c478bd9Sstevel@tonic-gate #endif
6567c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) {
6597c478bd9Sstevel@tonic-gate switch (c) {
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate case 'F':
6627c478bd9Sstevel@tonic-gate string = optarg;
6637c478bd9Sstevel@tonic-gate if (strcmp(string, "ufs") != 0)
6647c478bd9Sstevel@tonic-gate usage();
6657c478bd9Sstevel@tonic-gate break;
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate case 'm': /* return command line used to create this FS */
6687c478bd9Sstevel@tonic-gate mflag++;
6697c478bd9Sstevel@tonic-gate break;
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate case 'o':
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate * ufs specific options.
6747c478bd9Sstevel@tonic-gate */
6757c478bd9Sstevel@tonic-gate string = optarg;
6767c478bd9Sstevel@tonic-gate while (*string != '\0') {
6777c478bd9Sstevel@tonic-gate if (match("nsect=")) {
6787c478bd9Sstevel@tonic-gate nsect = number(DFLNSECT, "nsect", 0);
6797c478bd9Sstevel@tonic-gate nsect_flag = RC_KEYWORD;
6807c478bd9Sstevel@tonic-gate } else if (match("ntrack=")) {
6817c478bd9Sstevel@tonic-gate ntrack = number(DFLNTRAK, "ntrack", 0);
6827c478bd9Sstevel@tonic-gate ntrack_flag = RC_KEYWORD;
6837c478bd9Sstevel@tonic-gate } else if (match("bsize=")) {
6847c478bd9Sstevel@tonic-gate bsize = number(DESBLKSIZE, "bsize", 0);
6857c478bd9Sstevel@tonic-gate bsize_flag = RC_KEYWORD;
6867c478bd9Sstevel@tonic-gate } else if (match("fragsize=")) {
6877c478bd9Sstevel@tonic-gate fragsize = number(DESFRAGSIZE,
6887c478bd9Sstevel@tonic-gate "fragsize", 0);
6897c478bd9Sstevel@tonic-gate fragsize_flag = RC_KEYWORD;
6907c478bd9Sstevel@tonic-gate } else if (match("cgsize=")) {
6917c478bd9Sstevel@tonic-gate cpg = number(DESCPG, "cgsize", 0);
6927c478bd9Sstevel@tonic-gate cpg_flag = RC_KEYWORD;
6937c478bd9Sstevel@tonic-gate } else if (match("free=")) {
6947c478bd9Sstevel@tonic-gate minfree = number(MINFREE, "free",
6957c478bd9Sstevel@tonic-gate ALLOW_PERCENT);
6967c478bd9Sstevel@tonic-gate minfree_flag = RC_KEYWORD;
6977c478bd9Sstevel@tonic-gate } else if (match("maxcontig=")) {
6987c478bd9Sstevel@tonic-gate tmpmaxcontig =
6997c478bd9Sstevel@tonic-gate number(-1, "maxcontig", 0);
7007c478bd9Sstevel@tonic-gate maxcontig_flag = RC_KEYWORD;
7017c478bd9Sstevel@tonic-gate } else if (match("nrpos=")) {
7027c478bd9Sstevel@tonic-gate nrpos = number(NRPOS, "nrpos", 0);
7037c478bd9Sstevel@tonic-gate nrpos_flag = RC_KEYWORD;
7047c478bd9Sstevel@tonic-gate } else if (match("rps=")) {
7057c478bd9Sstevel@tonic-gate rps = number(DEFHZ, "rps", 0);
7067c478bd9Sstevel@tonic-gate rps_flag = RC_KEYWORD;
7077c478bd9Sstevel@tonic-gate } else if (match("nbpi=")) {
7087c478bd9Sstevel@tonic-gate nbpi = number(NBPI, "nbpi", 0);
7097c478bd9Sstevel@tonic-gate nbpi_flag = RC_KEYWORD;
7107c478bd9Sstevel@tonic-gate } else if (match("opt=")) {
7117c478bd9Sstevel@tonic-gate opt = checkopt(string);
7127c478bd9Sstevel@tonic-gate } else if (match("mtb=")) {
7137c478bd9Sstevel@tonic-gate mtb = checkmtb(string);
7147c478bd9Sstevel@tonic-gate } else if (match("apc=")) {
7157c478bd9Sstevel@tonic-gate apc = number(0, "apc", 0);
7167c478bd9Sstevel@tonic-gate apc_flag = RC_KEYWORD;
7177c478bd9Sstevel@tonic-gate } else if (match("gap=")) {
7187c478bd9Sstevel@tonic-gate (void) number(0, "gap", ALLOW_MS1);
7197c478bd9Sstevel@tonic-gate rotdelay = ROTDELAY;
7207c478bd9Sstevel@tonic-gate rotdelay_flag = RC_DEFAULT;
7217c478bd9Sstevel@tonic-gate } else if (match("debug=")) {
7227c478bd9Sstevel@tonic-gate debug = number(0, "debug", 0);
7237c478bd9Sstevel@tonic-gate } else if (match("N")) {
7247c478bd9Sstevel@tonic-gate Nflag++;
725355d6bb5Sswilcox } else if (match("calcsb")) {
726355d6bb5Sswilcox rflag++;
727355d6bb5Sswilcox Nflag++;
728355d6bb5Sswilcox } else if (match("calcbinsb")) {
729355d6bb5Sswilcox rflag++;
730355d6bb5Sswilcox Rflag++;
731355d6bb5Sswilcox Nflag++;
7327c478bd9Sstevel@tonic-gate } else if (*string == '\0') {
7337c478bd9Sstevel@tonic-gate break;
7347c478bd9Sstevel@tonic-gate } else {
7357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
736d50c8f90Svsakar "illegal option: %s\n"), string);
7377c478bd9Sstevel@tonic-gate usage();
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate if (*string == ',') string++;
7417c478bd9Sstevel@tonic-gate if (*string == ' ') string++;
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate break;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate case 'V':
7467c478bd9Sstevel@tonic-gate {
7477c478bd9Sstevel@tonic-gate char *opt_text;
7487c478bd9Sstevel@tonic-gate int opt_count;
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext("mkfs -F ufs "));
7517c478bd9Sstevel@tonic-gate for (opt_count = 1; opt_count < argc;
7527c478bd9Sstevel@tonic-gate opt_count++) {
7537c478bd9Sstevel@tonic-gate opt_text = argv[opt_count];
7547c478bd9Sstevel@tonic-gate if (opt_text)
7557c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s ",
7567c478bd9Sstevel@tonic-gate opt_text);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n");
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate break;
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate case 'b': /* do nothing for this */
7637c478bd9Sstevel@tonic-gate break;
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate case 'M': /* grow the mounted file system */
7667c478bd9Sstevel@tonic-gate directory = optarg;
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
7697c478bd9Sstevel@tonic-gate case 'G': /* grow the file system */
7707c478bd9Sstevel@tonic-gate grow = 1;
7717c478bd9Sstevel@tonic-gate break;
7727c478bd9Sstevel@tonic-gate case 'P': /* probe the file system growing size */
7737c478bd9Sstevel@tonic-gate Pflag = 1;
7747c478bd9Sstevel@tonic-gate grow = 1; /* probe mode implies fs growing */
7757c478bd9Sstevel@tonic-gate break;
7767c478bd9Sstevel@tonic-gate case 'T': /* For testing */
7777c478bd9Sstevel@tonic-gate testforce = 1;
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
7807c478bd9Sstevel@tonic-gate case 't':
7817c478bd9Sstevel@tonic-gate test = 1;
7827c478bd9Sstevel@tonic-gate string = optarg;
7837c478bd9Sstevel@tonic-gate testfrags = number(NO_DEFAULT, "testfrags", 0);
7847c478bd9Sstevel@tonic-gate break;
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate case '?':
7877c478bd9Sstevel@tonic-gate usage();
7887c478bd9Sstevel@tonic-gate break;
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate #ifdef MKFS_DEBUG
7927c478bd9Sstevel@tonic-gate /*
7937c478bd9Sstevel@tonic-gate * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
7947c478bd9Sstevel@tonic-gate * that can be reproduced by setting the time to 0 and seeding
7957c478bd9Sstevel@tonic-gate * the random number generator to a constant.
7967c478bd9Sstevel@tonic-gate */
7977c478bd9Sstevel@tonic-gate mkfstime = 0; /* reproducible results */
7987c478bd9Sstevel@tonic-gate #else
7997c478bd9Sstevel@tonic-gate (void) time(&mkfstime);
8007c478bd9Sstevel@tonic-gate #endif
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate if (optind >= (argc - 1)) {
8037c478bd9Sstevel@tonic-gate if (optind > (argc - 1)) {
8047c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
8057c478bd9Sstevel@tonic-gate gettext("special not specified\n"));
8067c478bd9Sstevel@tonic-gate usage();
8077c478bd9Sstevel@tonic-gate } else if (mflag == 0) {
8087c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
8097c478bd9Sstevel@tonic-gate gettext("size not specified\n"));
8107c478bd9Sstevel@tonic-gate usage();
8117c478bd9Sstevel@tonic-gate }
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate argc -= optind;
8147c478bd9Sstevel@tonic-gate argv = &argv[optind];
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate fsys = argv[0];
8177c478bd9Sstevel@tonic-gate fsi = open64(fsys, O_RDONLY);
8187c478bd9Sstevel@tonic-gate if (fsi < 0) {
8197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: cannot open\n"), fsys);
8207c478bd9Sstevel@tonic-gate lockexit(32);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate if (mflag) {
8247c478bd9Sstevel@tonic-gate dump_fscmd(fsys, fsi);
8257c478bd9Sstevel@tonic-gate lockexit(0);
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate * The task of setting all of the configuration parameters for a
8307c478bd9Sstevel@tonic-gate * UFS file system is basically a matter of solving n equations
8317c478bd9Sstevel@tonic-gate * in m variables. Typically, m is greater than n, so there is
8327c478bd9Sstevel@tonic-gate * usually more than one valid solution. Since this is usually
8337c478bd9Sstevel@tonic-gate * an under-constrained problem, it's not always obvious what the
8347c478bd9Sstevel@tonic-gate * "best" configuration is.
8357c478bd9Sstevel@tonic-gate *
8367c478bd9Sstevel@tonic-gate * In general, the approach is to
8377c478bd9Sstevel@tonic-gate * 1. Determine the values for the file system parameters
8387c478bd9Sstevel@tonic-gate * that are externally contrained and therefore not adjustable
8397c478bd9Sstevel@tonic-gate * by mkfs (such as the device's size and maxtransfer size).
8407c478bd9Sstevel@tonic-gate * 2. Acquire the user's requested setting for all configuration
8417c478bd9Sstevel@tonic-gate * values that can be set on the command line.
8427c478bd9Sstevel@tonic-gate * 3. Determine the final value of all configuration values, by
8437c478bd9Sstevel@tonic-gate * the following approach:
8447c478bd9Sstevel@tonic-gate * - set the file system block size (fs_bsize). Although
8457c478bd9Sstevel@tonic-gate * this could be regarded as an adjustable parameter, in
8467c478bd9Sstevel@tonic-gate * fact, it's pretty much a constant. At this time, it's
8477c478bd9Sstevel@tonic-gate * generally set to 8k (with older hardware, it can
8487c478bd9Sstevel@tonic-gate * sometimes make sense to set it to 4k, but those
8497c478bd9Sstevel@tonic-gate * situations are pretty rare now).
8507c478bd9Sstevel@tonic-gate * - re-adjust the maximum file system size based on the
8517c478bd9Sstevel@tonic-gate * value of the file system block size. Since the
8527c478bd9Sstevel@tonic-gate * frag size can't be any larger than a file system
8537c478bd9Sstevel@tonic-gate * block, and the number of frags in the file system
8547c478bd9Sstevel@tonic-gate * has to fit into 31 bits, the file system block size
8557c478bd9Sstevel@tonic-gate * affects the maximum file system size.
8567c478bd9Sstevel@tonic-gate * - now that the real maximum file system is known, set the
8577c478bd9Sstevel@tonic-gate * actual size of the file system to be created to
8587c478bd9Sstevel@tonic-gate * MIN(requested size, maximum file system size).
8597c478bd9Sstevel@tonic-gate * - now validate, and if necessary, adjust the following
8607c478bd9Sstevel@tonic-gate * values:
8617c478bd9Sstevel@tonic-gate * rotdelay
8627c478bd9Sstevel@tonic-gate * nsect
8637c478bd9Sstevel@tonic-gate * maxcontig
8647c478bd9Sstevel@tonic-gate * apc
8657c478bd9Sstevel@tonic-gate * frag_size
8667c478bd9Sstevel@tonic-gate * rps
8677c478bd9Sstevel@tonic-gate * minfree
8687c478bd9Sstevel@tonic-gate * nrpos
8697c478bd9Sstevel@tonic-gate * nrack
8707c478bd9Sstevel@tonic-gate * nbpi
8717c478bd9Sstevel@tonic-gate * - calculate maxcpg (the maximum value of the cylinders-per-
8727c478bd9Sstevel@tonic-gate * cylinder-group configuration parameters). There are two
8737c478bd9Sstevel@tonic-gate * algorithms for calculating maxcpg: an old one, which is
8747c478bd9Sstevel@tonic-gate * used for file systems of less than 1 terabyte, and a
8757c478bd9Sstevel@tonic-gate * new one, implemented in the function compute_maxcpg(),
8767c478bd9Sstevel@tonic-gate * which is used for file systems of greater than 1 TB.
8777c478bd9Sstevel@tonic-gate * The difference between them is that compute_maxcpg()
8787c478bd9Sstevel@tonic-gate * really tries to maximize the cpg value. The old
8797c478bd9Sstevel@tonic-gate * algorithm fails to take advantage of smaller frags and
8807c478bd9Sstevel@tonic-gate * lower inode density when determining the maximum cpg,
8817c478bd9Sstevel@tonic-gate * and thus comes up with much lower numbers in some
8827c478bd9Sstevel@tonic-gate * configurations. At some point, we might use the
8837c478bd9Sstevel@tonic-gate * new algorithm for determining maxcpg for all file
8847c478bd9Sstevel@tonic-gate * systems, but at this time, the changes implemented for
8857c478bd9Sstevel@tonic-gate * multi-terabyte UFS are NOT being automatically applied
8867c478bd9Sstevel@tonic-gate * to UFS file systems of less than a terabyte (in the
8877c478bd9Sstevel@tonic-gate * interest of not changing existing UFS policy too much
8887c478bd9Sstevel@tonic-gate * until the ramifications of the changes are well-understood
8897c478bd9Sstevel@tonic-gate * and have been evaluated for their effects on performance.)
8907c478bd9Sstevel@tonic-gate * - check the current values of the configuration parameters
8917c478bd9Sstevel@tonic-gate * against the various constraints imposed by UFS. These
8927c478bd9Sstevel@tonic-gate * include:
8937c478bd9Sstevel@tonic-gate * * There must be at least one inode in each
8947c478bd9Sstevel@tonic-gate * cylinder group.
8957c478bd9Sstevel@tonic-gate * * The cylinder group overhead block, which
8967c478bd9Sstevel@tonic-gate * contains the inode and frag bigmaps, must fit
8977c478bd9Sstevel@tonic-gate * within one file system block.
8987c478bd9Sstevel@tonic-gate * * The space required for inode maps should
8997c478bd9Sstevel@tonic-gate * occupy no more than a third of the cylinder
9007c478bd9Sstevel@tonic-gate * group overhead block.
9017c478bd9Sstevel@tonic-gate * * The rotational position tables have to fit
9027c478bd9Sstevel@tonic-gate * within the available space in the super block.
9037c478bd9Sstevel@tonic-gate * Adjust the configuration values that can be adjusted
9047c478bd9Sstevel@tonic-gate * so that these constraints are satisfied. The
9057c478bd9Sstevel@tonic-gate * configuration values that are adjustable are:
9067c478bd9Sstevel@tonic-gate * * frag size
9077c478bd9Sstevel@tonic-gate * * cylinders per group
9087c478bd9Sstevel@tonic-gate * * inode density (can be increased)
9097c478bd9Sstevel@tonic-gate * * number of rotational positions (the rotational
9107c478bd9Sstevel@tonic-gate * position tables are eliminated altogether if
9117c478bd9Sstevel@tonic-gate * there isn't enough room for them.)
9127c478bd9Sstevel@tonic-gate * 4. Set the values for all the dependent configuration
9137c478bd9Sstevel@tonic-gate * values (those that aren't settable on the command
9147c478bd9Sstevel@tonic-gate * line and which are completely dependent on the
9157c478bd9Sstevel@tonic-gate * adjustable parameters). This include cpc (cycles
9167c478bd9Sstevel@tonic-gate * per cylinder, spc (sectors-per-cylinder), and many others.
9177c478bd9Sstevel@tonic-gate */
9187c478bd9Sstevel@tonic-gate
919d50c8f90Svsakar /*
920d50c8f90Svsakar * Figure out the partition size and initialize the label_type.
921d50c8f90Svsakar */
9227c478bd9Sstevel@tonic-gate max_fssize = get_max_size(fsi);
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate /*
9257c478bd9Sstevel@tonic-gate * Get and check positional arguments, if any.
9267c478bd9Sstevel@tonic-gate */
9277c478bd9Sstevel@tonic-gate switch (argc - 1) {
9287c478bd9Sstevel@tonic-gate default:
9297c478bd9Sstevel@tonic-gate usage();
9307c478bd9Sstevel@tonic-gate /*NOTREACHED*/
9317c478bd9Sstevel@tonic-gate case 15:
9327c478bd9Sstevel@tonic-gate mtb = checkmtb(argv[15]);
9337c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9347c478bd9Sstevel@tonic-gate case 14:
9357c478bd9Sstevel@tonic-gate string = argv[14];
9367c478bd9Sstevel@tonic-gate tmpmaxcontig = number(-1, "maxcontig", 0);
9377c478bd9Sstevel@tonic-gate maxcontig_flag = RC_POSITIONAL;
9387c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9397c478bd9Sstevel@tonic-gate case 13:
9407c478bd9Sstevel@tonic-gate string = argv[13];
9417c478bd9Sstevel@tonic-gate nrpos = number(NRPOS, "nrpos", 0);
9427c478bd9Sstevel@tonic-gate nrpos_flag = RC_POSITIONAL;
9437c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9447c478bd9Sstevel@tonic-gate case 12:
9457c478bd9Sstevel@tonic-gate string = argv[12];
9467c478bd9Sstevel@tonic-gate rotdelay = ROTDELAY;
9477c478bd9Sstevel@tonic-gate rotdelay_flag = RC_DEFAULT;
9487c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9497c478bd9Sstevel@tonic-gate case 11:
9507c478bd9Sstevel@tonic-gate string = argv[11];
9517c478bd9Sstevel@tonic-gate apc = number(0, "apc", 0);
9527c478bd9Sstevel@tonic-gate apc_flag = RC_POSITIONAL;
9537c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9547c478bd9Sstevel@tonic-gate case 10:
9557c478bd9Sstevel@tonic-gate opt = checkopt(argv[10]);
9567c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9577c478bd9Sstevel@tonic-gate case 9:
9587c478bd9Sstevel@tonic-gate string = argv[9];
9597c478bd9Sstevel@tonic-gate nbpi = number(NBPI, "nbpi", 0);
9607c478bd9Sstevel@tonic-gate nbpi_flag = RC_POSITIONAL;
9617c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9627c478bd9Sstevel@tonic-gate case 8:
9637c478bd9Sstevel@tonic-gate string = argv[8];
9647c478bd9Sstevel@tonic-gate rps = number(DEFHZ, "rps", 0);
9657c478bd9Sstevel@tonic-gate rps_flag = RC_POSITIONAL;
9667c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9677c478bd9Sstevel@tonic-gate case 7:
9687c478bd9Sstevel@tonic-gate string = argv[7];
9697c478bd9Sstevel@tonic-gate minfree = number(MINFREE, "free", ALLOW_PERCENT);
9707c478bd9Sstevel@tonic-gate minfree_flag = RC_POSITIONAL;
9717c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9727c478bd9Sstevel@tonic-gate case 6:
9737c478bd9Sstevel@tonic-gate string = argv[6];
9747c478bd9Sstevel@tonic-gate cpg = number(DESCPG, "cgsize", 0);
9757c478bd9Sstevel@tonic-gate cpg_flag = RC_POSITIONAL;
9767c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9777c478bd9Sstevel@tonic-gate case 5:
9787c478bd9Sstevel@tonic-gate string = argv[5];
9797c478bd9Sstevel@tonic-gate fragsize = number(DESFRAGSIZE, "fragsize", 0);
9807c478bd9Sstevel@tonic-gate fragsize_flag = RC_POSITIONAL;
9817c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9827c478bd9Sstevel@tonic-gate case 4:
9837c478bd9Sstevel@tonic-gate string = argv[4];
9847c478bd9Sstevel@tonic-gate bsize = number(DESBLKSIZE, "bsize", 0);
9857c478bd9Sstevel@tonic-gate bsize_flag = RC_POSITIONAL;
9867c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9877c478bd9Sstevel@tonic-gate case 3:
9887c478bd9Sstevel@tonic-gate string = argv[3];
9897c478bd9Sstevel@tonic-gate ntrack = number(DFLNTRAK, "ntrack", 0);
9907c478bd9Sstevel@tonic-gate ntrack_flag = RC_POSITIONAL;
9917c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9927c478bd9Sstevel@tonic-gate case 2:
9937c478bd9Sstevel@tonic-gate string = argv[2];
9947c478bd9Sstevel@tonic-gate nsect = number(DFLNSECT, "nsect", 0);
9957c478bd9Sstevel@tonic-gate nsect_flag = RC_POSITIONAL;
9967c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
9977c478bd9Sstevel@tonic-gate case 1:
9987c478bd9Sstevel@tonic-gate string = argv[1];
9997c478bd9Sstevel@tonic-gate fssize_db = number(max_fssize, "size", 0);
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate
1002d50c8f90Svsakar /*
1003d50c8f90Svsakar * Initialize the parameters in the same way as newfs so that
1004d50c8f90Svsakar * newfs and mkfs would result in the same file system layout
1005d50c8f90Svsakar * for EFI labelled disks. Do this only in the absence of user
1006d50c8f90Svsakar * specified values for these parameters.
1007d50c8f90Svsakar */
1008d50c8f90Svsakar if (label_type == LABEL_TYPE_EFI) {
1009d50c8f90Svsakar if (apc_flag == RC_DEFAULT) apc = 0;
1010d50c8f90Svsakar if (nrpos_flag == RC_DEFAULT) nrpos = 1;
1011d50c8f90Svsakar if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI;
1012d50c8f90Svsakar if (rps_flag == RC_DEFAULT) rps = DEFHZ;
1013d50c8f90Svsakar if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI;
1014d50c8f90Svsakar }
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) ||
10177c478bd9Sstevel@tonic-gate (maxcontig == -1)) {
10187c478bd9Sstevel@tonic-gate long maxtrax = get_max_track_size(fsi);
10197c478bd9Sstevel@tonic-gate maxcontig = maxtrax / bsize;
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate } else {
10227c478bd9Sstevel@tonic-gate maxcontig = tmpmaxcontig;
10237c478bd9Sstevel@tonic-gate }
10246451fdbcSvsakar dprintf(("DeBuG maxcontig : %ld\n", maxcontig));
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate if (rotdelay == -1) { /* default by newfs and mkfs */
10277c478bd9Sstevel@tonic-gate rotdelay = ROTDELAY;
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */
10317c478bd9Sstevel@tonic-gate cpg = DESCPG;
10327c478bd9Sstevel@tonic-gate }
10336451fdbcSvsakar dprintf(("DeBuG cpg : %ld\n", cpg));
10347c478bd9Sstevel@tonic-gate
10357c478bd9Sstevel@tonic-gate /*
10367c478bd9Sstevel@tonic-gate * Now that we have the semi-sane args, either positional, via -o,
10377c478bd9Sstevel@tonic-gate * or by defaulting, handle inter-dependencies and range checks.
10387c478bd9Sstevel@tonic-gate */
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate * Settle the file system block size first, since it's a fixed
10427c478bd9Sstevel@tonic-gate * parameter once set and so many other parameters, including
10437c478bd9Sstevel@tonic-gate * max_fssize, depend on it.
10447c478bd9Sstevel@tonic-gate */
10457c478bd9Sstevel@tonic-gate range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE,
10467c478bd9Sstevel@tonic-gate bsize_flag);
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate if (!POWEROF2(bsize)) {
10497c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10507c478bd9Sstevel@tonic-gate gettext("block size must be a power of 2, not %ld\n"),
10517c478bd9Sstevel@tonic-gate bsize);
10527c478bd9Sstevel@tonic-gate bsize = DESBLKSIZE;
10537c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10547c478bd9Sstevel@tonic-gate gettext("mkfs: bsize reset to default %ld\n"),
10557c478bd9Sstevel@tonic-gate bsize);
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) {
10597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
10607c478bd9Sstevel@tonic-gate "Warning: the requested size of this file system\n"
10617c478bd9Sstevel@tonic-gate "(%lld sectors) is greater than the size of the\n"
10627c478bd9Sstevel@tonic-gate "device reported by the driver (%lld sectors).\n"
10637c478bd9Sstevel@tonic-gate "However, a read of the device at the requested size\n"
10647c478bd9Sstevel@tonic-gate "does succeed, so the requested size will be used.\n"),
10657c478bd9Sstevel@tonic-gate fssize_db, max_fssize);
10667c478bd9Sstevel@tonic-gate max_fssize = fssize_db;
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate /*
10697c478bd9Sstevel@tonic-gate * Since the maximum allocatable unit (the frag) must be less than
10707c478bd9Sstevel@tonic-gate * or equal to bsize, and the number of frags must be less than or
10717c478bd9Sstevel@tonic-gate * equal to INT_MAX, the total size of the file system (in
10727c478bd9Sstevel@tonic-gate * bytes) must be less than or equal to bsize * INT_MAX.
10737c478bd9Sstevel@tonic-gate */
10747c478bd9Sstevel@tonic-gate
10757c478bd9Sstevel@tonic-gate if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX)
10767c478bd9Sstevel@tonic-gate max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX;
1077d50c8f90Svsakar
10787c478bd9Sstevel@tonic-gate range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1);
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate if (fssize_db >= SECTORS_PER_TERABYTE) {
10817c478bd9Sstevel@tonic-gate mtb = 'y';
10827c478bd9Sstevel@tonic-gate if (!in_64bit_mode()) {
10837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
10847c478bd9Sstevel@tonic-gate "mkfs: Warning: Creating a file system greater than 1 terabyte on a\n"
10857c478bd9Sstevel@tonic-gate " system running a 32-bit kernel. This file system will not be\n"
10867c478bd9Sstevel@tonic-gate " accessible until the system is rebooted with a 64-bit kernel.\n"));
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate }
1089d50c8f90Svsakar dprintf(("DeBuG mtb : %c\n", mtb));
10907c478bd9Sstevel@tonic-gate
10916451fdbcSvsakar /*
10926451fdbcSvsakar * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M)
10936451fdbcSvsakar * commands had problems in correctly handling the "native" geometries
10946451fdbcSvsakar * for various storage devices.
10956451fdbcSvsakar *
10966451fdbcSvsakar * To handle the new age disks, mkfs_ufs(1M) will use the EFI style
10976451fdbcSvsakar * for non-EFI disks that are larger than the CHS addressing limit
10986451fdbcSvsakar * ( > 8GB approx ) and ignore the disk geometry information for
10996451fdbcSvsakar * these drives. This is what is currently done for multi-terrabyte
11006451fdbcSvsakar * filesystems on EFI disks.
11016451fdbcSvsakar *
11026451fdbcSvsakar * However if the user asked for a specific layout by supplying values
11036d24e334Svsakar * for even one of the three parameters (nsect, ntrack, cpg), honour
11046d24e334Svsakar * the user supplied parameters.
11056d24e334Svsakar *
11066d24e334Svsakar * Choosing EFI style or native geometry style can make a lot of
11076d24e334Svsakar * difference, because the size of a cylinder group is dependent on
11086d24e334Svsakar * this choice. This in turn means that the position of alternate
11096d24e334Svsakar * superblocks varies depending on the style chosen. It is not
11106d24e334Svsakar * necessary that all disks of size > CHSLIMIT have EFI style layout.
11116d24e334Svsakar * There can be disks which are > CHSLIMIT size, but have native
11126d24e334Svsakar * geometry style layout, thereby warranting the need for alternate
11136d24e334Svsakar * logic in superblock detection.
11146451fdbcSvsakar */
1115d50c8f90Svsakar if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK ||
1116d50c8f90Svsakar DEFAULT_SECT_TRAK_CPG)) {
11176451fdbcSvsakar /*
11186d24e334Svsakar * "-1" indicates that we were called from newfs and ntracks
11196d24e334Svsakar * was not specified in newfs command line. Calculate nsect
11206451fdbcSvsakar * and ntrack in the same manner as newfs.
11216451fdbcSvsakar *
11226451fdbcSvsakar * This is required because, the defaults for nsect and ntrack
11236451fdbcSvsakar * is hardcoded in mkfs, whereas to generate the alternate
11246451fdbcSvsakar * superblock locations for the -N option, there is a need for
11256451fdbcSvsakar * the geometry based values that newfs would have arrived at.
11266451fdbcSvsakar * Newfs would have arrived at these values as below.
11276451fdbcSvsakar */
1128d50c8f90Svsakar if (label_type == LABEL_TYPE_EFI ||
1129d50c8f90Svsakar label_type == LABEL_TYPE_OTHER) {
1130d50c8f90Svsakar use_efi_dflts = 1;
1131d50c8f90Svsakar retry = 1;
1132d50c8f90Svsakar } else if (ioctl(fsi, DKIOCGGEOM, &dkg)) {
11336451fdbcSvsakar dprintf(("%s: Unable to read Disk geometry", fsys));
11346451fdbcSvsakar perror(gettext("Unable to read Disk geometry"));
11356451fdbcSvsakar lockexit(32);
11366451fdbcSvsakar } else {
11376451fdbcSvsakar nsect = dkg.dkg_nsect;
11386451fdbcSvsakar ntrack = dkg.dkg_nhead;
11396451fdbcSvsakar #ifdef i386 /* Bug 1170182 */
11406451fdbcSvsakar if (ntrack > 32 && (ntrack % 16) != 0) {
11416451fdbcSvsakar ntrack -= (ntrack % 16);
11426451fdbcSvsakar }
11436451fdbcSvsakar #endif
1144d50c8f90Svsakar if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) {
11454d594c33Svsakar dprintf(("DeBuG Unable to determine if %s is"
11464d594c33Svsakar " Removable Media. Proceeding with system"
11474d594c33Svsakar " determined parameters.\n", fsys));
1148d50c8f90Svsakar isremovable = 0;
1149d50c8f90Svsakar }
11508b7c2cdfSws195443 if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) {
11518b7c2cdfSws195443 dprintf(("DeBuG Unable to determine if %s is"
11528b7c2cdfSws195443 " Hotpluggable Media. Proceeding with "
11538b7c2cdfSws195443 "system determined parameters.\n", fsys));
11548b7c2cdfSws195443 ishotpluggable = 0;
11558b7c2cdfSws195443 }
1156342440ecSPrasad Singamsetty if ((((diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead *
1157342440ecSPrasad Singamsetty dkg.dkg_nsect) > CHSLIMIT) || isremovable ||
1158342440ecSPrasad Singamsetty ishotpluggable) {
11596451fdbcSvsakar use_efi_dflts = 1;
11606451fdbcSvsakar retry = 1;
11616451fdbcSvsakar }
11626451fdbcSvsakar }
1163d50c8f90Svsakar }
1164342440ecSPrasad Singamsetty dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT,
1165342440ecSPrasad Singamsetty (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect));
11668b7c2cdfSws195443 dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d "
11678b7c2cdfSws195443 "use_efi_dflts = %d\n", label_type, isremovable, ishotpluggable,
11688b7c2cdfSws195443 use_efi_dflts));
11696451fdbcSvsakar
11706451fdbcSvsakar /*
11716451fdbcSvsakar * For the newfs -N case, even if the disksize is > CHSLIMIT, do not
11726451fdbcSvsakar * blindly follow EFI style. If the fs_version indicates a geometry
11736451fdbcSvsakar * based layout, try that one first. If it fails we can always try the
11746451fdbcSvsakar * other logic.
11756451fdbcSvsakar *
11766451fdbcSvsakar * If we were called from growfs, we will have a problem if we mix
11776451fdbcSvsakar * and match the filesystem creation and growth styles. For example,
11786d24e334Svsakar * if we create using EFI style, we have to also grow using EFI
11796451fdbcSvsakar * style. So follow the style indicated by the fs_version.
11806451fdbcSvsakar *
11816451fdbcSvsakar * Read and verify the primary superblock. If it looks sane, use the
11826451fdbcSvsakar * fs_version from the superblock. If the primary superblock does
11836451fdbcSvsakar * not look good, read and verify the first alternate superblock at
11846451fdbcSvsakar * ALTSB. Use the fs_version to decide whether to use the
11856451fdbcSvsakar * EFI style logic or the old geometry based logic to calculate
11866451fdbcSvsakar * the alternate superblock locations.
11876451fdbcSvsakar */
11886451fdbcSvsakar if ((Nflag && use_efi_dflts) || (grow)) {
11896451fdbcSvsakar if (grow && ntrack_flag != RC_DEFAULT)
11906d24e334Svsakar goto start_fs_creation;
11916451fdbcSvsakar rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize,
11926451fdbcSvsakar (char *)&altsblock);
11936451fdbcSvsakar ret = checksblock(altsblock, 1);
11946451fdbcSvsakar
11956451fdbcSvsakar if (!ret) {
11966451fdbcSvsakar if (altsblock.fs_magic == MTB_UFS_MAGIC) {
11976451fdbcSvsakar mtb = 'y';
11986d24e334Svsakar goto start_fs_creation;
11996451fdbcSvsakar }
12006451fdbcSvsakar use_efi_dflts = (altsblock.fs_version ==
12016451fdbcSvsakar UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
12026451fdbcSvsakar } else {
12036451fdbcSvsakar /*
12046451fdbcSvsakar * The primary superblock didn't help in determining
12056451fdbcSvsakar * the fs_version. Try the first alternate superblock.
12066451fdbcSvsakar */
12076451fdbcSvsakar dprintf(("DeBuG checksblock() failed - error : %d"
12086451fdbcSvsakar " for sb : %d\n", ret, SBOFF/sectorsize));
12096451fdbcSvsakar rdfs((diskaddr_t)ALTSB, (int)sbsize,
12106451fdbcSvsakar (char *)&altsblock);
12116451fdbcSvsakar ret = checksblock(altsblock, 1);
12126451fdbcSvsakar
12136451fdbcSvsakar if (!ret) {
12146451fdbcSvsakar if (altsblock.fs_magic == MTB_UFS_MAGIC) {
12156451fdbcSvsakar mtb = 'y';
12166d24e334Svsakar goto start_fs_creation;
12176451fdbcSvsakar }
12186451fdbcSvsakar use_efi_dflts = (altsblock.fs_version ==
12196451fdbcSvsakar UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
12206d24e334Svsakar }
12216d24e334Svsakar dprintf(("DeBuG checksblock() returned : %d"
12226451fdbcSvsakar " for sb : %d\n", ret, ALTSB));
12236451fdbcSvsakar }
12246451fdbcSvsakar }
12256451fdbcSvsakar
12266d24e334Svsakar geom_nsect = nsect;
12276d24e334Svsakar geom_ntrack = ntrack;
12286d24e334Svsakar geom_cpg = cpg;
12296d24e334Svsakar dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n",
12306d24e334Svsakar geom_nsect, geom_ntrack, geom_cpg));
12316d24e334Svsakar
12326d24e334Svsakar start_fs_creation:
12336451fdbcSvsakar retry_alternate_logic:
12346451fdbcSvsakar invalid_sb_cnt = 0;
12356d24e334Svsakar cg_too_small = 0;
12366451fdbcSvsakar if (use_efi_dflts) {
12376451fdbcSvsakar nsect = DEF_SECTORS_EFI;
12386451fdbcSvsakar ntrack = DEF_TRACKS_EFI;
12396451fdbcSvsakar cpg = DESCPG;
12406451fdbcSvsakar dprintf(("\nDeBuG Using EFI defaults\n"));
12416451fdbcSvsakar } else {
12426d24e334Svsakar nsect = geom_nsect;
12436d24e334Svsakar ntrack = geom_ntrack;
12446d24e334Svsakar cpg = geom_cpg;
12456d24e334Svsakar dprintf(("\nDeBuG Using Geometry\n"));
12467c478bd9Sstevel@tonic-gate /*
12477c478bd9Sstevel@tonic-gate * 32K based on max block size of 64K, and rotational layout
12487c478bd9Sstevel@tonic-gate * test of nsect <= (256 * sectors/block). Current block size
12497c478bd9Sstevel@tonic-gate * limit is not 64K, but it's growing soon.
12507c478bd9Sstevel@tonic-gate */
12517c478bd9Sstevel@tonic-gate range_check(&nsect, "nsect", 1, 32768, DFLNSECT, nsect_flag);
12526451fdbcSvsakar /*
12536451fdbcSvsakar * ntrack is the number of tracks per cylinder.
12546451fdbcSvsakar * The ntrack value must be between 1 and the total number of
12556451fdbcSvsakar * sectors in the file system.
12566451fdbcSvsakar */
12576451fdbcSvsakar range_check(&ntrack, "ntrack", 1,
12586451fdbcSvsakar fssize_db > INT_MAX ? INT_MAX : (uint32_t)fssize_db,
12596451fdbcSvsakar DFLNTRAK, ntrack_flag);
12606451fdbcSvsakar }
12616451fdbcSvsakar
12627c478bd9Sstevel@tonic-gate range_check(&apc, "apc", 0, nsect - 1, 0, apc_flag);
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate if (mtb == 'y')
12657c478bd9Sstevel@tonic-gate fragsize = bsize;
12667c478bd9Sstevel@tonic-gate
12677c478bd9Sstevel@tonic-gate range_check(&fragsize, "fragsize", sectorsize, bsize,
12687c478bd9Sstevel@tonic-gate MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)), fragsize_flag);
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate if ((bsize / MAXFRAG) > fragsize) {
12717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
12727c478bd9Sstevel@tonic-gate "fragment size %ld is too small, minimum with block size %ld is %ld\n"),
12737c478bd9Sstevel@tonic-gate fragsize, bsize, bsize / MAXFRAG);
12747c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
12757c478bd9Sstevel@tonic-gate gettext("mkfs: fragsize reset to minimum %ld\n"),
12767c478bd9Sstevel@tonic-gate bsize / MAXFRAG);
12777c478bd9Sstevel@tonic-gate fragsize = bsize / MAXFRAG;
12787c478bd9Sstevel@tonic-gate }
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate if (!POWEROF2(fragsize)) {
12817c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
12827c478bd9Sstevel@tonic-gate gettext("fragment size must be a power of 2, not %ld\n"),
12837c478bd9Sstevel@tonic-gate fragsize);
12847c478bd9Sstevel@tonic-gate fragsize = MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize));
12857c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
12867c478bd9Sstevel@tonic-gate gettext("mkfs: fragsize reset to %ld\n"),
12877c478bd9Sstevel@tonic-gate fragsize);
12887c478bd9Sstevel@tonic-gate }
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate /* At this point, bsize must be >= fragsize, so no need to check it */
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate if (bsize < PAGESIZE) {
12937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
12947c478bd9Sstevel@tonic-gate "WARNING: filesystem block size (%ld) is smaller than "
12957c478bd9Sstevel@tonic-gate "memory page size (%ld).\nResulting filesystem can not be "
12967c478bd9Sstevel@tonic-gate "mounted on this system.\n\n"),
12977c478bd9Sstevel@tonic-gate bsize, (long)PAGESIZE);
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gate range_check(&rps, "rps", 1, 1000, DEFHZ, rps_flag);
13017c478bd9Sstevel@tonic-gate range_check(&minfree, "free", 0, 99, MINFREE, minfree_flag);
13027c478bd9Sstevel@tonic-gate range_check(&nrpos, "nrpos", 1, nsect, MIN(nsect, NRPOS), nrpos_flag);
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate /*
13057c478bd9Sstevel@tonic-gate * nbpi is variable, but 2MB seems a reasonable upper limit,
13067c478bd9Sstevel@tonic-gate * as 4MB tends to cause problems (using otherwise-default
13077c478bd9Sstevel@tonic-gate * parameters). The true limit is where we end up with one
13087c478bd9Sstevel@tonic-gate * inode per cylinder group. If this file system is being
13097c478bd9Sstevel@tonic-gate * configured for multi-terabyte access, nbpi must be at least 1MB.
13107c478bd9Sstevel@tonic-gate */
13117c478bd9Sstevel@tonic-gate if (mtb == 'y' && nbpi < MTB_NBPI) {
1312d50c8f90Svsakar if (nbpi_flag != RC_DEFAULT)
1313d50c8f90Svsakar (void) fprintf(stderr, gettext("mkfs: bad value for "
1314d50c8f90Svsakar "nbpi: must be at least 1048576 for multi-terabyte,"
13157c478bd9Sstevel@tonic-gate " nbpi reset to default 1048576\n"));
13167c478bd9Sstevel@tonic-gate nbpi = MTB_NBPI;
13177c478bd9Sstevel@tonic-gate }
13187c478bd9Sstevel@tonic-gate
13197c478bd9Sstevel@tonic-gate if (mtb == 'y')
13207c478bd9Sstevel@tonic-gate range_check(&nbpi, "nbpi", MTB_NBPI, 2 * MB, MTB_NBPI,
13217c478bd9Sstevel@tonic-gate nbpi_flag);
13227c478bd9Sstevel@tonic-gate else
13237c478bd9Sstevel@tonic-gate range_check(&nbpi, "nbpi", DEV_BSIZE, 2 * MB, NBPI, nbpi_flag);
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate /*
13267c478bd9Sstevel@tonic-gate * maxcpg is another variably-limited parameter. Calculate
13277c478bd9Sstevel@tonic-gate * the limit based on what we've got for its dependent
13287c478bd9Sstevel@tonic-gate * variables. Effectively, it's how much space is left in the
13297c478bd9Sstevel@tonic-gate * superblock after all the other bits are accounted for. We
13307c478bd9Sstevel@tonic-gate * only fill in sblock fields so we can use MAXIpG.
13317c478bd9Sstevel@tonic-gate *
13327c478bd9Sstevel@tonic-gate * If the calculation of maxcpg below (for the mtb == 'n'
13337c478bd9Sstevel@tonic-gate * case) is changed, update newfs as well.
13347c478bd9Sstevel@tonic-gate *
13357c478bd9Sstevel@tonic-gate * For old-style, non-MTB format file systems, use the old
13367c478bd9Sstevel@tonic-gate * algorithm for calculating the maximum cylinder group size,
13377c478bd9Sstevel@tonic-gate * even though it limits the cylinder group more than necessary.
13387c478bd9Sstevel@tonic-gate * Since layout can affect performance, we don't want to change
13397c478bd9Sstevel@tonic-gate * the default layout for non-MTB file systems at this time.
13407c478bd9Sstevel@tonic-gate * However, for MTB file systems, use the new maxcpg calculation,
13417c478bd9Sstevel@tonic-gate * which really maxes out the cylinder group size.
13427c478bd9Sstevel@tonic-gate */
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate sblock.fs_bsize = bsize;
13457c478bd9Sstevel@tonic-gate sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate if (mtb == 'n') {
13487c478bd9Sstevel@tonic-gate maxcpg = (bsize - sizeof (struct cg) -
13497c478bd9Sstevel@tonic-gate howmany(MAXIpG(&sblock), NBBY)) /
13507c478bd9Sstevel@tonic-gate (sizeof (long) + nrpos * sizeof (short) +
13517c478bd9Sstevel@tonic-gate nsect / (MAXFRAG * NBBY));
13527c478bd9Sstevel@tonic-gate } else {
13537c478bd9Sstevel@tonic-gate maxcpg = compute_maxcpg(bsize, fragsize, nbpi, nrpos,
13547c478bd9Sstevel@tonic-gate nsect * ntrack);
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13576451fdbcSvsakar dprintf(("DeBuG cpg : %ld\n", cpg));
1358d50c8f90Svsakar /*
1359d50c8f90Svsakar * Increase the cpg to maxcpg if either newfs was invoked
1360d50c8f90Svsakar * with -T option or if mkfs wants to create a mtb file system
1361d50c8f90Svsakar * and if the user has not specified the cpg.
1362d50c8f90Svsakar */
1363d50c8f90Svsakar if (cpg == -1 || (mtb == 'y' && cpg_flag == RC_DEFAULT))
13647c478bd9Sstevel@tonic-gate cpg = maxcpg;
13656451fdbcSvsakar dprintf(("DeBuG cpg : %ld\n", cpg));
13666451fdbcSvsakar
13677c478bd9Sstevel@tonic-gate /*
13687c478bd9Sstevel@tonic-gate * mincpg is variable in complex ways, so we really can't
13697c478bd9Sstevel@tonic-gate * do a sane lower-end limit check at this point.
13707c478bd9Sstevel@tonic-gate */
13717c478bd9Sstevel@tonic-gate range_check(&cpg, "cgsize", 1, maxcpg, MIN(maxcpg, DESCPG), cpg_flag);
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate * get the controller info
13757c478bd9Sstevel@tonic-gate */
13767c478bd9Sstevel@tonic-gate ismdd = 0;
13777c478bd9Sstevel@tonic-gate islog = 0;
13787c478bd9Sstevel@tonic-gate islogok = 0;
13797c478bd9Sstevel@tonic-gate waslog = 0;
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate if (ioctl(fsi, DKIOCINFO, &dkcinfo) == 0)
13827c478bd9Sstevel@tonic-gate /*
13837c478bd9Sstevel@tonic-gate * if it is an MDD (disksuite) device
13847c478bd9Sstevel@tonic-gate */
13857c478bd9Sstevel@tonic-gate if (dkcinfo.dki_ctype == DKC_MD) {
13867c478bd9Sstevel@tonic-gate ismdd++;
13877c478bd9Sstevel@tonic-gate /*
13887c478bd9Sstevel@tonic-gate * check the logging device
13897c478bd9Sstevel@tonic-gate */
13907c478bd9Sstevel@tonic-gate if (ioctl(fsi, _FIOISLOG, NULL) == 0) {
13917c478bd9Sstevel@tonic-gate islog++;
13927c478bd9Sstevel@tonic-gate if (ioctl(fsi, _FIOISLOGOK, NULL) == 0)
13937c478bd9Sstevel@tonic-gate islogok++;
13947c478bd9Sstevel@tonic-gate }
13957c478bd9Sstevel@tonic-gate }
13967c478bd9Sstevel@tonic-gate
13977c478bd9Sstevel@tonic-gate /*
13987c478bd9Sstevel@tonic-gate * Do not grow the file system, but print on stdout the maximum
13997c478bd9Sstevel@tonic-gate * size in sectors to which the file system can be increased.
14007c478bd9Sstevel@tonic-gate * The calculated size is limited by fssize_db.
14017c478bd9Sstevel@tonic-gate * Note that we don't lock the filesystem and therefore under rare
14027c478bd9Sstevel@tonic-gate * conditions (the filesystem is mounted, the free block count is
14037c478bd9Sstevel@tonic-gate * almost zero, and the superuser is still changing it) the calculated
14047c478bd9Sstevel@tonic-gate * size can be imprecise.
14057c478bd9Sstevel@tonic-gate */
14067c478bd9Sstevel@tonic-gate if (Pflag) {
14077c478bd9Sstevel@tonic-gate (void) printf("%llu\n", probe_summaryinfo());
14087c478bd9Sstevel@tonic-gate exit(0);
14097c478bd9Sstevel@tonic-gate }
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate /*
14127c478bd9Sstevel@tonic-gate * If we're growing an existing filesystem, then we're about
14137c478bd9Sstevel@tonic-gate * to start doing things that can require recovery efforts if
14147c478bd9Sstevel@tonic-gate * we get interrupted, so make sure we get a chance to do so.
14157c478bd9Sstevel@tonic-gate */
14167c478bd9Sstevel@tonic-gate if (grow) {
14177c478bd9Sstevel@tonic-gate sigact.sa_handler = recover_from_sigint;
14187c478bd9Sstevel@tonic-gate sigemptyset(&sigact.sa_mask);
14197c478bd9Sstevel@tonic-gate sigact.sa_flags = SA_RESTART;
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate if (sigaction(SIGINT, &sigact, (struct sigaction *)NULL) < 0) {
14227c478bd9Sstevel@tonic-gate perror(gettext("Could not register SIGINT handler"));
14237c478bd9Sstevel@tonic-gate lockexit(3);
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate }
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate if (!Nflag) {
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * Check if MNTTAB is trustable
14307c478bd9Sstevel@tonic-gate */
14317c478bd9Sstevel@tonic-gate if (statvfs64(MNTTAB, &fs) < 0) {
14327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't statvfs %s\n"),
14337c478bd9Sstevel@tonic-gate MNTTAB);
14347c478bd9Sstevel@tonic-gate exit(32);
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate if (strcmp(MNTTYPE_MNTFS, fs.f_basetype) != 0) {
14387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
14397c478bd9Sstevel@tonic-gate "%s file system type is not %s, can't mkfs\n"),
14407c478bd9Sstevel@tonic-gate MNTTAB, MNTTYPE_MNTFS);
14417c478bd9Sstevel@tonic-gate exit(32);
14427c478bd9Sstevel@tonic-gate }
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate special = getfullblkname(fsys);
14457c478bd9Sstevel@tonic-gate checkdev(fsys, special);
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate /*
14487c478bd9Sstevel@tonic-gate * If we found the block device name,
14497c478bd9Sstevel@tonic-gate * then check the mount table.
14507c478bd9Sstevel@tonic-gate * if mounted, and growing write lock the file system
14517c478bd9Sstevel@tonic-gate *
14527c478bd9Sstevel@tonic-gate */
14537c478bd9Sstevel@tonic-gate if ((special != NULL) && (*special != '\0')) {
14547c478bd9Sstevel@tonic-gate if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
14557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
14567c478bd9Sstevel@tonic-gate "can't open %s\n"), MNTTAB);
14577c478bd9Sstevel@tonic-gate exit(32);
14587c478bd9Sstevel@tonic-gate }
14597c478bd9Sstevel@tonic-gate while ((getmntent(mnttab, &mntp)) == NULL) {
14607c478bd9Sstevel@tonic-gate if (grow) {
14617c478bd9Sstevel@tonic-gate checkmount(&mntp, special);
14627c478bd9Sstevel@tonic-gate continue;
14637c478bd9Sstevel@tonic-gate }
14647c478bd9Sstevel@tonic-gate if (strcmp(special, mntp.mnt_special) == 0) {
14657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
14667c478bd9Sstevel@tonic-gate "%s is mounted, can't mkfs\n"),
14677c478bd9Sstevel@tonic-gate special);
14687c478bd9Sstevel@tonic-gate exit(32);
14697c478bd9Sstevel@tonic-gate }
14707c478bd9Sstevel@tonic-gate }
14717c478bd9Sstevel@tonic-gate (void) fclose(mnttab);
14727c478bd9Sstevel@tonic-gate }
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate if (directory && (ismounted == 0)) {
14757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s is not mounted\n"),
14767c478bd9Sstevel@tonic-gate special);
14777c478bd9Sstevel@tonic-gate lockexit(32);
14787c478bd9Sstevel@tonic-gate }
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate fso = (grow) ? open64(fsys, O_WRONLY) : creat64(fsys, 0666);
14817c478bd9Sstevel@tonic-gate if (fso < 0) {
14827c478bd9Sstevel@tonic-gate saverr = errno;
14837c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14847c478bd9Sstevel@tonic-gate gettext("%s: cannot create: %s\n"),
14857c478bd9Sstevel@tonic-gate fsys, strerror(saverr));
14867c478bd9Sstevel@tonic-gate lockexit(32);
14877c478bd9Sstevel@tonic-gate }
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate } else {
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gate /*
14927c478bd9Sstevel@tonic-gate * For the -N case, a file descriptor is needed for the llseek()
14937c478bd9Sstevel@tonic-gate * in wtfs(). See the comment in wtfs() for more information.
14947c478bd9Sstevel@tonic-gate *
14957c478bd9Sstevel@tonic-gate * Get a file descriptor that's read-only so that this code
14967c478bd9Sstevel@tonic-gate * doesn't accidentally write to the file.
14977c478bd9Sstevel@tonic-gate */
14987c478bd9Sstevel@tonic-gate fso = open64(fsys, O_RDONLY);
14997c478bd9Sstevel@tonic-gate if (fso < 0) {
15007c478bd9Sstevel@tonic-gate saverr = errno;
15017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: cannot open: %s\n"),
15027c478bd9Sstevel@tonic-gate fsys, strerror(saverr));
15037c478bd9Sstevel@tonic-gate lockexit(32);
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate /*
150865908c77Syu, larry liu - Sun Microsystems - Beijing China * Check the media sector size
150965908c77Syu, larry liu - Sun Microsystems - Beijing China */
151065908c77Syu, larry liu - Sun Microsystems - Beijing China if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) {
151165908c77Syu, larry liu - Sun Microsystems - Beijing China if (dkminfo.dki_lbsize != 0 &&
151265908c77Syu, larry liu - Sun Microsystems - Beijing China POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) &&
151365908c77Syu, larry liu - Sun Microsystems - Beijing China dkminfo.dki_lbsize != DEV_BSIZE) {
151465908c77Syu, larry liu - Sun Microsystems - Beijing China fprintf(stderr,
151565908c77Syu, larry liu - Sun Microsystems - Beijing China gettext("The device sector size %u is not "
151665908c77Syu, larry liu - Sun Microsystems - Beijing China "supported by ufs!\n"), dkminfo.dki_lbsize);
151765908c77Syu, larry liu - Sun Microsystems - Beijing China (void) close(fso);
151865908c77Syu, larry liu - Sun Microsystems - Beijing China exit(1);
151965908c77Syu, larry liu - Sun Microsystems - Beijing China }
152065908c77Syu, larry liu - Sun Microsystems - Beijing China }
152165908c77Syu, larry liu - Sun Microsystems - Beijing China
152265908c77Syu, larry liu - Sun Microsystems - Beijing China /*
15237c478bd9Sstevel@tonic-gate * seed random # generator (for ic_generation)
15247c478bd9Sstevel@tonic-gate */
15257c478bd9Sstevel@tonic-gate #ifdef MKFS_DEBUG
15267c478bd9Sstevel@tonic-gate srand48(12962); /* reproducible results */
15277c478bd9Sstevel@tonic-gate #else
15287c478bd9Sstevel@tonic-gate srand48((long)(time((time_t *)NULL) + getpid()));
15297c478bd9Sstevel@tonic-gate #endif
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate if (grow) {
15327c478bd9Sstevel@tonic-gate growinit(fsys);
15337c478bd9Sstevel@tonic-gate goto grow00;
15347c478bd9Sstevel@tonic-gate }
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate /*
15377c478bd9Sstevel@tonic-gate * Validate the given file system size.
15387c478bd9Sstevel@tonic-gate * Verify that its last block can actually be accessed.
15397c478bd9Sstevel@tonic-gate *
15407c478bd9Sstevel@tonic-gate * Note: it's ok to use sblock as a buffer because it is immediately
15417c478bd9Sstevel@tonic-gate * overwritten by the rdfs() of the superblock in the next line.
15427c478bd9Sstevel@tonic-gate *
15437c478bd9Sstevel@tonic-gate * ToDo: Because the size checking is done in rdfs()/wtfs(), the
15447c478bd9Sstevel@tonic-gate * error message for specifying an illegal size is very unfriendly.
15457c478bd9Sstevel@tonic-gate * In the future, one could replace the rdfs()/wtfs() calls
15467c478bd9Sstevel@tonic-gate * below with in-line calls to read() or write(). This allows better
15477c478bd9Sstevel@tonic-gate * error messages to be put in place.
15487c478bd9Sstevel@tonic-gate */
15497c478bd9Sstevel@tonic-gate rdfs(fssize_db - 1, (int)sectorsize, (char *)&sblock);
15507c478bd9Sstevel@tonic-gate
15517c478bd9Sstevel@tonic-gate /*
15527c478bd9Sstevel@tonic-gate * make the fs unmountable
15537c478bd9Sstevel@tonic-gate */
15547c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
15557c478bd9Sstevel@tonic-gate sblock.fs_magic = -1;
15567c478bd9Sstevel@tonic-gate sblock.fs_clean = FSBAD;
15577c478bd9Sstevel@tonic-gate sblock.fs_state = FSOKAY - sblock.fs_time;
15587c478bd9Sstevel@tonic-gate wtfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
15597c478bd9Sstevel@tonic-gate bzero(&sblock, (size_t)sbsize);
15607c478bd9Sstevel@tonic-gate
15617c478bd9Sstevel@tonic-gate sblock.fs_nsect = nsect;
15627c478bd9Sstevel@tonic-gate sblock.fs_ntrak = ntrack;
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate /*
15657c478bd9Sstevel@tonic-gate * Validate specified/determined spc
15667c478bd9Sstevel@tonic-gate * and calculate minimum cylinders per group.
15677c478bd9Sstevel@tonic-gate */
15687c478bd9Sstevel@tonic-gate
15697c478bd9Sstevel@tonic-gate /*
15707c478bd9Sstevel@tonic-gate * sectors/cyl = tracks/cyl * sectors/track
15717c478bd9Sstevel@tonic-gate */
15727c478bd9Sstevel@tonic-gate sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
15737c478bd9Sstevel@tonic-gate
15747c478bd9Sstevel@tonic-gate grow00:
15757c478bd9Sstevel@tonic-gate if (apc_flag) {
15767c478bd9Sstevel@tonic-gate sblock.fs_spc -= apc;
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate /*
15797c478bd9Sstevel@tonic-gate * Have to test for this separately from apc_flag, due to
15807c478bd9Sstevel@tonic-gate * the growfs case....
15817c478bd9Sstevel@tonic-gate */
15827c478bd9Sstevel@tonic-gate if (sblock.fs_spc != sblock.fs_ntrak * sblock.fs_nsect) {
15837c478bd9Sstevel@tonic-gate spc_flag = 1;
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate if (grow)
15867c478bd9Sstevel@tonic-gate goto grow10;
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate sblock.fs_nrpos = nrpos;
15897c478bd9Sstevel@tonic-gate sblock.fs_bsize = bsize;
15907c478bd9Sstevel@tonic-gate sblock.fs_fsize = fragsize;
15917c478bd9Sstevel@tonic-gate sblock.fs_minfree = minfree;
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate grow10:
15947c478bd9Sstevel@tonic-gate if (nbpi < sblock.fs_fsize) {
15957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
15967c478bd9Sstevel@tonic-gate "warning: wasteful data byte allocation / inode (nbpi):\n"));
15977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
15987c478bd9Sstevel@tonic-gate "%ld smaller than allocatable fragment size of %d\n"),
15997c478bd9Sstevel@tonic-gate nbpi, sblock.fs_fsize);
16007c478bd9Sstevel@tonic-gate }
16017c478bd9Sstevel@tonic-gate if (grow)
16027c478bd9Sstevel@tonic-gate goto grow20;
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate if (opt == 's')
16057c478bd9Sstevel@tonic-gate sblock.fs_optim = FS_OPTSPACE;
16067c478bd9Sstevel@tonic-gate else
16077c478bd9Sstevel@tonic-gate sblock.fs_optim = FS_OPTTIME;
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate sblock.fs_bmask = ~(sblock.fs_bsize - 1);
16107c478bd9Sstevel@tonic-gate sblock.fs_fmask = ~(sblock.fs_fsize - 1);
16117c478bd9Sstevel@tonic-gate /*
16127c478bd9Sstevel@tonic-gate * Planning now for future expansion.
16137c478bd9Sstevel@tonic-gate */
16147c478bd9Sstevel@tonic-gate #if defined(_BIG_ENDIAN)
16157c478bd9Sstevel@tonic-gate sblock.fs_qbmask.val[0] = 0;
16167c478bd9Sstevel@tonic-gate sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
16177c478bd9Sstevel@tonic-gate sblock.fs_qfmask.val[0] = 0;
16187c478bd9Sstevel@tonic-gate sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
16197c478bd9Sstevel@tonic-gate #endif
16207c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN)
16217c478bd9Sstevel@tonic-gate sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
16227c478bd9Sstevel@tonic-gate sblock.fs_qbmask.val[1] = 0;
16237c478bd9Sstevel@tonic-gate sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
16247c478bd9Sstevel@tonic-gate sblock.fs_qfmask.val[1] = 0;
16257c478bd9Sstevel@tonic-gate #endif
16267c478bd9Sstevel@tonic-gate for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
16277c478bd9Sstevel@tonic-gate sblock.fs_bshift++;
16287c478bd9Sstevel@tonic-gate for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
16297c478bd9Sstevel@tonic-gate sblock.fs_fshift++;
16307c478bd9Sstevel@tonic-gate sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
16317c478bd9Sstevel@tonic-gate for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
16327c478bd9Sstevel@tonic-gate sblock.fs_fragshift++;
16337c478bd9Sstevel@tonic-gate if (sblock.fs_frag > MAXFRAG) {
16347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
16357c478bd9Sstevel@tonic-gate "fragment size %d is too small, minimum with block size %d is %d\n"),
16367c478bd9Sstevel@tonic-gate sblock.fs_fsize, sblock.fs_bsize,
16377c478bd9Sstevel@tonic-gate sblock.fs_bsize / MAXFRAG);
16387c478bd9Sstevel@tonic-gate lockexit(32);
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate sblock.fs_nindir = sblock.fs_bsize / sizeof (daddr32_t);
16417c478bd9Sstevel@tonic-gate sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
16427c478bd9Sstevel@tonic-gate sblock.fs_nspf = sblock.fs_fsize / sectorsize;
16437c478bd9Sstevel@tonic-gate for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
16447c478bd9Sstevel@tonic-gate sblock.fs_fsbtodb++;
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate /*
16477c478bd9Sstevel@tonic-gate * Compute the super-block, cylinder group, and inode blocks.
16487c478bd9Sstevel@tonic-gate * Note that these "blkno" are really fragment addresses.
16497c478bd9Sstevel@tonic-gate * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16,
16507c478bd9Sstevel@tonic-gate * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so
16517c478bd9Sstevel@tonic-gate * important: only 1 FS block is allocated for the cg struct (fragment
16527c478bd9Sstevel@tonic-gate * numbers 24 through 31).
16537c478bd9Sstevel@tonic-gate */
16547c478bd9Sstevel@tonic-gate sblock.fs_sblkno =
16557c478bd9Sstevel@tonic-gate roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
16567c478bd9Sstevel@tonic-gate sblock.fs_cblkno = (daddr32_t)(sblock.fs_sblkno +
16577c478bd9Sstevel@tonic-gate roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
16587c478bd9Sstevel@tonic-gate sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate sblock.fs_cgoffset = roundup(
16617c478bd9Sstevel@tonic-gate howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
16627c478bd9Sstevel@tonic-gate for (sblock.fs_cgmask = -1, i = sblock.fs_ntrak; i > 1; i >>= 1)
16637c478bd9Sstevel@tonic-gate sblock.fs_cgmask <<= 1;
16647c478bd9Sstevel@tonic-gate if (!POWEROF2(sblock.fs_ntrak))
16657c478bd9Sstevel@tonic-gate sblock.fs_cgmask <<= 1;
16667c478bd9Sstevel@tonic-gate /*
16677c478bd9Sstevel@tonic-gate * Validate specified/determined spc
16687c478bd9Sstevel@tonic-gate * and calculate minimum cylinders per group.
16697c478bd9Sstevel@tonic-gate */
16707c478bd9Sstevel@tonic-gate
16717c478bd9Sstevel@tonic-gate for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
16727c478bd9Sstevel@tonic-gate sblock.fs_cpc > 1 && (i & 1) == 0;
16737c478bd9Sstevel@tonic-gate sblock.fs_cpc >>= 1, i >>= 1)
16747c478bd9Sstevel@tonic-gate /* void */;
16757c478bd9Sstevel@tonic-gate mincpc = sblock.fs_cpc;
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate /* if these calculations are changed, check dump_fscmd also */
16787c478bd9Sstevel@tonic-gate bpcg = (uint64_t)sblock.fs_spc * sectorsize;
16797c478bd9Sstevel@tonic-gate inospercg = (uint64_t)roundup(bpcg / sizeof (struct dinode),
16807c478bd9Sstevel@tonic-gate INOPB(&sblock));
16817c478bd9Sstevel@tonic-gate if (inospercg > MAXIpG(&sblock))
16827c478bd9Sstevel@tonic-gate inospercg = MAXIpG(&sblock);
16837c478bd9Sstevel@tonic-gate used = (uint64_t)(sblock.fs_iblkno + inospercg /
16847c478bd9Sstevel@tonic-gate INOPF(&sblock)) * NSPF(&sblock);
16857c478bd9Sstevel@tonic-gate mincpgcnt = (long)howmany((uint64_t)sblock.fs_cgoffset *
16867c478bd9Sstevel@tonic-gate (~sblock.fs_cgmask) + used, sblock.fs_spc);
16877c478bd9Sstevel@tonic-gate mincpg = roundup(mincpgcnt, mincpc);
16887c478bd9Sstevel@tonic-gate /*
16897c478bd9Sstevel@tonic-gate * Insure that cylinder group with mincpg has enough space
16907c478bd9Sstevel@tonic-gate * for block maps
16917c478bd9Sstevel@tonic-gate */
16927c478bd9Sstevel@tonic-gate sblock.fs_cpg = mincpg;
16937c478bd9Sstevel@tonic-gate sblock.fs_ipg = (int32_t)inospercg;
16947c478bd9Sstevel@tonic-gate mapcramped = 0;
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate /*
16977c478bd9Sstevel@tonic-gate * Make sure the cg struct fits within the file system block.
16987c478bd9Sstevel@tonic-gate * Use larger block sizes until it fits
16997c478bd9Sstevel@tonic-gate */
17007c478bd9Sstevel@tonic-gate while (CGSIZE(&sblock) > sblock.fs_bsize) {
17017c478bd9Sstevel@tonic-gate mapcramped = 1;
17027c478bd9Sstevel@tonic-gate if (sblock.fs_bsize < MAXBSIZE) {
17037c478bd9Sstevel@tonic-gate sblock.fs_bsize <<= 1;
17047c478bd9Sstevel@tonic-gate if ((i & 1) == 0) {
17057c478bd9Sstevel@tonic-gate i >>= 1;
17067c478bd9Sstevel@tonic-gate } else {
17077c478bd9Sstevel@tonic-gate sblock.fs_cpc <<= 1;
17087c478bd9Sstevel@tonic-gate mincpc <<= 1;
17097c478bd9Sstevel@tonic-gate mincpg = roundup(mincpgcnt, mincpc);
17107c478bd9Sstevel@tonic-gate sblock.fs_cpg = mincpg;
17117c478bd9Sstevel@tonic-gate }
17127c478bd9Sstevel@tonic-gate sblock.fs_frag <<= 1;
17137c478bd9Sstevel@tonic-gate sblock.fs_fragshift += 1;
17147c478bd9Sstevel@tonic-gate if (sblock.fs_frag <= MAXFRAG)
17157c478bd9Sstevel@tonic-gate continue;
17167c478bd9Sstevel@tonic-gate }
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate /*
17197c478bd9Sstevel@tonic-gate * Looped far enough. The fragment is now as large as the
17207c478bd9Sstevel@tonic-gate * filesystem block!
17217c478bd9Sstevel@tonic-gate */
17227c478bd9Sstevel@tonic-gate if (sblock.fs_fsize == sblock.fs_bsize) {
17237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
17247c478bd9Sstevel@tonic-gate "There is no block size that can support this disk\n"));
17257c478bd9Sstevel@tonic-gate lockexit(32);
17267c478bd9Sstevel@tonic-gate }
17277c478bd9Sstevel@tonic-gate
17287c478bd9Sstevel@tonic-gate /*
17297c478bd9Sstevel@tonic-gate * Try a larger fragment. Double the fragment size.
17307c478bd9Sstevel@tonic-gate */
17317c478bd9Sstevel@tonic-gate sblock.fs_frag >>= 1;
17327c478bd9Sstevel@tonic-gate sblock.fs_fragshift -= 1;
17337c478bd9Sstevel@tonic-gate sblock.fs_fsize <<= 1;
17347c478bd9Sstevel@tonic-gate sblock.fs_nspf <<= 1;
17357c478bd9Sstevel@tonic-gate }
17367c478bd9Sstevel@tonic-gate /*
17377c478bd9Sstevel@tonic-gate * Insure that cylinder group with mincpg has enough space for inodes
17387c478bd9Sstevel@tonic-gate */
17397c478bd9Sstevel@tonic-gate inodecramped = 0;
17407c478bd9Sstevel@tonic-gate used *= sectorsize;
17417c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)mincpg * bpcg - used;
17427c478bd9Sstevel@tonic-gate inospercg = (uint64_t)roundup((nbytes64 / nbpi), INOPB(&sblock));
17437c478bd9Sstevel@tonic-gate sblock.fs_ipg = (int32_t)inospercg;
17447c478bd9Sstevel@tonic-gate while (inospercg > MAXIpG(&sblock)) {
17457c478bd9Sstevel@tonic-gate inodecramped = 1;
17467c478bd9Sstevel@tonic-gate if (mincpc == 1 || sblock.fs_frag == 1 ||
17477c478bd9Sstevel@tonic-gate sblock.fs_bsize == MINBSIZE)
17487c478bd9Sstevel@tonic-gate break;
17497c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)mincpg * bpcg - used;
17507c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
17517c478bd9Sstevel@tonic-gate gettext("With a block size of %d %s %lu\n"),
17527c478bd9Sstevel@tonic-gate sblock.fs_bsize, gettext("minimum bytes per inode is"),
17537c478bd9Sstevel@tonic-gate (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
17547c478bd9Sstevel@tonic-gate sblock.fs_bsize >>= 1;
17557c478bd9Sstevel@tonic-gate sblock.fs_frag >>= 1;
17567c478bd9Sstevel@tonic-gate sblock.fs_fragshift -= 1;
17577c478bd9Sstevel@tonic-gate mincpc >>= 1;
17587c478bd9Sstevel@tonic-gate sblock.fs_cpg = roundup(mincpgcnt, mincpc);
17597c478bd9Sstevel@tonic-gate if (CGSIZE(&sblock) > sblock.fs_bsize) {
17607c478bd9Sstevel@tonic-gate sblock.fs_bsize <<= 1;
17617c478bd9Sstevel@tonic-gate break;
17627c478bd9Sstevel@tonic-gate }
17637c478bd9Sstevel@tonic-gate mincpg = sblock.fs_cpg;
17647c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)mincpg * bpcg - used;
17657c478bd9Sstevel@tonic-gate inospercg = (uint64_t)roundup((nbytes64 / nbpi),
17667c478bd9Sstevel@tonic-gate INOPB(&sblock));
17677c478bd9Sstevel@tonic-gate sblock.fs_ipg = (int32_t)inospercg;
17687c478bd9Sstevel@tonic-gate }
17697c478bd9Sstevel@tonic-gate if (inodecramped) {
17707c478bd9Sstevel@tonic-gate if (inospercg > MAXIpG(&sblock)) {
17717c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)mincpg * bpcg - used;
17727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
17737c478bd9Sstevel@tonic-gate "Minimum bytes per inode is %d\n"),
17747c478bd9Sstevel@tonic-gate (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
17757c478bd9Sstevel@tonic-gate } else if (!mapcramped) {
17767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
17777c478bd9Sstevel@tonic-gate "With %ld bytes per inode, minimum cylinders per group is %ld\n"),
17787c478bd9Sstevel@tonic-gate nbpi, mincpg);
17797c478bd9Sstevel@tonic-gate }
17807c478bd9Sstevel@tonic-gate }
17817c478bd9Sstevel@tonic-gate if (mapcramped) {
17827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
17837c478bd9Sstevel@tonic-gate "With %d sectors per cylinder, minimum cylinders "
17847c478bd9Sstevel@tonic-gate "per group is %ld\n"),
17857c478bd9Sstevel@tonic-gate sblock.fs_spc, mincpg);
17867c478bd9Sstevel@tonic-gate }
17877c478bd9Sstevel@tonic-gate if (inodecramped || mapcramped) {
17887c478bd9Sstevel@tonic-gate /*
17897c478bd9Sstevel@tonic-gate * To make this at least somewhat comprehensible in
17907c478bd9Sstevel@tonic-gate * the world of i18n, figure out what we're going to
17917c478bd9Sstevel@tonic-gate * say and then say it all at one time. The days of
17927c478bd9Sstevel@tonic-gate * needing to scrimp on string space are behind us....
17937c478bd9Sstevel@tonic-gate */
17947c478bd9Sstevel@tonic-gate if ((sblock.fs_bsize != bsize) &&
17957c478bd9Sstevel@tonic-gate (sblock.fs_fsize != fragsize)) {
17967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
17977c478bd9Sstevel@tonic-gate "This requires the block size to be changed from %ld to %d\n"
17987c478bd9Sstevel@tonic-gate "and the fragment size to be changed from %ld to %d\n"),
17997c478bd9Sstevel@tonic-gate bsize, sblock.fs_bsize,
18007c478bd9Sstevel@tonic-gate fragsize, sblock.fs_fsize);
18017c478bd9Sstevel@tonic-gate } else if (sblock.fs_bsize != bsize) {
18027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18037c478bd9Sstevel@tonic-gate "This requires the block size to be changed from %ld to %d\n"),
18047c478bd9Sstevel@tonic-gate bsize, sblock.fs_bsize);
18057c478bd9Sstevel@tonic-gate } else if (sblock.fs_fsize != fragsize) {
18067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18077c478bd9Sstevel@tonic-gate "This requires the fragment size to be changed from %ld to %d\n"),
18087c478bd9Sstevel@tonic-gate fragsize, sblock.fs_fsize);
18097c478bd9Sstevel@tonic-gate } else {
18107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18117c478bd9Sstevel@tonic-gate "Unable to make filesystem fit with the given constraints\n"));
18127c478bd9Sstevel@tonic-gate }
18137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18147c478bd9Sstevel@tonic-gate "Please re-run mkfs with corrected parameters\n"));
18157c478bd9Sstevel@tonic-gate lockexit(32);
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate /*
18187c478bd9Sstevel@tonic-gate * Calculate the number of cylinders per group
18197c478bd9Sstevel@tonic-gate */
18207c478bd9Sstevel@tonic-gate sblock.fs_cpg = cpg;
18217c478bd9Sstevel@tonic-gate if (sblock.fs_cpg % mincpc != 0) {
18227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18237c478bd9Sstevel@tonic-gate "Warning: cylinder groups must have a multiple "
18247c478bd9Sstevel@tonic-gate "of %ld cylinders with the given\n parameters\n"),
18257c478bd9Sstevel@tonic-gate mincpc);
18267c478bd9Sstevel@tonic-gate sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
18277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Rounded cgsize up to %d\n"),
18287c478bd9Sstevel@tonic-gate sblock.fs_cpg);
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate /*
18317c478bd9Sstevel@tonic-gate * Must insure there is enough space for inodes
18327c478bd9Sstevel@tonic-gate */
18337c478bd9Sstevel@tonic-gate /* if these calculations are changed, check dump_fscmd also */
18347c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
18357c478bd9Sstevel@tonic-gate sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), INOPB(&sblock));
18367c478bd9Sstevel@tonic-gate
18377c478bd9Sstevel@tonic-gate /*
18387c478bd9Sstevel@tonic-gate * Slim down cylinders per group, until the inodes can fit.
18397c478bd9Sstevel@tonic-gate */
18407c478bd9Sstevel@tonic-gate while (sblock.fs_ipg > MAXIpG(&sblock)) {
18417c478bd9Sstevel@tonic-gate inodecramped = 1;
18427c478bd9Sstevel@tonic-gate sblock.fs_cpg -= mincpc;
18437c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
18447c478bd9Sstevel@tonic-gate sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
18457c478bd9Sstevel@tonic-gate INOPB(&sblock));
18467c478bd9Sstevel@tonic-gate }
18477c478bd9Sstevel@tonic-gate /*
18487c478bd9Sstevel@tonic-gate * Must insure there is enough space to hold block map.
18497c478bd9Sstevel@tonic-gate * Cut down on cylinders per group, until the cg struct fits in a
18507c478bd9Sstevel@tonic-gate * filesystem block.
18517c478bd9Sstevel@tonic-gate */
18527c478bd9Sstevel@tonic-gate while (CGSIZE(&sblock) > sblock.fs_bsize) {
18537c478bd9Sstevel@tonic-gate mapcramped = 1;
18547c478bd9Sstevel@tonic-gate sblock.fs_cpg -= mincpc;
18557c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
18567c478bd9Sstevel@tonic-gate sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
18577c478bd9Sstevel@tonic-gate INOPB(&sblock));
18587c478bd9Sstevel@tonic-gate }
18597c478bd9Sstevel@tonic-gate sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
18607c478bd9Sstevel@tonic-gate if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
18617c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18627c478bd9Sstevel@tonic-gate gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n"));
18637c478bd9Sstevel@tonic-gate lockexit(32);
18647c478bd9Sstevel@tonic-gate }
18657c478bd9Sstevel@tonic-gate if (sblock.fs_cpg < mincpg) {
18667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18677c478bd9Sstevel@tonic-gate "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"),
18687c478bd9Sstevel@tonic-gate mincpg);
18697c478bd9Sstevel@tonic-gate lockexit(32);
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
18727c478bd9Sstevel@tonic-gate grow20:
18737c478bd9Sstevel@tonic-gate /*
18747c478bd9Sstevel@tonic-gate * Now have size for file system and nsect and ntrak.
18757c478bd9Sstevel@tonic-gate * Determine number of cylinders and blocks in the file system.
18767c478bd9Sstevel@tonic-gate */
18777c478bd9Sstevel@tonic-gate fssize_frag = (int64_t)dbtofsb(&sblock, fssize_db);
18787c478bd9Sstevel@tonic-gate if (fssize_frag > INT_MAX) {
18797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18807c478bd9Sstevel@tonic-gate "There are too many fragments in the system, increase fragment size\n"),
18817c478bd9Sstevel@tonic-gate mincpg);
18827c478bd9Sstevel@tonic-gate lockexit(32);
18837c478bd9Sstevel@tonic-gate }
18847c478bd9Sstevel@tonic-gate sblock.fs_size = (int32_t)fssize_frag;
18857c478bd9Sstevel@tonic-gate sblock.fs_ncyl = (int32_t)(fssize_frag * NSPF(&sblock) / sblock.fs_spc);
18867c478bd9Sstevel@tonic-gate if (fssize_frag * NSPF(&sblock) >
18877c478bd9Sstevel@tonic-gate (uint64_t)sblock.fs_ncyl * sblock.fs_spc) {
18887c478bd9Sstevel@tonic-gate sblock.fs_ncyl++;
18897c478bd9Sstevel@tonic-gate warn = 1;
18907c478bd9Sstevel@tonic-gate }
18917c478bd9Sstevel@tonic-gate if (sblock.fs_ncyl < 1) {
18927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
18937c478bd9Sstevel@tonic-gate "file systems must have at least one cylinder\n"));
18947c478bd9Sstevel@tonic-gate lockexit(32);
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate if (grow)
18977c478bd9Sstevel@tonic-gate goto grow30;
18987c478bd9Sstevel@tonic-gate /*
18997c478bd9Sstevel@tonic-gate * Determine feasability/values of rotational layout tables.
19007c478bd9Sstevel@tonic-gate *
19017c478bd9Sstevel@tonic-gate * The size of the rotational layout tables is limited by the size
19027c478bd9Sstevel@tonic-gate * of the file system block, fs_bsize. The amount of space
19037c478bd9Sstevel@tonic-gate * available for tables is calculated as (fs_bsize - sizeof (struct
19047c478bd9Sstevel@tonic-gate * fs)). The size of these tables is inversely proportional to the
19057c478bd9Sstevel@tonic-gate * block size of the file system. The size increases if sectors per
19067c478bd9Sstevel@tonic-gate * track are not powers of two, because more cylinders must be
19077c478bd9Sstevel@tonic-gate * described by the tables before the rotational pattern repeats
19087c478bd9Sstevel@tonic-gate * (fs_cpc).
19097c478bd9Sstevel@tonic-gate */
19107c478bd9Sstevel@tonic-gate sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
19117c478bd9Sstevel@tonic-gate sblock.fs_sbsize = fragroundup(&sblock, sizeof (struct fs));
19127c478bd9Sstevel@tonic-gate sblock.fs_npsect = sblock.fs_nsect;
19137c478bd9Sstevel@tonic-gate if (sblock.fs_ntrak == 1) {
19147c478bd9Sstevel@tonic-gate sblock.fs_cpc = 0;
19157c478bd9Sstevel@tonic-gate goto next;
19167c478bd9Sstevel@tonic-gate }
19177c478bd9Sstevel@tonic-gate postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof (short);
19187c478bd9Sstevel@tonic-gate rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
19197c478bd9Sstevel@tonic-gate totalsbsize = sizeof (struct fs) + rotblsize;
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate /* do static allocation if nrpos == 8 and fs_cpc == 16 */
19227c478bd9Sstevel@tonic-gate if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
19237c478bd9Sstevel@tonic-gate /* use old static table space */
19247c478bd9Sstevel@tonic-gate sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
19257c478bd9Sstevel@tonic-gate (char *)(&sblock.fs_link);
19267c478bd9Sstevel@tonic-gate sblock.fs_rotbloff = &sblock.fs_space[0] -
19277c478bd9Sstevel@tonic-gate (uchar_t *)(&sblock.fs_link);
19287c478bd9Sstevel@tonic-gate } else {
19297c478bd9Sstevel@tonic-gate /* use 4.3 dynamic table space */
19307c478bd9Sstevel@tonic-gate sblock.fs_postbloff = &sblock.fs_space[0] -
19317c478bd9Sstevel@tonic-gate (uchar_t *)(&sblock.fs_link);
19327c478bd9Sstevel@tonic-gate sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
19337c478bd9Sstevel@tonic-gate totalsbsize += postblsize;
19347c478bd9Sstevel@tonic-gate }
19357c478bd9Sstevel@tonic-gate if (totalsbsize > sblock.fs_bsize ||
19367c478bd9Sstevel@tonic-gate sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
19377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
19387c478bd9Sstevel@tonic-gate "Warning: insufficient space in super block for\n"
19397c478bd9Sstevel@tonic-gate "rotational layout tables with nsect %d, ntrack %d, "
19407c478bd9Sstevel@tonic-gate "and nrpos %d.\nOmitting tables - file system "
19417c478bd9Sstevel@tonic-gate "performance may be impaired.\n"),
19427c478bd9Sstevel@tonic-gate sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_nrpos);
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate /*
19457c478bd9Sstevel@tonic-gate * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to
19467c478bd9Sstevel@tonic-gate * ignore the positional layout table and rotational
19477c478bd9Sstevel@tonic-gate * position table.
19487c478bd9Sstevel@tonic-gate */
19497c478bd9Sstevel@tonic-gate sblock.fs_cpc = 0;
19507c478bd9Sstevel@tonic-gate goto next;
19517c478bd9Sstevel@tonic-gate }
19527c478bd9Sstevel@tonic-gate sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
19537c478bd9Sstevel@tonic-gate
19547c478bd9Sstevel@tonic-gate
19557c478bd9Sstevel@tonic-gate /*
19567c478bd9Sstevel@tonic-gate * calculate the available blocks for each rotational position
19577c478bd9Sstevel@tonic-gate */
19587c478bd9Sstevel@tonic-gate for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
19597c478bd9Sstevel@tonic-gate for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
19607c478bd9Sstevel@tonic-gate fs_postbl(&sblock, cylno)[rpos] = -1;
19617c478bd9Sstevel@tonic-gate for (i = (rotblsize - 1) * sblock.fs_frag;
19627c478bd9Sstevel@tonic-gate i >= 0; i -= sblock.fs_frag) {
19637c478bd9Sstevel@tonic-gate cylno = cbtocylno(&sblock, i);
19647c478bd9Sstevel@tonic-gate rpos = cbtorpos(&sblock, i);
19657c478bd9Sstevel@tonic-gate blk = fragstoblks(&sblock, i);
19667c478bd9Sstevel@tonic-gate if (fs_postbl(&sblock, cylno)[rpos] == -1)
19677c478bd9Sstevel@tonic-gate fs_rotbl(&sblock)[blk] = 0;
19687c478bd9Sstevel@tonic-gate else
19697c478bd9Sstevel@tonic-gate fs_rotbl(&sblock)[blk] =
19707c478bd9Sstevel@tonic-gate fs_postbl(&sblock, cylno)[rpos] - blk;
19717c478bd9Sstevel@tonic-gate fs_postbl(&sblock, cylno)[rpos] = blk;
19727c478bd9Sstevel@tonic-gate }
19737c478bd9Sstevel@tonic-gate next:
19747c478bd9Sstevel@tonic-gate grow30:
19757c478bd9Sstevel@tonic-gate /*
19767c478bd9Sstevel@tonic-gate * Compute/validate number of cylinder groups.
19777c478bd9Sstevel@tonic-gate * Note that if an excessively large filesystem is specified
19787c478bd9Sstevel@tonic-gate * (e.g., more than 16384 cylinders for an 8K filesystem block), it
19797c478bd9Sstevel@tonic-gate * does not get detected until checksummarysize()
19807c478bd9Sstevel@tonic-gate */
19817c478bd9Sstevel@tonic-gate sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
19827c478bd9Sstevel@tonic-gate if (sblock.fs_ncyl % sblock.fs_cpg)
19837c478bd9Sstevel@tonic-gate sblock.fs_ncg++;
19847c478bd9Sstevel@tonic-gate sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
19857c478bd9Sstevel@tonic-gate i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
19867c478bd9Sstevel@tonic-gate ibpcl = cgdmin(&sblock, i) - cgbase(&sblock, i);
19877c478bd9Sstevel@tonic-gate if (ibpcl >= sblock.fs_fpg) {
19887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
19897c478bd9Sstevel@tonic-gate "inode blocks/cyl group (%d) >= data blocks (%d)\n"),
19907c478bd9Sstevel@tonic-gate cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
19917c478bd9Sstevel@tonic-gate sblock.fs_fpg / sblock.fs_frag);
19927c478bd9Sstevel@tonic-gate if ((ibpcl < 0) || (sblock.fs_fpg < 0)) {
19937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
19947c478bd9Sstevel@tonic-gate "number of cylinders per cylinder group (%d) must be decreased.\n"),
19957c478bd9Sstevel@tonic-gate sblock.fs_cpg);
19967c478bd9Sstevel@tonic-gate } else {
19977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
19987c478bd9Sstevel@tonic-gate "number of cylinders per cylinder group (%d) must be increased.\n"),
19997c478bd9Sstevel@tonic-gate sblock.fs_cpg);
20007c478bd9Sstevel@tonic-gate }
20017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
20027c478bd9Sstevel@tonic-gate "Note that cgsize may have been adjusted to allow struct cg to fit.\n"));
20037c478bd9Sstevel@tonic-gate lockexit(32);
20047c478bd9Sstevel@tonic-gate }
20057c478bd9Sstevel@tonic-gate j = sblock.fs_ncg - 1;
20067c478bd9Sstevel@tonic-gate if ((i = fssize_frag - j * sblock.fs_fpg) < sblock.fs_fpg &&
20077c478bd9Sstevel@tonic-gate cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
20087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
20097c478bd9Sstevel@tonic-gate "Warning: inode blocks/cyl group (%d) >= data "
20107c478bd9Sstevel@tonic-gate "blocks (%ld) in last\n cylinder group. This "
20117c478bd9Sstevel@tonic-gate "implies %ld sector(s) cannot be allocated.\n"),
20127c478bd9Sstevel@tonic-gate (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
20137c478bd9Sstevel@tonic-gate i / sblock.fs_frag, i * NSPF(&sblock));
20146d24e334Svsakar /*
20156d24e334Svsakar * If there is only one cylinder group and that is not even
20166d24e334Svsakar * big enough to hold the inodes, exit.
20176d24e334Svsakar */
20186d24e334Svsakar if (sblock.fs_ncg == 1)
20196d24e334Svsakar cg_too_small = 1;
20207c478bd9Sstevel@tonic-gate sblock.fs_ncg--;
202138b58fe3SHarold N Shaw- Sun Microsystem sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
20227c478bd9Sstevel@tonic-gate sblock.fs_size = fssize_frag =
20237c478bd9Sstevel@tonic-gate (int64_t)sblock.fs_ncyl * (int64_t)sblock.fs_spc /
20247c478bd9Sstevel@tonic-gate (int64_t)NSPF(&sblock);
20257c478bd9Sstevel@tonic-gate warn = 0;
20267c478bd9Sstevel@tonic-gate }
20277c478bd9Sstevel@tonic-gate if (warn && !spc_flag) {
20287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
20297c478bd9Sstevel@tonic-gate "Warning: %d sector(s) in last cylinder unallocated\n"),
20307c478bd9Sstevel@tonic-gate sblock.fs_spc - (uint32_t)(fssize_frag * NSPF(&sblock) -
20317c478bd9Sstevel@tonic-gate (uint64_t)(sblock.fs_ncyl - 1) * sblock.fs_spc));
20327c478bd9Sstevel@tonic-gate }
20337c478bd9Sstevel@tonic-gate /*
20347c478bd9Sstevel@tonic-gate * fill in remaining fields of the super block
20357c478bd9Sstevel@tonic-gate */
20367c478bd9Sstevel@tonic-gate
20377c478bd9Sstevel@tonic-gate /*
20387c478bd9Sstevel@tonic-gate * The csum records are stored in cylinder group 0, starting at
20397c478bd9Sstevel@tonic-gate * cgdmin, the first data block.
20407c478bd9Sstevel@tonic-gate */
20417c478bd9Sstevel@tonic-gate sblock.fs_csaddr = cgdmin(&sblock, 0);
20427c478bd9Sstevel@tonic-gate sblock.fs_cssize =
20437c478bd9Sstevel@tonic-gate fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum));
20447c478bd9Sstevel@tonic-gate i = sblock.fs_bsize / sizeof (struct csum);
20457c478bd9Sstevel@tonic-gate sblock.fs_csmask = ~(i - 1);
20467c478bd9Sstevel@tonic-gate for (sblock.fs_csshift = 0; i > 1; i >>= 1)
20477c478bd9Sstevel@tonic-gate sblock.fs_csshift++;
20487c478bd9Sstevel@tonic-gate fscs = (struct csum *)calloc(1, sblock.fs_cssize);
20497c478bd9Sstevel@tonic-gate
20507c478bd9Sstevel@tonic-gate checksummarysize();
20517c478bd9Sstevel@tonic-gate if (mtb == 'y') {
20527c478bd9Sstevel@tonic-gate sblock.fs_magic = MTB_UFS_MAGIC;
20537c478bd9Sstevel@tonic-gate sblock.fs_version = MTB_UFS_VERSION_1;
20547c478bd9Sstevel@tonic-gate } else {
20557c478bd9Sstevel@tonic-gate sblock.fs_magic = FS_MAGIC;
20566451fdbcSvsakar if (use_efi_dflts)
20576451fdbcSvsakar sblock.fs_version = UFS_EFISTYLE4NONEFI_VERSION_2;
20586451fdbcSvsakar else
20596451fdbcSvsakar sblock.fs_version = UFS_VERSION_MIN;
20607c478bd9Sstevel@tonic-gate }
20617c478bd9Sstevel@tonic-gate
20627c478bd9Sstevel@tonic-gate if (grow) {
20637c478bd9Sstevel@tonic-gate bcopy((caddr_t)grow_fscs, (caddr_t)fscs, (int)grow_fs_cssize);
20647c478bd9Sstevel@tonic-gate extendsummaryinfo();
20657c478bd9Sstevel@tonic-gate goto grow40;
20667c478bd9Sstevel@tonic-gate }
20677c478bd9Sstevel@tonic-gate sblock.fs_rotdelay = rotdelay;
20687c478bd9Sstevel@tonic-gate sblock.fs_maxcontig = maxcontig;
20697c478bd9Sstevel@tonic-gate sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate sblock.fs_rps = rps;
20727c478bd9Sstevel@tonic-gate sblock.fs_cgrotor = 0;
20737c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_ndir = 0;
20747c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nbfree = 0;
20757c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nifree = 0;
20767c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nffree = 0;
20777c478bd9Sstevel@tonic-gate sblock.fs_fmod = 0;
20787c478bd9Sstevel@tonic-gate sblock.fs_ronly = 0;
20797c478bd9Sstevel@tonic-gate sblock.fs_time = mkfstime;
20807c478bd9Sstevel@tonic-gate sblock.fs_state = FSOKAY - sblock.fs_time;
20817c478bd9Sstevel@tonic-gate sblock.fs_clean = FSCLEAN;
20827c478bd9Sstevel@tonic-gate grow40:
20837c478bd9Sstevel@tonic-gate
20847c478bd9Sstevel@tonic-gate /*
2085355d6bb5Sswilcox * If all that's needed is a dump of the superblock we
2086355d6bb5Sswilcox * would use by default, we've got it now. So, splat it
2087355d6bb5Sswilcox * out and leave.
2088355d6bb5Sswilcox */
2089355d6bb5Sswilcox if (rflag) {
2090355d6bb5Sswilcox dump_sblock();
2091355d6bb5Sswilcox lockexit(0);
2092355d6bb5Sswilcox }
2093355d6bb5Sswilcox /*
20947c478bd9Sstevel@tonic-gate * Dump out summary information about file system.
20957c478bd9Sstevel@tonic-gate */
20967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
20977c478bd9Sstevel@tonic-gate "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"),
20987c478bd9Sstevel@tonic-gate fsys, (uint64_t)sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
20997c478bd9Sstevel@tonic-gate sblock.fs_ntrak, sblock.fs_nsect);
21007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
21017c478bd9Sstevel@tonic-gate "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"),
21027c478bd9Sstevel@tonic-gate (float)sblock.fs_size * sblock.fs_fsize / MB, sblock.fs_ncg,
21037c478bd9Sstevel@tonic-gate sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize / MB,
21047c478bd9Sstevel@tonic-gate sblock.fs_ipg);
21056451fdbcSvsakar
21066451fdbcSvsakar tmpbuf = calloc(sblock.fs_ncg / 50 + 500, 1);
21076451fdbcSvsakar if (tmpbuf == NULL) {
21086451fdbcSvsakar perror("calloc");
21096451fdbcSvsakar lockexit(32);
21106451fdbcSvsakar }
21116d24e334Svsakar if (cg_too_small) {
21126d24e334Svsakar (void) fprintf(stderr, gettext("File system creation failed. "
21136d24e334Svsakar "There is only one cylinder group and\nthat is "
21146d24e334Svsakar "not even big enough to hold the inodes.\n"));
21156d24e334Svsakar lockexit(32);
21166d24e334Svsakar }
21177c478bd9Sstevel@tonic-gate /*
21187c478bd9Sstevel@tonic-gate * Now build the cylinders group blocks and
21197c478bd9Sstevel@tonic-gate * then print out indices of cylinder groups.
21207c478bd9Sstevel@tonic-gate */
21216451fdbcSvsakar tprintf(gettext(
21227c478bd9Sstevel@tonic-gate "super-block backups (for fsck -F ufs -o b=#) at:\n"));
21237c478bd9Sstevel@tonic-gate for (width = cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) {
21247c478bd9Sstevel@tonic-gate if ((grow == 0) || (cylno >= grow_fs_ncg))
21257c478bd9Sstevel@tonic-gate initcg(cylno);
21267c478bd9Sstevel@tonic-gate num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
21276451fdbcSvsakar /*
21286451fdbcSvsakar * If Nflag and if the disk is larger than the CHSLIMIT,
21296451fdbcSvsakar * then sanity test the superblocks before reporting. If there
21306d24e334Svsakar * are too many superblocks which look insane, we have
21316d24e334Svsakar * to retry with alternate logic. If both methods have
21326d24e334Svsakar * failed, then our efforts to arrive at alternate
21336451fdbcSvsakar * superblocks failed, so complain and exit.
21346451fdbcSvsakar */
21356451fdbcSvsakar if (Nflag && retry) {
21366451fdbcSvsakar skip_this_sb = 0;
21376451fdbcSvsakar rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
21386451fdbcSvsakar ret = checksblock(altsblock, 1);
21396451fdbcSvsakar if (ret) {
21406451fdbcSvsakar skip_this_sb = 1;
21416451fdbcSvsakar invalid_sb_cnt++;
2142d50c8f90Svsakar dprintf(("DeBuG checksblock() failed - error :"
2143d50c8f90Svsakar " %d for sb : %llu invalid_sb_cnt : %d\n",
21446451fdbcSvsakar ret, num, invalid_sb_cnt));
21456451fdbcSvsakar } else {
21466451fdbcSvsakar /*
2147d50c8f90Svsakar * Though the superblock looks sane, verify if
2148d50c8f90Svsakar * the fs_version in the superblock and the
2149d50c8f90Svsakar * logic that we are using to arrive at the
2150d50c8f90Svsakar * superblocks match.
21516451fdbcSvsakar */
21526451fdbcSvsakar if (use_efi_dflts && altsblock.fs_version
21536451fdbcSvsakar != UFS_EFISTYLE4NONEFI_VERSION_2) {
21546451fdbcSvsakar skip_this_sb = 1;
21556451fdbcSvsakar invalid_sb_cnt++;
21566451fdbcSvsakar }
21576451fdbcSvsakar }
21586451fdbcSvsakar if (invalid_sb_cnt >= INVALIDSBLIMIT) {
21596451fdbcSvsakar if (retry > 1) {
21606451fdbcSvsakar (void) fprintf(stderr, gettext(
21616451fdbcSvsakar "Error determining alternate "
21626451fdbcSvsakar "superblock locations\n"));
21636451fdbcSvsakar free(tmpbuf);
21646451fdbcSvsakar lockexit(32);
21656451fdbcSvsakar }
21666451fdbcSvsakar retry++;
21676451fdbcSvsakar use_efi_dflts = !use_efi_dflts;
21686451fdbcSvsakar free(tmpbuf);
21696451fdbcSvsakar goto retry_alternate_logic;
21706451fdbcSvsakar }
21716451fdbcSvsakar if (skip_this_sb)
21726451fdbcSvsakar continue;
21736451fdbcSvsakar }
21747c478bd9Sstevel@tonic-gate (void) sprintf(pbuf, " %llu,", num);
21757c478bd9Sstevel@tonic-gate plen = strlen(pbuf);
21767c478bd9Sstevel@tonic-gate if ((width + plen) > (WIDTH - 1)) {
21777c478bd9Sstevel@tonic-gate width = plen;
21786451fdbcSvsakar tprintf("\n");
21797c478bd9Sstevel@tonic-gate } else {
21807c478bd9Sstevel@tonic-gate width += plen;
21817c478bd9Sstevel@tonic-gate }
21826451fdbcSvsakar if (Nflag && retry)
21836d24e334Svsakar (void) strncat(tmpbuf, pbuf, strlen(pbuf));
21846451fdbcSvsakar else
21857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", pbuf);
21867c478bd9Sstevel@tonic-gate }
21876451fdbcSvsakar tprintf("\n");
21887c478bd9Sstevel@tonic-gate
21897c478bd9Sstevel@tonic-gate remaining_cg = sblock.fs_ncg - cylno;
21907c478bd9Sstevel@tonic-gate
21917c478bd9Sstevel@tonic-gate /*
21927c478bd9Sstevel@tonic-gate * If there are more than 300 cylinder groups still to be
21937c478bd9Sstevel@tonic-gate * initialized, print a "." for every 50 cylinder groups.
21947c478bd9Sstevel@tonic-gate */
21957c478bd9Sstevel@tonic-gate if (remaining_cg > 300) {
21966451fdbcSvsakar tprintf(gettext("Initializing cylinder groups:\n"));
21977c478bd9Sstevel@tonic-gate do_dot = 1;
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate /*
22017c478bd9Sstevel@tonic-gate * Now initialize all cylinder groups between the first ten
22027c478bd9Sstevel@tonic-gate * and the last ten.
22037c478bd9Sstevel@tonic-gate *
22047c478bd9Sstevel@tonic-gate * If the number of cylinder groups was less than 10, all of the
22057c478bd9Sstevel@tonic-gate * cylinder group offsets would have printed in the last loop
22067c478bd9Sstevel@tonic-gate * and cylno will already be equal to sblock.fs_ncg and so this
22077c478bd9Sstevel@tonic-gate * loop will not be entered. If there are less than 20 cylinder
22087c478bd9Sstevel@tonic-gate * groups, cylno is already less than fs_ncg - 10, so this loop
22097c478bd9Sstevel@tonic-gate * won't be entered in that case either.
22107c478bd9Sstevel@tonic-gate */
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate i = 0;
22137c478bd9Sstevel@tonic-gate for (; cylno < sblock.fs_ncg - 10; cylno++) {
22147c478bd9Sstevel@tonic-gate if ((grow == 0) || (cylno >= grow_fs_ncg))
22157c478bd9Sstevel@tonic-gate initcg(cylno);
22167c478bd9Sstevel@tonic-gate if (do_dot && cylno % 50 == 0) {
22176451fdbcSvsakar tprintf(".");
22187c478bd9Sstevel@tonic-gate i++;
22197c478bd9Sstevel@tonic-gate if (i == WIDTH - 1) {
22206451fdbcSvsakar tprintf("\n");
22217c478bd9Sstevel@tonic-gate i = 0;
22227c478bd9Sstevel@tonic-gate }
22237c478bd9Sstevel@tonic-gate }
22247c478bd9Sstevel@tonic-gate }
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate /*
22277c478bd9Sstevel@tonic-gate * Now print the cylinder group offsets for the last 10
22287c478bd9Sstevel@tonic-gate * cylinder groups, if any are left.
22297c478bd9Sstevel@tonic-gate */
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate if (do_dot) {
22326451fdbcSvsakar tprintf(gettext(
22337c478bd9Sstevel@tonic-gate "\nsuper-block backups for last 10 cylinder groups at:\n"));
22347c478bd9Sstevel@tonic-gate }
22357c478bd9Sstevel@tonic-gate for (width = 0; cylno < sblock.fs_ncg; cylno++) {
22367c478bd9Sstevel@tonic-gate if ((grow == 0) || (cylno >= grow_fs_ncg))
22377c478bd9Sstevel@tonic-gate initcg(cylno);
22387c478bd9Sstevel@tonic-gate num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
22396451fdbcSvsakar if (Nflag && retry) {
22406451fdbcSvsakar skip_this_sb = 0;
22416451fdbcSvsakar rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
22426451fdbcSvsakar ret = checksblock(altsblock, 1);
22436451fdbcSvsakar if (ret) {
22446451fdbcSvsakar skip_this_sb = 1;
22456451fdbcSvsakar invalid_sb_cnt++;
2246d50c8f90Svsakar dprintf(("DeBuG checksblock() failed - error :"
2247d50c8f90Svsakar " %d for sb : %llu invalid_sb_cnt : %d\n",
22486451fdbcSvsakar ret, num, invalid_sb_cnt));
22496451fdbcSvsakar } else {
22506451fdbcSvsakar /*
2251d50c8f90Svsakar * Though the superblock looks sane, verify if
2252d50c8f90Svsakar * the fs_version in the superblock and the
2253d50c8f90Svsakar * logic that we are using to arrive at the
2254d50c8f90Svsakar * superblocks match.
22556451fdbcSvsakar */
22566451fdbcSvsakar if (use_efi_dflts && altsblock.fs_version
22576451fdbcSvsakar != UFS_EFISTYLE4NONEFI_VERSION_2) {
22586451fdbcSvsakar skip_this_sb = 1;
22596451fdbcSvsakar invalid_sb_cnt++;
22606451fdbcSvsakar }
22616451fdbcSvsakar }
22626451fdbcSvsakar if (invalid_sb_cnt >= INVALIDSBLIMIT) {
22636451fdbcSvsakar if (retry > 1) {
22646451fdbcSvsakar (void) fprintf(stderr, gettext(
22656451fdbcSvsakar "Error determining alternate "
22666451fdbcSvsakar "superblock locations\n"));
22676451fdbcSvsakar free(tmpbuf);
22686451fdbcSvsakar lockexit(32);
22696451fdbcSvsakar }
22706451fdbcSvsakar retry++;
22716451fdbcSvsakar use_efi_dflts = !use_efi_dflts;
22726451fdbcSvsakar free(tmpbuf);
22736451fdbcSvsakar goto retry_alternate_logic;
22746451fdbcSvsakar }
22756451fdbcSvsakar if (skip_this_sb)
22766451fdbcSvsakar continue;
22776451fdbcSvsakar }
22786451fdbcSvsakar /* Don't print ',' for the last superblock */
22796451fdbcSvsakar if (cylno == sblock.fs_ncg-1)
22806451fdbcSvsakar (void) sprintf(pbuf, " %llu", num);
22816451fdbcSvsakar else
22827c478bd9Sstevel@tonic-gate (void) sprintf(pbuf, " %llu,", num);
22837c478bd9Sstevel@tonic-gate plen = strlen(pbuf);
22847c478bd9Sstevel@tonic-gate if ((width + plen) > (WIDTH - 1)) {
22857c478bd9Sstevel@tonic-gate width = plen;
22866451fdbcSvsakar tprintf("\n");
22877c478bd9Sstevel@tonic-gate } else {
22887c478bd9Sstevel@tonic-gate width += plen;
22897c478bd9Sstevel@tonic-gate }
22906451fdbcSvsakar if (Nflag && retry)
22916d24e334Svsakar (void) strncat(tmpbuf, pbuf, strlen(pbuf));
22926451fdbcSvsakar else
22937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", pbuf);
22947c478bd9Sstevel@tonic-gate }
22956451fdbcSvsakar tprintf("\n");
22966451fdbcSvsakar if (Nflag) {
22976451fdbcSvsakar if (retry)
22986d24e334Svsakar (void) fprintf(stderr, "%s", tmpbuf);
22996451fdbcSvsakar free(tmpbuf);
23007c478bd9Sstevel@tonic-gate lockexit(0);
23016451fdbcSvsakar }
23026451fdbcSvsakar
23036451fdbcSvsakar free(tmpbuf);
23047c478bd9Sstevel@tonic-gate if (grow)
23057c478bd9Sstevel@tonic-gate goto grow50;
23067c478bd9Sstevel@tonic-gate
23077c478bd9Sstevel@tonic-gate /*
23087c478bd9Sstevel@tonic-gate * Now construct the initial file system,
23097c478bd9Sstevel@tonic-gate * then write out the super-block.
23107c478bd9Sstevel@tonic-gate */
23117c478bd9Sstevel@tonic-gate fsinit();
23127c478bd9Sstevel@tonic-gate grow50:
23137c478bd9Sstevel@tonic-gate /*
23147c478bd9Sstevel@tonic-gate * write the superblock and csum information
23157c478bd9Sstevel@tonic-gate */
23167c478bd9Sstevel@tonic-gate wtsb();
23177c478bd9Sstevel@tonic-gate
23187c478bd9Sstevel@tonic-gate /*
23197c478bd9Sstevel@tonic-gate * extend the last cylinder group in the original file system
23207c478bd9Sstevel@tonic-gate */
23217c478bd9Sstevel@tonic-gate if (grow) {
23227c478bd9Sstevel@tonic-gate extendcg(grow_fs_ncg-1);
23237c478bd9Sstevel@tonic-gate wtsb();
23247c478bd9Sstevel@tonic-gate }
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate /*
23277c478bd9Sstevel@tonic-gate * Write out the duplicate super blocks to the first 10
23287c478bd9Sstevel@tonic-gate * cylinder groups (or fewer, if there are fewer than 10
23297c478bd9Sstevel@tonic-gate * cylinder groups).
23307c478bd9Sstevel@tonic-gate */
23317c478bd9Sstevel@tonic-gate for (cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++)
23327c478bd9Sstevel@tonic-gate awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
23337c478bd9Sstevel@tonic-gate (int)sbsize, (char *)&sblock, SAVE);
23347c478bd9Sstevel@tonic-gate
23357c478bd9Sstevel@tonic-gate /*
23367c478bd9Sstevel@tonic-gate * Now write out duplicate super blocks to the remaining
23377c478bd9Sstevel@tonic-gate * cylinder groups. In the case of multi-terabyte file
23387c478bd9Sstevel@tonic-gate * systems, just write out the super block to the last ten
23397c478bd9Sstevel@tonic-gate * cylinder groups (or however many are left).
23407c478bd9Sstevel@tonic-gate */
23417c478bd9Sstevel@tonic-gate if (mtb == 'y') {
23427c478bd9Sstevel@tonic-gate if (sblock.fs_ncg <= 10)
23437c478bd9Sstevel@tonic-gate cylno = sblock.fs_ncg;
23447c478bd9Sstevel@tonic-gate else if (sblock.fs_ncg <= 20)
23457c478bd9Sstevel@tonic-gate cylno = 10;
23467c478bd9Sstevel@tonic-gate else
23477c478bd9Sstevel@tonic-gate cylno = sblock.fs_ncg - 10;
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate
23507c478bd9Sstevel@tonic-gate for (; cylno < sblock.fs_ncg; cylno++)
23517c478bd9Sstevel@tonic-gate awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
23527c478bd9Sstevel@tonic-gate (int)sbsize, (char *)&sblock, SAVE);
23537c478bd9Sstevel@tonic-gate
23547c478bd9Sstevel@tonic-gate /*
23557c478bd9Sstevel@tonic-gate * Flush out all the AIO writes we've done. It's not
23567c478bd9Sstevel@tonic-gate * necessary to do this explicitly, but it's the only
23577c478bd9Sstevel@tonic-gate * way to report any errors from those writes.
23587c478bd9Sstevel@tonic-gate */
23597c478bd9Sstevel@tonic-gate flush_writes();
23607c478bd9Sstevel@tonic-gate
23617c478bd9Sstevel@tonic-gate /*
23627c478bd9Sstevel@tonic-gate * set clean flag
23637c478bd9Sstevel@tonic-gate */
23647c478bd9Sstevel@tonic-gate if (grow)
23657c478bd9Sstevel@tonic-gate sblock.fs_clean = grow_fs_clean;
23667c478bd9Sstevel@tonic-gate else
23677c478bd9Sstevel@tonic-gate sblock.fs_clean = FSCLEAN;
23687c478bd9Sstevel@tonic-gate sblock.fs_time = mkfstime;
23697c478bd9Sstevel@tonic-gate sblock.fs_state = FSOKAY - sblock.fs_time;
23707c478bd9Sstevel@tonic-gate wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
23717c478bd9Sstevel@tonic-gate isbad = 0;
23727c478bd9Sstevel@tonic-gate
23737c478bd9Sstevel@tonic-gate if (fsync(fso) == -1) {
23747c478bd9Sstevel@tonic-gate saverr = errno;
23757c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
23767c478bd9Sstevel@tonic-gate gettext("mkfs: fsync failed on write disk: %s\n"),
23777c478bd9Sstevel@tonic-gate strerror(saverr));
23787c478bd9Sstevel@tonic-gate /* we're just cleaning up, so keep going */
23797c478bd9Sstevel@tonic-gate }
23807c478bd9Sstevel@tonic-gate if (close(fsi) == -1) {
23817c478bd9Sstevel@tonic-gate saverr = errno;
23827c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
23837c478bd9Sstevel@tonic-gate gettext("mkfs: close failed on read disk: %s\n"),
23847c478bd9Sstevel@tonic-gate strerror(saverr));
23857c478bd9Sstevel@tonic-gate /* we're just cleaning up, so keep going */
23867c478bd9Sstevel@tonic-gate }
23877c478bd9Sstevel@tonic-gate if (close(fso) == -1) {
23887c478bd9Sstevel@tonic-gate saverr = errno;
23897c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
23907c478bd9Sstevel@tonic-gate gettext("mkfs: close failed on write disk: %s\n"),
23917c478bd9Sstevel@tonic-gate strerror(saverr));
23927c478bd9Sstevel@tonic-gate /* we're just cleaning up, so keep going */
23937c478bd9Sstevel@tonic-gate }
23947c478bd9Sstevel@tonic-gate fsi = fso = -1;
2395029b4de8Sswilcox
23967c478bd9Sstevel@tonic-gate #ifndef STANDALONE
23977c478bd9Sstevel@tonic-gate lockexit(0);
23987c478bd9Sstevel@tonic-gate #endif
2399029b4de8Sswilcox
2400029b4de8Sswilcox return (0);
24017c478bd9Sstevel@tonic-gate }
24027c478bd9Sstevel@tonic-gate
24037c478bd9Sstevel@tonic-gate /*
24047c478bd9Sstevel@tonic-gate * Figure out how big the partition we're dealing with is.
24057c478bd9Sstevel@tonic-gate * The value returned is in disk blocks (sectors);
24067c478bd9Sstevel@tonic-gate */
24077c478bd9Sstevel@tonic-gate static diskaddr_t
get_max_size(int fd)24087c478bd9Sstevel@tonic-gate get_max_size(int fd)
24097c478bd9Sstevel@tonic-gate {
2410342440ecSPrasad Singamsetty struct extvtoc vtoc;
24117c478bd9Sstevel@tonic-gate dk_gpt_t *efi_vtoc;
24127c478bd9Sstevel@tonic-gate diskaddr_t slicesize;
24137c478bd9Sstevel@tonic-gate
2414342440ecSPrasad Singamsetty int index = read_extvtoc(fd, &vtoc);
24157c478bd9Sstevel@tonic-gate
24166451fdbcSvsakar if (index >= 0) {
24176451fdbcSvsakar label_type = LABEL_TYPE_VTOC;
24186451fdbcSvsakar } else {
24197c478bd9Sstevel@tonic-gate if (index == VT_ENOTSUP || index == VT_ERROR) {
24207c478bd9Sstevel@tonic-gate /* it might be an EFI label */
24217c478bd9Sstevel@tonic-gate index = efi_alloc_and_read(fd, &efi_vtoc);
24226451fdbcSvsakar label_type = LABEL_TYPE_EFI;
24237c478bd9Sstevel@tonic-gate }
24247c478bd9Sstevel@tonic-gate }
24257c478bd9Sstevel@tonic-gate
24267c478bd9Sstevel@tonic-gate if (index < 0) {
24277c478bd9Sstevel@tonic-gate switch (index) {
24287c478bd9Sstevel@tonic-gate case VT_ERROR:
24297c478bd9Sstevel@tonic-gate break;
24307c478bd9Sstevel@tonic-gate case VT_EIO:
24317c478bd9Sstevel@tonic-gate errno = EIO;
24327c478bd9Sstevel@tonic-gate break;
24337c478bd9Sstevel@tonic-gate case VT_EINVAL:
24347c478bd9Sstevel@tonic-gate errno = EINVAL;
24357c478bd9Sstevel@tonic-gate }
24367c478bd9Sstevel@tonic-gate perror(gettext("Can not determine partition size"));
24377c478bd9Sstevel@tonic-gate lockexit(32);
24387c478bd9Sstevel@tonic-gate }
24397c478bd9Sstevel@tonic-gate
24406451fdbcSvsakar if (label_type == LABEL_TYPE_EFI) {
24417c478bd9Sstevel@tonic-gate slicesize = efi_vtoc->efi_parts[index].p_size;
24427c478bd9Sstevel@tonic-gate efi_free(efi_vtoc);
24437c478bd9Sstevel@tonic-gate } else {
24447c478bd9Sstevel@tonic-gate /*
24457c478bd9Sstevel@tonic-gate * In the vtoc struct, p_size is a 32-bit signed quantity.
24467c478bd9Sstevel@tonic-gate * In the dk_gpt struct (efi's version of the vtoc), p_size
24477c478bd9Sstevel@tonic-gate * is an unsigned 64-bit quantity. By casting the vtoc's
24487c478bd9Sstevel@tonic-gate * psize to an unsigned 32-bit quantity, it will be copied
24497c478bd9Sstevel@tonic-gate * to 'slicesize' (an unsigned 64-bit diskaddr_t) without
24507c478bd9Sstevel@tonic-gate * sign extension.
24517c478bd9Sstevel@tonic-gate */
24527c478bd9Sstevel@tonic-gate
24537c478bd9Sstevel@tonic-gate slicesize = (uint32_t)vtoc.v_part[index].p_size;
24547c478bd9Sstevel@tonic-gate }
24557c478bd9Sstevel@tonic-gate
24566451fdbcSvsakar dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n",
24576451fdbcSvsakar index, slicesize, (slicesize > FS_MAX)));
24587c478bd9Sstevel@tonic-gate
24597c478bd9Sstevel@tonic-gate /*
24607c478bd9Sstevel@tonic-gate * The next line limits a UFS file system to the maximum
24617c478bd9Sstevel@tonic-gate * supported size.
24627c478bd9Sstevel@tonic-gate */
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate if (slicesize > FS_MAX)
24657c478bd9Sstevel@tonic-gate return (FS_MAX);
24667c478bd9Sstevel@tonic-gate return (slicesize);
24677c478bd9Sstevel@tonic-gate }
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate static long
get_max_track_size(int fd)24707c478bd9Sstevel@tonic-gate get_max_track_size(int fd)
24717c478bd9Sstevel@tonic-gate {
24727c478bd9Sstevel@tonic-gate struct dk_cinfo ci;
24737c478bd9Sstevel@tonic-gate long track_size = -1;
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &ci) == 0) {
24767c478bd9Sstevel@tonic-gate track_size = ci.dki_maxtransfer * DEV_BSIZE;
24777c478bd9Sstevel@tonic-gate }
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate if ((track_size < 0)) {
24807c478bd9Sstevel@tonic-gate int error = 0;
24817c478bd9Sstevel@tonic-gate int maxphys;
24827c478bd9Sstevel@tonic-gate int gotit = 0;
24837c478bd9Sstevel@tonic-gate
24847c478bd9Sstevel@tonic-gate gotit = fsgetmaxphys(&maxphys, &error);
24857c478bd9Sstevel@tonic-gate if (gotit) {
24867c478bd9Sstevel@tonic-gate track_size = MIN(MB, maxphys);
24877c478bd9Sstevel@tonic-gate } else {
24887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
24897c478bd9Sstevel@tonic-gate "Warning: Could not get system value for maxphys. The value for\n"
24907c478bd9Sstevel@tonic-gate "maxcontig will default to 1MB.\n"));
24917c478bd9Sstevel@tonic-gate track_size = MB;
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate return (track_size);
24957c478bd9Sstevel@tonic-gate }
24967c478bd9Sstevel@tonic-gate
24977c478bd9Sstevel@tonic-gate /*
24987c478bd9Sstevel@tonic-gate * Initialize a cylinder group.
24997c478bd9Sstevel@tonic-gate */
25007c478bd9Sstevel@tonic-gate static void
initcg(int cylno)25017c478bd9Sstevel@tonic-gate initcg(int cylno)
25027c478bd9Sstevel@tonic-gate {
25037c478bd9Sstevel@tonic-gate diskaddr_t cbase, d;
25047c478bd9Sstevel@tonic-gate diskaddr_t dlower; /* last data block before cg metadata */
25057c478bd9Sstevel@tonic-gate diskaddr_t dupper; /* first data block after cg metadata */
25067c478bd9Sstevel@tonic-gate diskaddr_t dmax;
25077c478bd9Sstevel@tonic-gate int64_t i;
25087c478bd9Sstevel@tonic-gate struct csum *cs;
25097c478bd9Sstevel@tonic-gate struct dinode *inode_buffer;
25107c478bd9Sstevel@tonic-gate int size;
25117c478bd9Sstevel@tonic-gate
25127c478bd9Sstevel@tonic-gate /*
25137c478bd9Sstevel@tonic-gate * Variables used to store intermediate results as a part of
25147c478bd9Sstevel@tonic-gate * the internal implementation of the cbtocylno() macros.
25157c478bd9Sstevel@tonic-gate */
25167c478bd9Sstevel@tonic-gate diskaddr_t bno; /* UFS block number (not sector number) */
25177c478bd9Sstevel@tonic-gate int cbcylno; /* current cylinder number */
25187c478bd9Sstevel@tonic-gate int cbcylno_sect; /* sector offset within cylinder */
25197c478bd9Sstevel@tonic-gate int cbsect_incr; /* amount to increment sector offset */
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate /*
25227c478bd9Sstevel@tonic-gate * Variables used to store intermediate results as a part of
25237c478bd9Sstevel@tonic-gate * the internal implementation of the cbtorpos() macros.
25247c478bd9Sstevel@tonic-gate */
25257c478bd9Sstevel@tonic-gate short *cgblks; /* pointer to array of free blocks in cg */
25267c478bd9Sstevel@tonic-gate int trackrpos; /* tmp variable for rotation position */
25277c478bd9Sstevel@tonic-gate int trackoff; /* offset within a track */
25287c478bd9Sstevel@tonic-gate int trackoff_incr; /* amount to increment trackoff */
25297c478bd9Sstevel@tonic-gate int rpos; /* rotation position of current block */
25307c478bd9Sstevel@tonic-gate int rpos_incr; /* amount to increment rpos per block */
25317c478bd9Sstevel@tonic-gate
25327c478bd9Sstevel@tonic-gate union cgun *icgun; /* local pointer to a cg summary block */
25337c478bd9Sstevel@tonic-gate #define icg (icgun->cg)
25347c478bd9Sstevel@tonic-gate
25357c478bd9Sstevel@tonic-gate icgun = (union cgun *)getbuf(&cgsumbuf, sizeof (union cgun));
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate /*
25387c478bd9Sstevel@tonic-gate * Determine block bounds for cylinder group.
25397c478bd9Sstevel@tonic-gate * Allow space for super block summary information in first
25407c478bd9Sstevel@tonic-gate * cylinder group.
25417c478bd9Sstevel@tonic-gate */
25427c478bd9Sstevel@tonic-gate cbase = cgbase(&sblock, cylno);
25437c478bd9Sstevel@tonic-gate dmax = cbase + sblock.fs_fpg;
25447c478bd9Sstevel@tonic-gate if (dmax > sblock.fs_size) /* last cg may be smaller than normal */
25457c478bd9Sstevel@tonic-gate dmax = sblock.fs_size;
25467c478bd9Sstevel@tonic-gate dlower = cgsblock(&sblock, cylno) - cbase;
25477c478bd9Sstevel@tonic-gate dupper = cgdmin(&sblock, cylno) - cbase;
25487c478bd9Sstevel@tonic-gate if (cylno == 0)
25497c478bd9Sstevel@tonic-gate dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
25507c478bd9Sstevel@tonic-gate cs = fscs + cylno;
25517c478bd9Sstevel@tonic-gate icg.cg_time = mkfstime;
25527c478bd9Sstevel@tonic-gate icg.cg_magic = CG_MAGIC;
25537c478bd9Sstevel@tonic-gate icg.cg_cgx = cylno;
2554355d6bb5Sswilcox /* last one gets whatever's left */
25557c478bd9Sstevel@tonic-gate if (cylno == sblock.fs_ncg - 1)
2556355d6bb5Sswilcox icg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
25577c478bd9Sstevel@tonic-gate else
25587c478bd9Sstevel@tonic-gate icg.cg_ncyl = sblock.fs_cpg;
25597c478bd9Sstevel@tonic-gate icg.cg_niblk = sblock.fs_ipg;
25607c478bd9Sstevel@tonic-gate icg.cg_ndblk = dmax - cbase;
25617c478bd9Sstevel@tonic-gate icg.cg_cs.cs_ndir = 0;
25627c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nffree = 0;
25637c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nbfree = 0;
25647c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nifree = 0;
25657c478bd9Sstevel@tonic-gate icg.cg_rotor = 0;
25667c478bd9Sstevel@tonic-gate icg.cg_frotor = 0;
25677c478bd9Sstevel@tonic-gate icg.cg_irotor = 0;
25687c478bd9Sstevel@tonic-gate icg.cg_btotoff = &icg.cg_space[0] - (uchar_t *)(&icg.cg_link);
25697c478bd9Sstevel@tonic-gate icg.cg_boff = icg.cg_btotoff + sblock.fs_cpg * sizeof (long);
25707c478bd9Sstevel@tonic-gate icg.cg_iusedoff = icg.cg_boff +
25717c478bd9Sstevel@tonic-gate sblock.fs_cpg * sblock.fs_nrpos * sizeof (short);
25727c478bd9Sstevel@tonic-gate icg.cg_freeoff = icg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
25737c478bd9Sstevel@tonic-gate icg.cg_nextfreeoff = icg.cg_freeoff +
25747c478bd9Sstevel@tonic-gate howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
25757c478bd9Sstevel@tonic-gate for (i = 0; i < sblock.fs_frag; i++) {
25767c478bd9Sstevel@tonic-gate icg.cg_frsum[i] = 0;
25777c478bd9Sstevel@tonic-gate }
25787c478bd9Sstevel@tonic-gate bzero((caddr_t)cg_inosused(&icg), icg.cg_freeoff - icg.cg_iusedoff);
25797c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nifree += sblock.fs_ipg;
25807c478bd9Sstevel@tonic-gate if (cylno == 0)
25817c478bd9Sstevel@tonic-gate for (i = 0; i < UFSROOTINO; i++) {
25827c478bd9Sstevel@tonic-gate setbit(cg_inosused(&icg), i);
25837c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nifree--;
25847c478bd9Sstevel@tonic-gate }
25857c478bd9Sstevel@tonic-gate
25867c478bd9Sstevel@tonic-gate /*
25877c478bd9Sstevel@tonic-gate * Initialize all the inodes in the cylinder group using
25887c478bd9Sstevel@tonic-gate * random numbers.
25897c478bd9Sstevel@tonic-gate */
25907c478bd9Sstevel@tonic-gate size = sblock.fs_ipg * sizeof (struct dinode);
25917c478bd9Sstevel@tonic-gate inode_buffer = (struct dinode *)getbuf(&inodebuf, size);
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate for (i = 0; i < sblock.fs_ipg; i++) {
25947c478bd9Sstevel@tonic-gate IRANDOMIZE(&(inode_buffer[i].di_ic));
25957c478bd9Sstevel@tonic-gate }
25967c478bd9Sstevel@tonic-gate
25977c478bd9Sstevel@tonic-gate /*
25987c478bd9Sstevel@tonic-gate * Write all inodes in a single write for performance.
25997c478bd9Sstevel@tonic-gate */
26007c478bd9Sstevel@tonic-gate awtfs(fsbtodb(&sblock, (uint64_t)cgimin(&sblock, cylno)), (int)size,
26017c478bd9Sstevel@tonic-gate (char *)inode_buffer, RELEASE);
26027c478bd9Sstevel@tonic-gate
26037c478bd9Sstevel@tonic-gate bzero((caddr_t)cg_blktot(&icg), icg.cg_boff - icg.cg_btotoff);
26047c478bd9Sstevel@tonic-gate bzero((caddr_t)cg_blks(&sblock, &icg, 0),
26057c478bd9Sstevel@tonic-gate icg.cg_iusedoff - icg.cg_boff);
26067c478bd9Sstevel@tonic-gate bzero((caddr_t)cg_blksfree(&icg), icg.cg_nextfreeoff - icg.cg_freeoff);
26077c478bd9Sstevel@tonic-gate
26087c478bd9Sstevel@tonic-gate if (cylno > 0) {
26097c478bd9Sstevel@tonic-gate for (d = 0; d < dlower; d += sblock.fs_frag) {
26107c478bd9Sstevel@tonic-gate setblock(&sblock, cg_blksfree(&icg), d/sblock.fs_frag);
26117c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nbfree++;
26127c478bd9Sstevel@tonic-gate cg_blktot(&icg)[cbtocylno(&sblock, d)]++;
26137c478bd9Sstevel@tonic-gate cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
26147c478bd9Sstevel@tonic-gate [cbtorpos(&sblock, d)]++;
26157c478bd9Sstevel@tonic-gate }
26167c478bd9Sstevel@tonic-gate sblock.fs_dsize += dlower;
26177c478bd9Sstevel@tonic-gate }
26187c478bd9Sstevel@tonic-gate sblock.fs_dsize += icg.cg_ndblk - dupper;
26197c478bd9Sstevel@tonic-gate if ((i = dupper % sblock.fs_frag) != 0) {
26207c478bd9Sstevel@tonic-gate icg.cg_frsum[sblock.fs_frag - i]++;
26217c478bd9Sstevel@tonic-gate for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
26227c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&icg), dupper);
26237c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nffree++;
26247c478bd9Sstevel@tonic-gate }
26257c478bd9Sstevel@tonic-gate }
26267c478bd9Sstevel@tonic-gate
26277c478bd9Sstevel@tonic-gate /*
26287c478bd9Sstevel@tonic-gate * WARNING: The following code is somewhat confusing, but
26297c478bd9Sstevel@tonic-gate * results in a substantial performance improvement in mkfs.
26307c478bd9Sstevel@tonic-gate *
26317c478bd9Sstevel@tonic-gate * Instead of using cbtocylno() and cbtorpos() macros, we
26327c478bd9Sstevel@tonic-gate * keep track of all the intermediate state of those macros
26337c478bd9Sstevel@tonic-gate * in some variables. This allows simple addition to be
26347c478bd9Sstevel@tonic-gate * done to calculate the results as we step through the
26357c478bd9Sstevel@tonic-gate * blocks in an orderly fashion instead of the slower
26367c478bd9Sstevel@tonic-gate * multiplication and division the macros are forced to
26377c478bd9Sstevel@tonic-gate * used so they can support random input. (Multiplication,
26387c478bd9Sstevel@tonic-gate * division, and remainder operations typically take about
26397c478bd9Sstevel@tonic-gate * 10x as many processor cycles as other operations.)
26407c478bd9Sstevel@tonic-gate *
26417c478bd9Sstevel@tonic-gate * The basic idea is to take code:
26427c478bd9Sstevel@tonic-gate *
26437c478bd9Sstevel@tonic-gate * for (x = starting_x; x < max; x++)
26447c478bd9Sstevel@tonic-gate * y = (x * c) / z
26457c478bd9Sstevel@tonic-gate *
26467c478bd9Sstevel@tonic-gate * and rewrite it to take advantage of the fact that
26477c478bd9Sstevel@tonic-gate * the variable x is incrementing in an orderly way:
26487c478bd9Sstevel@tonic-gate *
26497c478bd9Sstevel@tonic-gate * intermediate = starting_x * c
26507c478bd9Sstevel@tonic-gate * yval = intermediate / z
26517c478bd9Sstevel@tonic-gate * for (x = starting_x; x < max; x++) {
26527c478bd9Sstevel@tonic-gate * y = yval;
26537c478bd9Sstevel@tonic-gate * intermediate += c
26547c478bd9Sstevel@tonic-gate * if (intermediate > z) {
26557c478bd9Sstevel@tonic-gate * yval++;
26567c478bd9Sstevel@tonic-gate * intermediate -= z
26577c478bd9Sstevel@tonic-gate * }
26587c478bd9Sstevel@tonic-gate * }
26597c478bd9Sstevel@tonic-gate *
26607c478bd9Sstevel@tonic-gate * Performance has improved as much as 4X using this code.
26617c478bd9Sstevel@tonic-gate */
26627c478bd9Sstevel@tonic-gate
26637c478bd9Sstevel@tonic-gate /*
26647c478bd9Sstevel@tonic-gate * Initialize the starting points for all the cbtocylno()
26657c478bd9Sstevel@tonic-gate * macro variables and figure out the increments needed each
26667c478bd9Sstevel@tonic-gate * time through the loop.
26677c478bd9Sstevel@tonic-gate */
26687c478bd9Sstevel@tonic-gate cbcylno_sect = dupper * NSPF(&sblock);
26697c478bd9Sstevel@tonic-gate cbsect_incr = sblock.fs_frag * NSPF(&sblock);
26707c478bd9Sstevel@tonic-gate cbcylno = cbcylno_sect / sblock.fs_spc;
26717c478bd9Sstevel@tonic-gate cbcylno_sect %= sblock.fs_spc;
26727c478bd9Sstevel@tonic-gate cgblks = cg_blks(&sblock, &icg, cbcylno);
26737c478bd9Sstevel@tonic-gate bno = dupper / sblock.fs_frag;
26747c478bd9Sstevel@tonic-gate
26757c478bd9Sstevel@tonic-gate /*
26767c478bd9Sstevel@tonic-gate * Initialize the starting points for all the cbtorpos()
26777c478bd9Sstevel@tonic-gate * macro variables and figure out the increments needed each
26787c478bd9Sstevel@tonic-gate * time through the loop.
26797c478bd9Sstevel@tonic-gate *
26807c478bd9Sstevel@tonic-gate * It's harder to simplify the cbtorpos() macro if there were
26817c478bd9Sstevel@tonic-gate * alternate sectors specified (or if they previously existed
26827c478bd9Sstevel@tonic-gate * in the growfs case). Since this is rare, we just revert to
26837c478bd9Sstevel@tonic-gate * using the macros in this case and skip the variable setup.
26847c478bd9Sstevel@tonic-gate */
26857c478bd9Sstevel@tonic-gate if (!spc_flag) {
26867c478bd9Sstevel@tonic-gate trackrpos = (cbcylno_sect % sblock.fs_nsect) * sblock.fs_nrpos;
26877c478bd9Sstevel@tonic-gate rpos = trackrpos / sblock.fs_nsect;
26887c478bd9Sstevel@tonic-gate trackoff = trackrpos % sblock.fs_nsect;
26897c478bd9Sstevel@tonic-gate trackoff_incr = cbsect_incr * sblock.fs_nrpos;
26907c478bd9Sstevel@tonic-gate rpos_incr = (trackoff_incr / sblock.fs_nsect) % sblock.fs_nrpos;
26917c478bd9Sstevel@tonic-gate trackoff_incr = trackoff_incr % sblock.fs_nsect;
26927c478bd9Sstevel@tonic-gate }
26937c478bd9Sstevel@tonic-gate
26947c478bd9Sstevel@tonic-gate /*
26957c478bd9Sstevel@tonic-gate * Loop through all the blocks, marking them free and
26967c478bd9Sstevel@tonic-gate * updating totals kept in the superblock and cg summary.
26977c478bd9Sstevel@tonic-gate */
26987c478bd9Sstevel@tonic-gate for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
26997c478bd9Sstevel@tonic-gate setblock(&sblock, cg_blksfree(&icg), bno);
27007c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nbfree++;
27017c478bd9Sstevel@tonic-gate
27027c478bd9Sstevel@tonic-gate cg_blktot(&icg)[cbcylno]++;
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate if (!spc_flag)
27057c478bd9Sstevel@tonic-gate cgblks[rpos]++;
27067c478bd9Sstevel@tonic-gate else
27077c478bd9Sstevel@tonic-gate cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
27087c478bd9Sstevel@tonic-gate [cbtorpos(&sblock, d)]++;
27097c478bd9Sstevel@tonic-gate
27107c478bd9Sstevel@tonic-gate d += sblock.fs_frag;
27117c478bd9Sstevel@tonic-gate bno++;
27127c478bd9Sstevel@tonic-gate
27137c478bd9Sstevel@tonic-gate /*
27147c478bd9Sstevel@tonic-gate * Increment the sector offset within the cylinder
27157c478bd9Sstevel@tonic-gate * for the cbtocylno() macro reimplementation. If
27167c478bd9Sstevel@tonic-gate * we're beyond the end of the cylinder, update the
27177c478bd9Sstevel@tonic-gate * cylinder number, calculate the offset in the
27187c478bd9Sstevel@tonic-gate * new cylinder, and update the cgblks pointer
27197c478bd9Sstevel@tonic-gate * to the next rotational position.
27207c478bd9Sstevel@tonic-gate */
27217c478bd9Sstevel@tonic-gate cbcylno_sect += cbsect_incr;
27227c478bd9Sstevel@tonic-gate if (cbcylno_sect >= sblock.fs_spc) {
27237c478bd9Sstevel@tonic-gate cbcylno++;
27247c478bd9Sstevel@tonic-gate cbcylno_sect -= sblock.fs_spc;
27257c478bd9Sstevel@tonic-gate cgblks += sblock.fs_nrpos;
27267c478bd9Sstevel@tonic-gate }
27277c478bd9Sstevel@tonic-gate
27287c478bd9Sstevel@tonic-gate /*
27297c478bd9Sstevel@tonic-gate * If there aren't alternate sectors, increment the
27307c478bd9Sstevel@tonic-gate * rotational position variables for the cbtorpos()
27317c478bd9Sstevel@tonic-gate * reimplementation. Note that we potentially
27327c478bd9Sstevel@tonic-gate * increment rpos twice. Once by rpos_incr, and one
27337c478bd9Sstevel@tonic-gate * more time when we wrap to a new track because
27347c478bd9Sstevel@tonic-gate * trackoff >= fs_nsect.
27357c478bd9Sstevel@tonic-gate */
27367c478bd9Sstevel@tonic-gate if (!spc_flag) {
27377c478bd9Sstevel@tonic-gate trackoff += trackoff_incr;
27387c478bd9Sstevel@tonic-gate rpos += rpos_incr;
27397c478bd9Sstevel@tonic-gate if (trackoff >= sblock.fs_nsect) {
27407c478bd9Sstevel@tonic-gate trackoff -= sblock.fs_nsect;
27417c478bd9Sstevel@tonic-gate rpos++;
27427c478bd9Sstevel@tonic-gate }
27437c478bd9Sstevel@tonic-gate if (rpos >= sblock.fs_nrpos)
27447c478bd9Sstevel@tonic-gate rpos -= sblock.fs_nrpos;
27457c478bd9Sstevel@tonic-gate }
27467c478bd9Sstevel@tonic-gate }
27477c478bd9Sstevel@tonic-gate
27487c478bd9Sstevel@tonic-gate if (d < dmax - cbase) {
27497c478bd9Sstevel@tonic-gate icg.cg_frsum[dmax - cbase - d]++;
27507c478bd9Sstevel@tonic-gate for (; d < dmax - cbase; d++) {
27517c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&icg), d);
27527c478bd9Sstevel@tonic-gate icg.cg_cs.cs_nffree++;
27537c478bd9Sstevel@tonic-gate }
27547c478bd9Sstevel@tonic-gate }
27557c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_ndir += icg.cg_cs.cs_ndir;
27567c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nffree += icg.cg_cs.cs_nffree;
27577c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nbfree += icg.cg_cs.cs_nbfree;
27587c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nifree += icg.cg_cs.cs_nifree;
27597c478bd9Sstevel@tonic-gate *cs = icg.cg_cs;
27607c478bd9Sstevel@tonic-gate awtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, cylno)),
27617c478bd9Sstevel@tonic-gate sblock.fs_bsize, (char *)&icg, RELEASE);
27627c478bd9Sstevel@tonic-gate }
27637c478bd9Sstevel@tonic-gate
27647c478bd9Sstevel@tonic-gate /*
27657c478bd9Sstevel@tonic-gate * initialize the file system
27667c478bd9Sstevel@tonic-gate */
27677c478bd9Sstevel@tonic-gate struct inode node;
27687c478bd9Sstevel@tonic-gate
27697c478bd9Sstevel@tonic-gate #define LOSTDIR
27707c478bd9Sstevel@tonic-gate #ifdef LOSTDIR
27717c478bd9Sstevel@tonic-gate #define PREDEFDIR 3
27727c478bd9Sstevel@tonic-gate #else
27737c478bd9Sstevel@tonic-gate #define PREDEFDIR 2
27747c478bd9Sstevel@tonic-gate #endif
27757c478bd9Sstevel@tonic-gate
27767c478bd9Sstevel@tonic-gate struct direct root_dir[] = {
27777c478bd9Sstevel@tonic-gate { UFSROOTINO, sizeof (struct direct), 1, "." },
27787c478bd9Sstevel@tonic-gate { UFSROOTINO, sizeof (struct direct), 2, ".." },
27797c478bd9Sstevel@tonic-gate #ifdef LOSTDIR
27807c478bd9Sstevel@tonic-gate { LOSTFOUNDINO, sizeof (struct direct), 10, "lost+found" },
27817c478bd9Sstevel@tonic-gate #endif
27827c478bd9Sstevel@tonic-gate };
27837c478bd9Sstevel@tonic-gate #ifdef LOSTDIR
27847c478bd9Sstevel@tonic-gate struct direct lost_found_dir[] = {
27857c478bd9Sstevel@tonic-gate { LOSTFOUNDINO, sizeof (struct direct), 1, "." },
27867c478bd9Sstevel@tonic-gate { UFSROOTINO, sizeof (struct direct), 2, ".." },
27877c478bd9Sstevel@tonic-gate { 0, DIRBLKSIZ, 0, 0 },
27887c478bd9Sstevel@tonic-gate };
27897c478bd9Sstevel@tonic-gate #endif
27907c478bd9Sstevel@tonic-gate char buf[MAXBSIZE];
27917c478bd9Sstevel@tonic-gate
27927c478bd9Sstevel@tonic-gate static void
fsinit()27937c478bd9Sstevel@tonic-gate fsinit()
27947c478bd9Sstevel@tonic-gate {
27957c478bd9Sstevel@tonic-gate int i;
27967c478bd9Sstevel@tonic-gate
27977c478bd9Sstevel@tonic-gate
27987c478bd9Sstevel@tonic-gate /*
27997c478bd9Sstevel@tonic-gate * initialize the node
28007c478bd9Sstevel@tonic-gate */
28017c478bd9Sstevel@tonic-gate node.i_atime = mkfstime;
28027c478bd9Sstevel@tonic-gate node.i_mtime = mkfstime;
28037c478bd9Sstevel@tonic-gate node.i_ctime = mkfstime;
28047c478bd9Sstevel@tonic-gate #ifdef LOSTDIR
28057c478bd9Sstevel@tonic-gate /*
28067c478bd9Sstevel@tonic-gate * create the lost+found directory
28077c478bd9Sstevel@tonic-gate */
28087c478bd9Sstevel@tonic-gate (void) makedir(lost_found_dir, 2);
28097c478bd9Sstevel@tonic-gate for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) {
28107c478bd9Sstevel@tonic-gate bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
28117c478bd9Sstevel@tonic-gate }
28127c478bd9Sstevel@tonic-gate node.i_number = LOSTFOUNDINO;
2813*6d24d8e5SRichard Lowe node.i_smode = IFDIR | 0700;
28147c478bd9Sstevel@tonic-gate node.i_nlink = 2;
28157c478bd9Sstevel@tonic-gate node.i_size = sblock.fs_bsize;
28167c478bd9Sstevel@tonic-gate node.i_db[0] = alloc((int)node.i_size, node.i_mode);
28177c478bd9Sstevel@tonic-gate node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
28187c478bd9Sstevel@tonic-gate IRANDOMIZE(&node.i_ic);
28197c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), (int)node.i_size, buf);
28207c478bd9Sstevel@tonic-gate iput(&node);
28217c478bd9Sstevel@tonic-gate #endif
28227c478bd9Sstevel@tonic-gate /*
28237c478bd9Sstevel@tonic-gate * create the root directory
28247c478bd9Sstevel@tonic-gate */
28257c478bd9Sstevel@tonic-gate node.i_number = UFSROOTINO;
2826*6d24d8e5SRichard Lowe node.i_mode = IFDIR | UMASK;
28277c478bd9Sstevel@tonic-gate node.i_nlink = PREDEFDIR;
28287c478bd9Sstevel@tonic-gate node.i_size = makedir(root_dir, PREDEFDIR);
28297c478bd9Sstevel@tonic-gate node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
28307c478bd9Sstevel@tonic-gate /* i_size < 2GB because we are initializing the file system */
28317c478bd9Sstevel@tonic-gate node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
28327c478bd9Sstevel@tonic-gate IRANDOMIZE(&node.i_ic);
28337c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), sblock.fs_fsize, buf);
28347c478bd9Sstevel@tonic-gate iput(&node);
28357c478bd9Sstevel@tonic-gate }
28367c478bd9Sstevel@tonic-gate
28377c478bd9Sstevel@tonic-gate /*
28387c478bd9Sstevel@tonic-gate * construct a set of directory entries in "buf".
28397c478bd9Sstevel@tonic-gate * return size of directory.
28407c478bd9Sstevel@tonic-gate */
28417c478bd9Sstevel@tonic-gate static int
makedir(struct direct * protodir,int entries)28427c478bd9Sstevel@tonic-gate makedir(struct direct *protodir, int entries)
28437c478bd9Sstevel@tonic-gate {
28447c478bd9Sstevel@tonic-gate char *cp;
28457c478bd9Sstevel@tonic-gate int i;
28467c478bd9Sstevel@tonic-gate ushort_t spcleft;
28477c478bd9Sstevel@tonic-gate
28487c478bd9Sstevel@tonic-gate spcleft = DIRBLKSIZ;
28497c478bd9Sstevel@tonic-gate for (cp = buf, i = 0; i < entries - 1; i++) {
28507c478bd9Sstevel@tonic-gate protodir[i].d_reclen = DIRSIZ(&protodir[i]);
28517c478bd9Sstevel@tonic-gate bcopy(&protodir[i], cp, protodir[i].d_reclen);
28527c478bd9Sstevel@tonic-gate cp += protodir[i].d_reclen;
28537c478bd9Sstevel@tonic-gate spcleft -= protodir[i].d_reclen;
28547c478bd9Sstevel@tonic-gate }
28557c478bd9Sstevel@tonic-gate protodir[i].d_reclen = spcleft;
28567c478bd9Sstevel@tonic-gate bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
28577c478bd9Sstevel@tonic-gate return (DIRBLKSIZ);
28587c478bd9Sstevel@tonic-gate }
28597c478bd9Sstevel@tonic-gate
28607c478bd9Sstevel@tonic-gate /*
28617c478bd9Sstevel@tonic-gate * allocate a block or frag
28627c478bd9Sstevel@tonic-gate */
28637c478bd9Sstevel@tonic-gate static daddr32_t
alloc(int size,int mode)28647c478bd9Sstevel@tonic-gate alloc(int size, int mode)
28657c478bd9Sstevel@tonic-gate {
28667c478bd9Sstevel@tonic-gate int i, frag;
28677c478bd9Sstevel@tonic-gate daddr32_t d;
28687c478bd9Sstevel@tonic-gate
28697c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
28707c478bd9Sstevel@tonic-gate (char *)&acg);
28717c478bd9Sstevel@tonic-gate if (acg.cg_magic != CG_MAGIC) {
28727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
28737c478bd9Sstevel@tonic-gate lockexit(32);
28747c478bd9Sstevel@tonic-gate }
28757c478bd9Sstevel@tonic-gate if (acg.cg_cs.cs_nbfree == 0) {
28767c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
28777c478bd9Sstevel@tonic-gate gettext("first cylinder group ran out of space\n"));
28787c478bd9Sstevel@tonic-gate lockexit(32);
28797c478bd9Sstevel@tonic-gate }
28807c478bd9Sstevel@tonic-gate for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
28817c478bd9Sstevel@tonic-gate if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
28827c478bd9Sstevel@tonic-gate goto goth;
28837c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
28847c478bd9Sstevel@tonic-gate gettext("internal error: can't find block in cyl 0\n"));
28857c478bd9Sstevel@tonic-gate lockexit(32);
28867c478bd9Sstevel@tonic-gate goth:
28877c478bd9Sstevel@tonic-gate clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
28887c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nbfree--;
28897c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nbfree--;
28907c478bd9Sstevel@tonic-gate fscs[0].cs_nbfree--;
28917c478bd9Sstevel@tonic-gate if (mode & IFDIR) {
28927c478bd9Sstevel@tonic-gate acg.cg_cs.cs_ndir++;
28937c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_ndir++;
28947c478bd9Sstevel@tonic-gate fscs[0].cs_ndir++;
28957c478bd9Sstevel@tonic-gate }
28967c478bd9Sstevel@tonic-gate cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
28977c478bd9Sstevel@tonic-gate cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
28987c478bd9Sstevel@tonic-gate if (size != sblock.fs_bsize) {
28997c478bd9Sstevel@tonic-gate frag = howmany(size, sblock.fs_fsize);
29007c478bd9Sstevel@tonic-gate fscs[0].cs_nffree += sblock.fs_frag - frag;
29017c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
29027c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
29037c478bd9Sstevel@tonic-gate acg.cg_frsum[sblock.fs_frag - frag]++;
29047c478bd9Sstevel@tonic-gate for (i = frag; i < sblock.fs_frag; i++)
29057c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&acg), d + i);
29067c478bd9Sstevel@tonic-gate }
29077c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
29087c478bd9Sstevel@tonic-gate (char *)&acg);
29097c478bd9Sstevel@tonic-gate return (d);
29107c478bd9Sstevel@tonic-gate }
29117c478bd9Sstevel@tonic-gate
29127c478bd9Sstevel@tonic-gate /*
29137c478bd9Sstevel@tonic-gate * Allocate an inode on the disk
29147c478bd9Sstevel@tonic-gate */
29157c478bd9Sstevel@tonic-gate static void
iput(struct inode * ip)29167c478bd9Sstevel@tonic-gate iput(struct inode *ip)
29177c478bd9Sstevel@tonic-gate {
29187c478bd9Sstevel@tonic-gate struct dinode buf[MAXINOPB];
29197c478bd9Sstevel@tonic-gate diskaddr_t d;
29207c478bd9Sstevel@tonic-gate
29217c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
29227c478bd9Sstevel@tonic-gate (char *)&acg);
29237c478bd9Sstevel@tonic-gate if (acg.cg_magic != CG_MAGIC) {
29247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
29257c478bd9Sstevel@tonic-gate lockexit(32);
29267c478bd9Sstevel@tonic-gate }
29277c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nifree--;
29287c478bd9Sstevel@tonic-gate setbit(cg_inosused(&acg), ip->i_number);
29297c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
29307c478bd9Sstevel@tonic-gate (char *)&acg);
29317c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nifree--;
29327c478bd9Sstevel@tonic-gate fscs[0].cs_nifree--;
29337c478bd9Sstevel@tonic-gate if ((int)ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
29347c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
29357c478bd9Sstevel@tonic-gate gettext("fsinit: inode value out of range (%d).\n"),
29367c478bd9Sstevel@tonic-gate ip->i_number);
29377c478bd9Sstevel@tonic-gate lockexit(32);
29387c478bd9Sstevel@tonic-gate }
29397c478bd9Sstevel@tonic-gate d = fsbtodb(&sblock, (uint64_t)itod(&sblock, (int)ip->i_number));
29407c478bd9Sstevel@tonic-gate rdfs(d, sblock.fs_bsize, (char *)buf);
29417c478bd9Sstevel@tonic-gate buf[itoo(&sblock, (int)ip->i_number)].di_ic = ip->i_ic;
29427c478bd9Sstevel@tonic-gate wtfs(d, sblock.fs_bsize, (char *)buf);
29437c478bd9Sstevel@tonic-gate }
29447c478bd9Sstevel@tonic-gate
29457c478bd9Sstevel@tonic-gate /*
29467c478bd9Sstevel@tonic-gate * getbuf() -- Get a buffer for use in an AIO operation. Buffer
29477c478bd9Sstevel@tonic-gate * is zero'd the first time returned, left with whatever
29487c478bd9Sstevel@tonic-gate * was in memory after that. This function actually gets
29497c478bd9Sstevel@tonic-gate * enough memory the first time it's called to support
29507c478bd9Sstevel@tonic-gate * MAXBUF buffers like a slab allocator. When all the
29517c478bd9Sstevel@tonic-gate * buffers are in use, it waits for an aio to complete
29527c478bd9Sstevel@tonic-gate * and make a buffer available.
29537c478bd9Sstevel@tonic-gate *
29547c478bd9Sstevel@tonic-gate * Never returns an error. Either succeeds or exits.
29557c478bd9Sstevel@tonic-gate */
29567c478bd9Sstevel@tonic-gate static char *
getbuf(bufhdr * bufhead,int size)29577c478bd9Sstevel@tonic-gate getbuf(bufhdr *bufhead, int size)
29587c478bd9Sstevel@tonic-gate {
29597c478bd9Sstevel@tonic-gate bufhdr *pbuf;
29607c478bd9Sstevel@tonic-gate bufhdr *prev;
29617c478bd9Sstevel@tonic-gate int i;
29627c478bd9Sstevel@tonic-gate int buf_size, max_bufs;
29637c478bd9Sstevel@tonic-gate
29647c478bd9Sstevel@tonic-gate /*
29657c478bd9Sstevel@tonic-gate * Initialize all the buffers
29667c478bd9Sstevel@tonic-gate */
29677c478bd9Sstevel@tonic-gate if (bufhead->head == NULL) {
29687c478bd9Sstevel@tonic-gate /*
29697c478bd9Sstevel@tonic-gate * round up the size of our buffer header to a
29707c478bd9Sstevel@tonic-gate * 16 byte boundary so the address we return to
29717c478bd9Sstevel@tonic-gate * the caller is "suitably aligned".
29727c478bd9Sstevel@tonic-gate */
29737c478bd9Sstevel@tonic-gate bufhdrsize = (sizeof (bufhdr) + 15) & ~15;
29747c478bd9Sstevel@tonic-gate
29757c478bd9Sstevel@tonic-gate /*
29767c478bd9Sstevel@tonic-gate * Add in our header to the buffer and round it all up to
29777c478bd9Sstevel@tonic-gate * a 16 byte boundry so each member of the slab is aligned.
29787c478bd9Sstevel@tonic-gate */
29797c478bd9Sstevel@tonic-gate buf_size = (size + bufhdrsize + 15) & ~15;
29807c478bd9Sstevel@tonic-gate
29817c478bd9Sstevel@tonic-gate /*
29827c478bd9Sstevel@tonic-gate * Limit number of buffers to lesser of MAXBUFMEM's worth
29837c478bd9Sstevel@tonic-gate * or MAXBUF, whichever is less.
29847c478bd9Sstevel@tonic-gate */
29857c478bd9Sstevel@tonic-gate max_bufs = MAXBUFMEM / buf_size;
29867c478bd9Sstevel@tonic-gate if (max_bufs > MAXBUF)
29877c478bd9Sstevel@tonic-gate max_bufs = MAXBUF;
29887c478bd9Sstevel@tonic-gate
29897c478bd9Sstevel@tonic-gate pbuf = (bufhdr *)calloc(max_bufs, buf_size);
29907c478bd9Sstevel@tonic-gate if (pbuf == NULL) {
29917c478bd9Sstevel@tonic-gate perror("calloc");
29927c478bd9Sstevel@tonic-gate lockexit(32);
29937c478bd9Sstevel@tonic-gate }
29947c478bd9Sstevel@tonic-gate
29957c478bd9Sstevel@tonic-gate bufhead->head = bufhead;
29967c478bd9Sstevel@tonic-gate prev = bufhead;
29977c478bd9Sstevel@tonic-gate for (i = 0; i < max_bufs; i++) {
29987c478bd9Sstevel@tonic-gate pbuf->head = bufhead;
29997c478bd9Sstevel@tonic-gate prev->next = pbuf;
30007c478bd9Sstevel@tonic-gate prev = pbuf;
30017c478bd9Sstevel@tonic-gate pbuf = (bufhdr *)((char *)pbuf + buf_size);
30027c478bd9Sstevel@tonic-gate }
30037c478bd9Sstevel@tonic-gate }
30047c478bd9Sstevel@tonic-gate
30057c478bd9Sstevel@tonic-gate /*
30067c478bd9Sstevel@tonic-gate * Get an available buffer, waiting for I/O if necessary
30077c478bd9Sstevel@tonic-gate */
30087c478bd9Sstevel@tonic-gate wait_for_write(NOBLOCK);
30097c478bd9Sstevel@tonic-gate while (bufhead->next == NULL)
30107c478bd9Sstevel@tonic-gate wait_for_write(BLOCK);
30117c478bd9Sstevel@tonic-gate
30127c478bd9Sstevel@tonic-gate /*
30137c478bd9Sstevel@tonic-gate * Take the buffer off the list
30147c478bd9Sstevel@tonic-gate */
30157c478bd9Sstevel@tonic-gate pbuf = bufhead->next;
30167c478bd9Sstevel@tonic-gate bufhead->next = pbuf->next;
30177c478bd9Sstevel@tonic-gate pbuf->next = NULL;
30187c478bd9Sstevel@tonic-gate
30197c478bd9Sstevel@tonic-gate /*
30207c478bd9Sstevel@tonic-gate * return the empty buffer space just past the header
30217c478bd9Sstevel@tonic-gate */
30227c478bd9Sstevel@tonic-gate return ((char *)pbuf + bufhdrsize);
30237c478bd9Sstevel@tonic-gate }
30247c478bd9Sstevel@tonic-gate
30257c478bd9Sstevel@tonic-gate /*
30267c478bd9Sstevel@tonic-gate * freebuf() -- Free a buffer gotten previously through getbuf.
30277c478bd9Sstevel@tonic-gate * Puts the buffer back on the appropriate list for
30287c478bd9Sstevel@tonic-gate * later use. Never calls free().
30297c478bd9Sstevel@tonic-gate *
30307c478bd9Sstevel@tonic-gate * Assumes that SIGINT is blocked.
30317c478bd9Sstevel@tonic-gate */
30327c478bd9Sstevel@tonic-gate static void
freebuf(char * buf)30337c478bd9Sstevel@tonic-gate freebuf(char *buf)
30347c478bd9Sstevel@tonic-gate {
30357c478bd9Sstevel@tonic-gate bufhdr *pbuf;
30367c478bd9Sstevel@tonic-gate bufhdr *bufhead;
30377c478bd9Sstevel@tonic-gate
30387c478bd9Sstevel@tonic-gate /*
30397c478bd9Sstevel@tonic-gate * get the header for this buffer
30407c478bd9Sstevel@tonic-gate */
30417c478bd9Sstevel@tonic-gate pbuf = (bufhdr *)(buf - bufhdrsize);
30427c478bd9Sstevel@tonic-gate
30437c478bd9Sstevel@tonic-gate /*
30447c478bd9Sstevel@tonic-gate * Put it back on the list of available buffers
30457c478bd9Sstevel@tonic-gate */
30467c478bd9Sstevel@tonic-gate bufhead = pbuf->head;
30477c478bd9Sstevel@tonic-gate pbuf->next = bufhead->next;
30487c478bd9Sstevel@tonic-gate bufhead->next = pbuf;
30497c478bd9Sstevel@tonic-gate }
30507c478bd9Sstevel@tonic-gate
30517c478bd9Sstevel@tonic-gate /*
30527c478bd9Sstevel@tonic-gate * freetrans() -- Free a transaction gotten previously through getaiop.
30537c478bd9Sstevel@tonic-gate * Puts the transaction struct back on the appropriate list for
30547c478bd9Sstevel@tonic-gate * later use. Never calls free().
30557c478bd9Sstevel@tonic-gate *
30567c478bd9Sstevel@tonic-gate * Assumes that SIGINT is blocked.
30577c478bd9Sstevel@tonic-gate */
30587c478bd9Sstevel@tonic-gate static void
freetrans(aio_trans * transp)30597c478bd9Sstevel@tonic-gate freetrans(aio_trans *transp)
30607c478bd9Sstevel@tonic-gate {
30617c478bd9Sstevel@tonic-gate /*
30627c478bd9Sstevel@tonic-gate * free the buffer associated with this AIO if needed
30637c478bd9Sstevel@tonic-gate */
30647c478bd9Sstevel@tonic-gate if (transp->release == RELEASE)
30657c478bd9Sstevel@tonic-gate freebuf(transp->buffer);
30667c478bd9Sstevel@tonic-gate
30677c478bd9Sstevel@tonic-gate /*
30687c478bd9Sstevel@tonic-gate * Put transaction on the free list
30697c478bd9Sstevel@tonic-gate */
30707c478bd9Sstevel@tonic-gate transp->next = results.trans;
30717c478bd9Sstevel@tonic-gate results.trans = transp;
30727c478bd9Sstevel@tonic-gate }
30737c478bd9Sstevel@tonic-gate
30747c478bd9Sstevel@tonic-gate /*
30757c478bd9Sstevel@tonic-gate * wait_for_write() -- Wait for an aio write to complete. Return
30767c478bd9Sstevel@tonic-gate * the transaction structure for that write.
30777c478bd9Sstevel@tonic-gate *
30787c478bd9Sstevel@tonic-gate * Blocks SIGINT if necessary.
30797c478bd9Sstevel@tonic-gate */
30807c478bd9Sstevel@tonic-gate aio_trans *
wait_for_write(int block)30817c478bd9Sstevel@tonic-gate wait_for_write(int block)
30827c478bd9Sstevel@tonic-gate {
30837c478bd9Sstevel@tonic-gate aio_trans *transp;
30847c478bd9Sstevel@tonic-gate aio_result_t *resultp;
30857c478bd9Sstevel@tonic-gate static struct timeval zero_wait = { 0, 0 };
30867c478bd9Sstevel@tonic-gate sigset_t old_mask;
30877c478bd9Sstevel@tonic-gate
30887c478bd9Sstevel@tonic-gate /*
30897c478bd9Sstevel@tonic-gate * If we know there aren't any outstanding transactions, just return
30907c478bd9Sstevel@tonic-gate */
30917c478bd9Sstevel@tonic-gate if (results.outstanding == 0)
30927c478bd9Sstevel@tonic-gate return ((aio_trans *) 0);
30937c478bd9Sstevel@tonic-gate
30947c478bd9Sstevel@tonic-gate block_sigint(&old_mask);
30957c478bd9Sstevel@tonic-gate
30967c478bd9Sstevel@tonic-gate resultp = aiowait(block ? NULL : &zero_wait);
30977c478bd9Sstevel@tonic-gate if (resultp == NULL ||
30987c478bd9Sstevel@tonic-gate (resultp == (aio_result_t *)-1 && errno == EINVAL)) {
30997c478bd9Sstevel@tonic-gate unblock_sigint(&old_mask);
31007c478bd9Sstevel@tonic-gate return ((aio_trans *) 0);
31017c478bd9Sstevel@tonic-gate }
31027c478bd9Sstevel@tonic-gate
31037c478bd9Sstevel@tonic-gate results.outstanding--;
31047c478bd9Sstevel@tonic-gate transp = (aio_trans *)resultp;
31057c478bd9Sstevel@tonic-gate
31067c478bd9Sstevel@tonic-gate if (resultp->aio_return != transp->size) {
31077c478bd9Sstevel@tonic-gate if (resultp->aio_return == -1) {
31087c478bd9Sstevel@tonic-gate /*
31097c478bd9Sstevel@tonic-gate * The aiowrite() may have failed because the
31107c478bd9Sstevel@tonic-gate * kernel didn't have enough memory to do the job.
31117c478bd9Sstevel@tonic-gate * Flush all pending writes and try a normal
31127c478bd9Sstevel@tonic-gate * write(). wtfs_breakup() will call exit if it
31137c478bd9Sstevel@tonic-gate * fails, so we don't worry about errors here.
31147c478bd9Sstevel@tonic-gate */
31157c478bd9Sstevel@tonic-gate flush_writes();
31167c478bd9Sstevel@tonic-gate wtfs_breakup(transp->bno, transp->size, transp->buffer);
31177c478bd9Sstevel@tonic-gate } else {
31187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
31197c478bd9Sstevel@tonic-gate "short write (%d of %d bytes) on sector %lld\n"),
31207c478bd9Sstevel@tonic-gate resultp->aio_return, transp->size,
31217c478bd9Sstevel@tonic-gate transp->bno);
31227c478bd9Sstevel@tonic-gate /*
31237c478bd9Sstevel@tonic-gate * Don't unblock SIGINT, to avoid potential
31247c478bd9Sstevel@tonic-gate * looping due to queued interrupts and
31257c478bd9Sstevel@tonic-gate * error handling.
31267c478bd9Sstevel@tonic-gate */
31277c478bd9Sstevel@tonic-gate lockexit(32);
31287c478bd9Sstevel@tonic-gate }
31297c478bd9Sstevel@tonic-gate }
31307c478bd9Sstevel@tonic-gate
31317c478bd9Sstevel@tonic-gate resultp->aio_return = 0;
31327c478bd9Sstevel@tonic-gate freetrans(transp);
31337c478bd9Sstevel@tonic-gate unblock_sigint(&old_mask);
31347c478bd9Sstevel@tonic-gate return (transp);
31357c478bd9Sstevel@tonic-gate }
31367c478bd9Sstevel@tonic-gate
31377c478bd9Sstevel@tonic-gate /*
31387c478bd9Sstevel@tonic-gate * flush_writes() -- flush all the outstanding aio writes.
31397c478bd9Sstevel@tonic-gate */
31407c478bd9Sstevel@tonic-gate static void
flush_writes(void)31417c478bd9Sstevel@tonic-gate flush_writes(void)
31427c478bd9Sstevel@tonic-gate {
31437c478bd9Sstevel@tonic-gate while (wait_for_write(BLOCK))
31447c478bd9Sstevel@tonic-gate ;
31457c478bd9Sstevel@tonic-gate }
31467c478bd9Sstevel@tonic-gate
31477c478bd9Sstevel@tonic-gate /*
31487c478bd9Sstevel@tonic-gate * get_aiop() -- find and return an aio_trans structure on which a new
31497c478bd9Sstevel@tonic-gate * aio can be done. Blocks on aiowait() if needed. Reaps
31507c478bd9Sstevel@tonic-gate * all outstanding completed aio's.
31517c478bd9Sstevel@tonic-gate *
31527c478bd9Sstevel@tonic-gate * Assumes that SIGINT is blocked.
31537c478bd9Sstevel@tonic-gate */
31547c478bd9Sstevel@tonic-gate aio_trans *
get_aiop()31557c478bd9Sstevel@tonic-gate get_aiop()
31567c478bd9Sstevel@tonic-gate {
31577c478bd9Sstevel@tonic-gate int i;
31587c478bd9Sstevel@tonic-gate aio_trans *transp;
31597c478bd9Sstevel@tonic-gate aio_trans *prev;
31607c478bd9Sstevel@tonic-gate
31617c478bd9Sstevel@tonic-gate /*
31627c478bd9Sstevel@tonic-gate * initialize aio stuff
31637c478bd9Sstevel@tonic-gate */
31647c478bd9Sstevel@tonic-gate if (!aio_inited) {
31657c478bd9Sstevel@tonic-gate aio_inited = 1;
31667c478bd9Sstevel@tonic-gate
31677c478bd9Sstevel@tonic-gate results.maxpend = 0;
31687c478bd9Sstevel@tonic-gate results.outstanding = 0;
31697c478bd9Sstevel@tonic-gate results.max = MAXAIO;
31707c478bd9Sstevel@tonic-gate
31717c478bd9Sstevel@tonic-gate results.trans = (aio_trans *)calloc(results.max,
31727c478bd9Sstevel@tonic-gate sizeof (aio_trans));
31737c478bd9Sstevel@tonic-gate if (results.trans == NULL) {
31747c478bd9Sstevel@tonic-gate perror("calloc");
31757c478bd9Sstevel@tonic-gate lockexit(32);
31767c478bd9Sstevel@tonic-gate }
31777c478bd9Sstevel@tonic-gate
31787c478bd9Sstevel@tonic-gate /*
31797c478bd9Sstevel@tonic-gate * Initialize the linked list of aio transaction
31807c478bd9Sstevel@tonic-gate * structures. Note that the final "next" pointer
31817c478bd9Sstevel@tonic-gate * will be NULL since we got the buffer from calloc().
31827c478bd9Sstevel@tonic-gate */
31837c478bd9Sstevel@tonic-gate prev = results.trans;
31847c478bd9Sstevel@tonic-gate for (i = 1; i < results.max; i++) {
31857c478bd9Sstevel@tonic-gate prev->next = &(results.trans[i]);
31867c478bd9Sstevel@tonic-gate prev = prev->next;
31877c478bd9Sstevel@tonic-gate }
31887c478bd9Sstevel@tonic-gate }
31897c478bd9Sstevel@tonic-gate
31907c478bd9Sstevel@tonic-gate wait_for_write(NOBLOCK);
31917c478bd9Sstevel@tonic-gate while (results.trans == NULL)
31927c478bd9Sstevel@tonic-gate wait_for_write(BLOCK);
31937c478bd9Sstevel@tonic-gate transp = results.trans;
31947c478bd9Sstevel@tonic-gate results.trans = results.trans->next;
31957c478bd9Sstevel@tonic-gate
31967c478bd9Sstevel@tonic-gate transp->next = 0;
31977c478bd9Sstevel@tonic-gate transp->resultbuf.aio_return = AIO_INPROGRESS;
31987c478bd9Sstevel@tonic-gate return (transp);
31997c478bd9Sstevel@tonic-gate }
32007c478bd9Sstevel@tonic-gate
32017c478bd9Sstevel@tonic-gate /*
32027c478bd9Sstevel@tonic-gate * read a block from the file system
32037c478bd9Sstevel@tonic-gate */
32047c478bd9Sstevel@tonic-gate static void
rdfs(diskaddr_t bno,int size,char * bf)32057c478bd9Sstevel@tonic-gate rdfs(diskaddr_t bno, int size, char *bf)
32067c478bd9Sstevel@tonic-gate {
32077c478bd9Sstevel@tonic-gate int n, saverr;
32087c478bd9Sstevel@tonic-gate
32097c478bd9Sstevel@tonic-gate /*
32107c478bd9Sstevel@tonic-gate * In case we need any data that's pending in an aiowrite(),
32117c478bd9Sstevel@tonic-gate * we wait for them all to complete before doing a read.
32127c478bd9Sstevel@tonic-gate */
32137c478bd9Sstevel@tonic-gate flush_writes();
32147c478bd9Sstevel@tonic-gate
32157c478bd9Sstevel@tonic-gate /*
32167c478bd9Sstevel@tonic-gate * Note: the llseek() can succeed, even if the offset is out of range.
32177c478bd9Sstevel@tonic-gate * It's not until the file i/o operation (the read()) that one knows
32187c478bd9Sstevel@tonic-gate * for sure if the raw device can handle the offset.
32197c478bd9Sstevel@tonic-gate */
32207c478bd9Sstevel@tonic-gate if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) {
32217c478bd9Sstevel@tonic-gate saverr = errno;
32227c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
32237c478bd9Sstevel@tonic-gate gettext("seek error on sector %lld: %s\n"),
32247c478bd9Sstevel@tonic-gate bno, strerror(saverr));
32257c478bd9Sstevel@tonic-gate lockexit(32);
32267c478bd9Sstevel@tonic-gate }
32277c478bd9Sstevel@tonic-gate n = read(fsi, bf, size);
32287c478bd9Sstevel@tonic-gate if (n != size) {
32297c478bd9Sstevel@tonic-gate saverr = errno;
32307c478bd9Sstevel@tonic-gate if (n == -1)
32317c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
32327c478bd9Sstevel@tonic-gate gettext("read error on sector %lld: %s\n"),
32337c478bd9Sstevel@tonic-gate bno, strerror(saverr));
32347c478bd9Sstevel@tonic-gate else
32357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
32367c478bd9Sstevel@tonic-gate "short read (%d of %d bytes) on sector %lld\n"),
32377c478bd9Sstevel@tonic-gate n, size, bno);
32387c478bd9Sstevel@tonic-gate lockexit(32);
32397c478bd9Sstevel@tonic-gate }
32407c478bd9Sstevel@tonic-gate }
32417c478bd9Sstevel@tonic-gate
32427c478bd9Sstevel@tonic-gate /*
32437c478bd9Sstevel@tonic-gate * write a block to the file system
32447c478bd9Sstevel@tonic-gate */
32457c478bd9Sstevel@tonic-gate static void
wtfs(diskaddr_t bno,int size,char * bf)32467c478bd9Sstevel@tonic-gate wtfs(diskaddr_t bno, int size, char *bf)
32477c478bd9Sstevel@tonic-gate {
32487c478bd9Sstevel@tonic-gate int n, saverr;
32497c478bd9Sstevel@tonic-gate
32507c478bd9Sstevel@tonic-gate if (fso == -1)
32517c478bd9Sstevel@tonic-gate return;
32527c478bd9Sstevel@tonic-gate
32537c478bd9Sstevel@tonic-gate /*
32547c478bd9Sstevel@tonic-gate * Note: the llseek() can succeed, even if the offset is out of range.
32557c478bd9Sstevel@tonic-gate * It's not until the file i/o operation (the write()) that one knows
32567c478bd9Sstevel@tonic-gate * for sure if the raw device can handle the offset.
32577c478bd9Sstevel@tonic-gate */
32587c478bd9Sstevel@tonic-gate if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
32597c478bd9Sstevel@tonic-gate saverr = errno;
32607c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
32617c478bd9Sstevel@tonic-gate gettext("seek error on sector %lld: %s\n"),
32627c478bd9Sstevel@tonic-gate bno, strerror(saverr));
32637c478bd9Sstevel@tonic-gate lockexit(32);
32647c478bd9Sstevel@tonic-gate }
32657c478bd9Sstevel@tonic-gate if (Nflag)
32667c478bd9Sstevel@tonic-gate return;
32677c478bd9Sstevel@tonic-gate n = write(fso, bf, size);
32687c478bd9Sstevel@tonic-gate if (n != size) {
32697c478bd9Sstevel@tonic-gate saverr = errno;
32707c478bd9Sstevel@tonic-gate if (n == -1)
32717c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
32727c478bd9Sstevel@tonic-gate gettext("write error on sector %lld: %s\n"),
32737c478bd9Sstevel@tonic-gate bno, strerror(saverr));
32747c478bd9Sstevel@tonic-gate else
32757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
32767c478bd9Sstevel@tonic-gate "short write (%d of %d bytes) on sector %lld\n"),
32777c478bd9Sstevel@tonic-gate n, size, bno);
32787c478bd9Sstevel@tonic-gate lockexit(32);
32797c478bd9Sstevel@tonic-gate }
32807c478bd9Sstevel@tonic-gate }
32817c478bd9Sstevel@tonic-gate
32827c478bd9Sstevel@tonic-gate /*
32837c478bd9Sstevel@tonic-gate * write a block to the file system -- buffered with aio
32847c478bd9Sstevel@tonic-gate */
32857c478bd9Sstevel@tonic-gate static void
awtfs(diskaddr_t bno,int size,char * bf,int release)32867c478bd9Sstevel@tonic-gate awtfs(diskaddr_t bno, int size, char *bf, int release)
32877c478bd9Sstevel@tonic-gate {
32887c478bd9Sstevel@tonic-gate int n;
32897c478bd9Sstevel@tonic-gate aio_trans *transp;
32907c478bd9Sstevel@tonic-gate sigset_t old_mask;
32917c478bd9Sstevel@tonic-gate
32927c478bd9Sstevel@tonic-gate if (fso == -1)
32937c478bd9Sstevel@tonic-gate return;
32947c478bd9Sstevel@tonic-gate
32957c478bd9Sstevel@tonic-gate /*
32967c478bd9Sstevel@tonic-gate * We need to keep things consistent if we get interrupted,
32977c478bd9Sstevel@tonic-gate * so defer any expected interrupts for the time being.
32987c478bd9Sstevel@tonic-gate */
32997c478bd9Sstevel@tonic-gate block_sigint(&old_mask);
33007c478bd9Sstevel@tonic-gate
33017c478bd9Sstevel@tonic-gate if (Nflag) {
33027c478bd9Sstevel@tonic-gate if (release == RELEASE)
33037c478bd9Sstevel@tonic-gate freebuf(bf);
33047c478bd9Sstevel@tonic-gate } else {
33057c478bd9Sstevel@tonic-gate transp = get_aiop();
33067c478bd9Sstevel@tonic-gate transp->bno = bno;
33077c478bd9Sstevel@tonic-gate transp->buffer = bf;
33087c478bd9Sstevel@tonic-gate transp->size = size;
33097c478bd9Sstevel@tonic-gate transp->release = release;
33107c478bd9Sstevel@tonic-gate
33117c478bd9Sstevel@tonic-gate n = aiowrite(fso, bf, size, (off_t)bno * sectorsize,
33127c478bd9Sstevel@tonic-gate SEEK_SET, &transp->resultbuf);
33137c478bd9Sstevel@tonic-gate
33147c478bd9Sstevel@tonic-gate if (n < 0) {
33157c478bd9Sstevel@tonic-gate /*
33167c478bd9Sstevel@tonic-gate * The aiowrite() may have failed because the
33177c478bd9Sstevel@tonic-gate * kernel didn't have enough memory to do the job.
33187c478bd9Sstevel@tonic-gate * Flush all pending writes and try a normal
33197c478bd9Sstevel@tonic-gate * write(). wtfs_breakup() will call exit if it
33207c478bd9Sstevel@tonic-gate * fails, so we don't worry about errors here.
33217c478bd9Sstevel@tonic-gate */
33227c478bd9Sstevel@tonic-gate flush_writes();
33237c478bd9Sstevel@tonic-gate wtfs_breakup(transp->bno, transp->size, transp->buffer);
33247c478bd9Sstevel@tonic-gate freetrans(transp);
33257c478bd9Sstevel@tonic-gate } else {
33267c478bd9Sstevel@tonic-gate /*
33277c478bd9Sstevel@tonic-gate * Keep track of our pending writes.
33287c478bd9Sstevel@tonic-gate */
33297c478bd9Sstevel@tonic-gate results.outstanding++;
33307c478bd9Sstevel@tonic-gate if (results.outstanding > results.maxpend)
33317c478bd9Sstevel@tonic-gate results.maxpend = results.outstanding;
33327c478bd9Sstevel@tonic-gate }
33337c478bd9Sstevel@tonic-gate }
33347c478bd9Sstevel@tonic-gate
33357c478bd9Sstevel@tonic-gate unblock_sigint(&old_mask);
33367c478bd9Sstevel@tonic-gate }
33377c478bd9Sstevel@tonic-gate
33387c478bd9Sstevel@tonic-gate
33397c478bd9Sstevel@tonic-gate /*
33407c478bd9Sstevel@tonic-gate * write a block to the file system, but break it up into sbsize
33417c478bd9Sstevel@tonic-gate * chunks to avoid forcing a large amount of memory to be locked down.
33427c478bd9Sstevel@tonic-gate * Only used as a fallback when an aio write has failed.
33437c478bd9Sstevel@tonic-gate */
33447c478bd9Sstevel@tonic-gate static void
wtfs_breakup(diskaddr_t bno,int size,char * bf)33457c478bd9Sstevel@tonic-gate wtfs_breakup(diskaddr_t bno, int size, char *bf)
33467c478bd9Sstevel@tonic-gate {
33477c478bd9Sstevel@tonic-gate int n, saverr;
33487c478bd9Sstevel@tonic-gate int wsize;
33497c478bd9Sstevel@tonic-gate int block_incr = sbsize / sectorsize;
33507c478bd9Sstevel@tonic-gate
33517c478bd9Sstevel@tonic-gate if (size < sbsize)
33527c478bd9Sstevel@tonic-gate wsize = size;
33537c478bd9Sstevel@tonic-gate else
33547c478bd9Sstevel@tonic-gate wsize = sbsize;
33557c478bd9Sstevel@tonic-gate
33567c478bd9Sstevel@tonic-gate n = 0;
33577c478bd9Sstevel@tonic-gate while (size) {
33587c478bd9Sstevel@tonic-gate /*
33597c478bd9Sstevel@tonic-gate * Note: the llseek() can succeed, even if the offset is
33607c478bd9Sstevel@tonic-gate * out of range. It's not until the file i/o operation
33617c478bd9Sstevel@tonic-gate * (the write()) that one knows for sure if the raw device
33627c478bd9Sstevel@tonic-gate * can handle the offset.
33637c478bd9Sstevel@tonic-gate */
33647c478bd9Sstevel@tonic-gate if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
33657c478bd9Sstevel@tonic-gate saverr = errno;
33667c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
33677c478bd9Sstevel@tonic-gate gettext("seek error on sector %lld: %s\n"),
33687c478bd9Sstevel@tonic-gate bno, strerror(saverr));
33697c478bd9Sstevel@tonic-gate lockexit(32);
33707c478bd9Sstevel@tonic-gate }
33717c478bd9Sstevel@tonic-gate
33727c478bd9Sstevel@tonic-gate n = write(fso, bf, wsize);
33737c478bd9Sstevel@tonic-gate if (n == -1) {
33747c478bd9Sstevel@tonic-gate saverr = errno;
33757c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
33767c478bd9Sstevel@tonic-gate gettext("write error on sector %lld: %s\n"),
33777c478bd9Sstevel@tonic-gate bno, strerror(saverr));
33787c478bd9Sstevel@tonic-gate lockexit(32);
33797c478bd9Sstevel@tonic-gate }
33807c478bd9Sstevel@tonic-gate if (n != wsize) {
33817c478bd9Sstevel@tonic-gate saverr = errno;
33827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
33837c478bd9Sstevel@tonic-gate "short write (%d of %d bytes) on sector %lld\n"),
33847c478bd9Sstevel@tonic-gate n, size, bno);
33857c478bd9Sstevel@tonic-gate lockexit(32);
33867c478bd9Sstevel@tonic-gate }
33877c478bd9Sstevel@tonic-gate
33887c478bd9Sstevel@tonic-gate bno += block_incr;
33897c478bd9Sstevel@tonic-gate bf += wsize;
33907c478bd9Sstevel@tonic-gate size -= wsize;
33917c478bd9Sstevel@tonic-gate if (size < wsize)
33927c478bd9Sstevel@tonic-gate wsize = size;
33937c478bd9Sstevel@tonic-gate }
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate
33967c478bd9Sstevel@tonic-gate
33977c478bd9Sstevel@tonic-gate /*
33987c478bd9Sstevel@tonic-gate * check if a block is available
33997c478bd9Sstevel@tonic-gate */
34007c478bd9Sstevel@tonic-gate static int
isblock(struct fs * fs,unsigned char * cp,int h)34017c478bd9Sstevel@tonic-gate isblock(struct fs *fs, unsigned char *cp, int h)
34027c478bd9Sstevel@tonic-gate {
34037c478bd9Sstevel@tonic-gate unsigned char mask;
34047c478bd9Sstevel@tonic-gate
34057c478bd9Sstevel@tonic-gate switch (fs->fs_frag) {
34067c478bd9Sstevel@tonic-gate case 8:
34077c478bd9Sstevel@tonic-gate return (cp[h] == 0xff);
34087c478bd9Sstevel@tonic-gate case 4:
34097c478bd9Sstevel@tonic-gate mask = 0x0f << ((h & 0x1) << 2);
34107c478bd9Sstevel@tonic-gate return ((cp[h >> 1] & mask) == mask);
34117c478bd9Sstevel@tonic-gate case 2:
34127c478bd9Sstevel@tonic-gate mask = 0x03 << ((h & 0x3) << 1);
34137c478bd9Sstevel@tonic-gate return ((cp[h >> 2] & mask) == mask);
34147c478bd9Sstevel@tonic-gate case 1:
34157c478bd9Sstevel@tonic-gate mask = 0x01 << (h & 0x7);
34167c478bd9Sstevel@tonic-gate return ((cp[h >> 3] & mask) == mask);
34177c478bd9Sstevel@tonic-gate default:
34187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
34197c478bd9Sstevel@tonic-gate return (0);
34207c478bd9Sstevel@tonic-gate }
34217c478bd9Sstevel@tonic-gate }
34227c478bd9Sstevel@tonic-gate
34237c478bd9Sstevel@tonic-gate /*
34247c478bd9Sstevel@tonic-gate * take a block out of the map
34257c478bd9Sstevel@tonic-gate */
34267c478bd9Sstevel@tonic-gate static void
clrblock(struct fs * fs,unsigned char * cp,int h)34277c478bd9Sstevel@tonic-gate clrblock(struct fs *fs, unsigned char *cp, int h)
34287c478bd9Sstevel@tonic-gate {
34297c478bd9Sstevel@tonic-gate switch ((fs)->fs_frag) {
34307c478bd9Sstevel@tonic-gate case 8:
34317c478bd9Sstevel@tonic-gate cp[h] = 0;
34327c478bd9Sstevel@tonic-gate return;
34337c478bd9Sstevel@tonic-gate case 4:
34347c478bd9Sstevel@tonic-gate cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
34357c478bd9Sstevel@tonic-gate return;
34367c478bd9Sstevel@tonic-gate case 2:
34377c478bd9Sstevel@tonic-gate cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
34387c478bd9Sstevel@tonic-gate return;
34397c478bd9Sstevel@tonic-gate case 1:
34407c478bd9Sstevel@tonic-gate cp[h >> 3] &= ~(0x01 << (h & 0x7));
34417c478bd9Sstevel@tonic-gate return;
34427c478bd9Sstevel@tonic-gate default:
34437c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
34447c478bd9Sstevel@tonic-gate gettext("clrblock: bad fs_frag value %d\n"), fs->fs_frag);
34457c478bd9Sstevel@tonic-gate return;
34467c478bd9Sstevel@tonic-gate }
34477c478bd9Sstevel@tonic-gate }
34487c478bd9Sstevel@tonic-gate
34497c478bd9Sstevel@tonic-gate /*
34507c478bd9Sstevel@tonic-gate * put a block into the map
34517c478bd9Sstevel@tonic-gate */
34527c478bd9Sstevel@tonic-gate static void
setblock(struct fs * fs,unsigned char * cp,int h)34537c478bd9Sstevel@tonic-gate setblock(struct fs *fs, unsigned char *cp, int h)
34547c478bd9Sstevel@tonic-gate {
34557c478bd9Sstevel@tonic-gate switch (fs->fs_frag) {
34567c478bd9Sstevel@tonic-gate case 8:
34577c478bd9Sstevel@tonic-gate cp[h] = 0xff;
34587c478bd9Sstevel@tonic-gate return;
34597c478bd9Sstevel@tonic-gate case 4:
34607c478bd9Sstevel@tonic-gate cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
34617c478bd9Sstevel@tonic-gate return;
34627c478bd9Sstevel@tonic-gate case 2:
34637c478bd9Sstevel@tonic-gate cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
34647c478bd9Sstevel@tonic-gate return;
34657c478bd9Sstevel@tonic-gate case 1:
34667c478bd9Sstevel@tonic-gate cp[h >> 3] |= (0x01 << (h & 0x7));
34677c478bd9Sstevel@tonic-gate return;
34687c478bd9Sstevel@tonic-gate default:
34697c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
34707c478bd9Sstevel@tonic-gate gettext("setblock: bad fs_frag value %d\n"), fs->fs_frag);
34717c478bd9Sstevel@tonic-gate return;
34727c478bd9Sstevel@tonic-gate }
34737c478bd9Sstevel@tonic-gate }
34747c478bd9Sstevel@tonic-gate
34757c478bd9Sstevel@tonic-gate static void
usage()34767c478bd9Sstevel@tonic-gate usage()
34777c478bd9Sstevel@tonic-gate {
34787c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
34797c478bd9Sstevel@tonic-gate gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] "
34807c478bd9Sstevel@tonic-gate "special " /* param 0 */
34817c478bd9Sstevel@tonic-gate "size(sectors) \\ \n")); /* param 1 */
34827c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
34837c478bd9Sstevel@tonic-gate "[nsect " /* param 2 */
34847c478bd9Sstevel@tonic-gate "ntrack " /* param 3 */
34857c478bd9Sstevel@tonic-gate "bsize " /* param 4 */
34867c478bd9Sstevel@tonic-gate "fragsize " /* param 5 */
34877c478bd9Sstevel@tonic-gate "cpg " /* param 6 */
34887c478bd9Sstevel@tonic-gate "free " /* param 7 */
34897c478bd9Sstevel@tonic-gate "rps " /* param 8 */
34907c478bd9Sstevel@tonic-gate "nbpi " /* param 9 */
34917c478bd9Sstevel@tonic-gate "opt " /* param 10 */
34927c478bd9Sstevel@tonic-gate "apc " /* param 11 */
34937c478bd9Sstevel@tonic-gate "gap " /* param 12 */
34947c478bd9Sstevel@tonic-gate "nrpos " /* param 13 */
34957c478bd9Sstevel@tonic-gate "maxcontig " /* param 14 */
34967c478bd9Sstevel@tonic-gate "mtb]\n"); /* param 15 */
34977c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
34987c478bd9Sstevel@tonic-gate gettext(" -m : dump fs cmd line used to make this partition\n"
34997c478bd9Sstevel@tonic-gate " -V :print this command line and return\n"
35007c478bd9Sstevel@tonic-gate " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n"
35017c478bd9Sstevel@tonic-gate " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n"
35027c478bd9Sstevel@tonic-gate " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n"
3503355d6bb5Sswilcox " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n"
35047c478bd9Sstevel@tonic-gate "NOTE that all -o suboptions: must be separated only by commas so as to\n"
35057c478bd9Sstevel@tonic-gate "be parsed as a single argument\n"),
35067c478bd9Sstevel@tonic-gate nsect, ntrack, bsize, fragsize, cpg, sblock.fs_minfree, rps,
35077c478bd9Sstevel@tonic-gate nbpi, opt, apc, (rotdelay == -1) ? 0 : rotdelay,
35087c478bd9Sstevel@tonic-gate sblock.fs_nrpos, maxcontig, mtb);
35097c478bd9Sstevel@tonic-gate lockexit(32);
35107c478bd9Sstevel@tonic-gate }
35117c478bd9Sstevel@tonic-gate
35127c478bd9Sstevel@tonic-gate /*ARGSUSED*/
35137c478bd9Sstevel@tonic-gate static void
dump_fscmd(char * fsys,int fsi)35147c478bd9Sstevel@tonic-gate dump_fscmd(char *fsys, int fsi)
35157c478bd9Sstevel@tonic-gate {
35167c478bd9Sstevel@tonic-gate int64_t used, bpcg, inospercg;
35177c478bd9Sstevel@tonic-gate int64_t nbpi;
35187c478bd9Sstevel@tonic-gate uint64_t nbytes64;
35197c478bd9Sstevel@tonic-gate
35207c478bd9Sstevel@tonic-gate bzero((char *)&sblock, sizeof (sblock));
35217c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)SBLOCK, SBSIZE, (char *)&sblock);
35227c478bd9Sstevel@tonic-gate
35237c478bd9Sstevel@tonic-gate /*
35247c478bd9Sstevel@tonic-gate * ensure a valid file system and if not, exit with error or else
35257c478bd9Sstevel@tonic-gate * we will end up computing block numbers etc and dividing by zero
35267c478bd9Sstevel@tonic-gate * which will cause floating point errors in this routine.
35277c478bd9Sstevel@tonic-gate */
35287c478bd9Sstevel@tonic-gate
35297c478bd9Sstevel@tonic-gate if ((sblock.fs_magic != FS_MAGIC) &&
35307c478bd9Sstevel@tonic-gate (sblock.fs_magic != MTB_UFS_MAGIC)) {
35317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
35327c478bd9Sstevel@tonic-gate "[not currently a valid file system - bad superblock]\n"));
35337c478bd9Sstevel@tonic-gate lockexit(32);
35347c478bd9Sstevel@tonic-gate }
35357c478bd9Sstevel@tonic-gate
35366451fdbcSvsakar if (sblock.fs_magic == FS_MAGIC &&
35376451fdbcSvsakar (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
35386451fdbcSvsakar sblock.fs_version != UFS_VERSION_MIN)) {
35396451fdbcSvsakar (void) fprintf(stderr, gettext(
35406451fdbcSvsakar "Unknown version of UFS format: %d\n"), sblock.fs_version);
35416451fdbcSvsakar lockexit(32);
35426451fdbcSvsakar }
35436451fdbcSvsakar
35447c478bd9Sstevel@tonic-gate if (sblock.fs_magic == MTB_UFS_MAGIC &&
35457c478bd9Sstevel@tonic-gate (sblock.fs_version > MTB_UFS_VERSION_1 ||
35467c478bd9Sstevel@tonic-gate sblock.fs_version < MTB_UFS_VERSION_MIN)) {
35477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
35487c478bd9Sstevel@tonic-gate "Unknown version of UFS format: %d\n"), sblock.fs_version);
35497c478bd9Sstevel@tonic-gate lockexit(32);
35507c478bd9Sstevel@tonic-gate }
35517c478bd9Sstevel@tonic-gate
35527c478bd9Sstevel@tonic-gate /*
35537c478bd9Sstevel@tonic-gate * Compute a reasonable nbpi value.
35547c478bd9Sstevel@tonic-gate * The algorithm for "used" is copied from code
35557c478bd9Sstevel@tonic-gate * in main() verbatim.
35567c478bd9Sstevel@tonic-gate * The nbpi equation is taken from main where the
35577c478bd9Sstevel@tonic-gate * fs_ipg value is set for the last time. The INOPB(...) - 1
35587c478bd9Sstevel@tonic-gate * is used to account for the roundup.
35597c478bd9Sstevel@tonic-gate * The problem is that a range of nbpi values map to
35607c478bd9Sstevel@tonic-gate * the same file system layout. So it is not possible
35617c478bd9Sstevel@tonic-gate * to calculate the exact value specified when the file
35627c478bd9Sstevel@tonic-gate * system was created. So instead we determine the top
35637c478bd9Sstevel@tonic-gate * end of the range of values.
35647c478bd9Sstevel@tonic-gate */
35657c478bd9Sstevel@tonic-gate bpcg = sblock.fs_spc * sectorsize;
35667c478bd9Sstevel@tonic-gate inospercg = (int64_t)roundup(bpcg / sizeof (struct dinode),
35677c478bd9Sstevel@tonic-gate INOPB(&sblock));
35687c478bd9Sstevel@tonic-gate if (inospercg > MAXIpG(&sblock))
35697c478bd9Sstevel@tonic-gate inospercg = MAXIpG(&sblock);
35707c478bd9Sstevel@tonic-gate used = (int64_t)
35717c478bd9Sstevel@tonic-gate (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
35727c478bd9Sstevel@tonic-gate used *= sectorsize;
35737c478bd9Sstevel@tonic-gate nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
35747c478bd9Sstevel@tonic-gate
35757c478bd9Sstevel@tonic-gate /*
35767c478bd9Sstevel@tonic-gate * The top end of the range of values for nbpi may not be
35777c478bd9Sstevel@tonic-gate * a valid command line value for mkfs. Report the bottom
35787c478bd9Sstevel@tonic-gate * end instead.
35797c478bd9Sstevel@tonic-gate */
35807c478bd9Sstevel@tonic-gate nbpi = (int64_t)(nbytes64 / (sblock.fs_ipg));
35817c478bd9Sstevel@tonic-gate
35827c478bd9Sstevel@tonic-gate (void) fprintf(stdout, gettext("mkfs -F ufs -o "), fsys);
35837c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "nsect=%d,ntrack=%d,",
35847c478bd9Sstevel@tonic-gate sblock.fs_nsect, sblock.fs_ntrak);
35857c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,",
35867c478bd9Sstevel@tonic-gate sblock.fs_bsize, sblock.fs_fsize, sblock.fs_cpg, sblock.fs_minfree);
35877c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,",
35887c478bd9Sstevel@tonic-gate sblock.fs_rps, nbpi, (sblock.fs_optim == FS_OPTSPACE) ? 's' : 't',
35897c478bd9Sstevel@tonic-gate (sblock.fs_ntrak * sblock.fs_nsect) - sblock.fs_spc,
35907c478bd9Sstevel@tonic-gate sblock.fs_rotdelay);
35917c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "nrpos=%d,maxcontig=%d,mtb=%c ",
35927c478bd9Sstevel@tonic-gate sblock.fs_nrpos, sblock.fs_maxcontig,
35937c478bd9Sstevel@tonic-gate ((sblock.fs_magic == MTB_UFS_MAGIC) ? 'y' : 'n'));
35947c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s %lld\n", fsys,
35957c478bd9Sstevel@tonic-gate fsbtodb(&sblock, sblock.fs_size));
35967c478bd9Sstevel@tonic-gate
35977c478bd9Sstevel@tonic-gate bzero((char *)&sblock, sizeof (sblock));
35987c478bd9Sstevel@tonic-gate }
35997c478bd9Sstevel@tonic-gate
36007c478bd9Sstevel@tonic-gate /* number ************************************************************* */
36017c478bd9Sstevel@tonic-gate /* */
36027c478bd9Sstevel@tonic-gate /* Convert a numeric string arg to binary */
36037c478bd9Sstevel@tonic-gate /* */
36047c478bd9Sstevel@tonic-gate /* Args: d_value - default value, if have parse error */
36057c478bd9Sstevel@tonic-gate /* param - the name of the argument, for error messages */
36067c478bd9Sstevel@tonic-gate /* flags - parser state and what's allowed in the arg */
36077c478bd9Sstevel@tonic-gate /* Global arg: string - pointer to command arg */
36087c478bd9Sstevel@tonic-gate /* */
36097c478bd9Sstevel@tonic-gate /* Valid forms: 123 | 123k | 123*123 | 123x123 */
36107c478bd9Sstevel@tonic-gate /* */
36117c478bd9Sstevel@tonic-gate /* Return: converted number */
36127c478bd9Sstevel@tonic-gate /* */
36137c478bd9Sstevel@tonic-gate /* ******************************************************************** */
36147c478bd9Sstevel@tonic-gate
36157c478bd9Sstevel@tonic-gate static uint64_t
number(uint64_t d_value,char * param,int flags)36167c478bd9Sstevel@tonic-gate number(uint64_t d_value, char *param, int flags)
36177c478bd9Sstevel@tonic-gate {
36187c478bd9Sstevel@tonic-gate char *cs;
36197c478bd9Sstevel@tonic-gate uint64_t n, t;
36207c478bd9Sstevel@tonic-gate uint64_t cut = BIG / 10; /* limit to avoid overflow */
36217c478bd9Sstevel@tonic-gate int minus = 0;
36227c478bd9Sstevel@tonic-gate
36237c478bd9Sstevel@tonic-gate cs = string;
36247c478bd9Sstevel@tonic-gate if (*cs == '-') {
36257c478bd9Sstevel@tonic-gate minus = 1;
36267c478bd9Sstevel@tonic-gate cs += 1;
36277c478bd9Sstevel@tonic-gate }
36287c478bd9Sstevel@tonic-gate if ((*cs < '0') || (*cs > '9')) {
36297c478bd9Sstevel@tonic-gate goto bail_out;
36307c478bd9Sstevel@tonic-gate }
36317c478bd9Sstevel@tonic-gate n = 0;
36327c478bd9Sstevel@tonic-gate while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
36337c478bd9Sstevel@tonic-gate n = n*10 + *cs++ - '0';
36347c478bd9Sstevel@tonic-gate }
36357c478bd9Sstevel@tonic-gate if (minus)
36367c478bd9Sstevel@tonic-gate n = -n;
36377c478bd9Sstevel@tonic-gate for (;;) {
36387c478bd9Sstevel@tonic-gate switch (*cs++) {
36397c478bd9Sstevel@tonic-gate case 'k':
36407c478bd9Sstevel@tonic-gate if (flags & ALLOW_END_ONLY)
36417c478bd9Sstevel@tonic-gate goto bail_out;
36427c478bd9Sstevel@tonic-gate if (n > (BIG / 1024))
36437c478bd9Sstevel@tonic-gate goto overflow;
36447c478bd9Sstevel@tonic-gate n *= 1024;
36457c478bd9Sstevel@tonic-gate continue;
36467c478bd9Sstevel@tonic-gate
36477c478bd9Sstevel@tonic-gate case '*':
36487c478bd9Sstevel@tonic-gate case 'x':
36497c478bd9Sstevel@tonic-gate if (flags & ALLOW_END_ONLY)
36507c478bd9Sstevel@tonic-gate goto bail_out;
36517c478bd9Sstevel@tonic-gate string = cs;
36527c478bd9Sstevel@tonic-gate t = number(d_value, param, flags);
36537c478bd9Sstevel@tonic-gate if (n > (BIG / t))
36547c478bd9Sstevel@tonic-gate goto overflow;
36557c478bd9Sstevel@tonic-gate n *= t;
36567c478bd9Sstevel@tonic-gate cs = string + 1; /* adjust for -- below */
36577c478bd9Sstevel@tonic-gate
36587c478bd9Sstevel@tonic-gate /* recursion has read rest of expression */
36597c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
36607c478bd9Sstevel@tonic-gate
36617c478bd9Sstevel@tonic-gate case ',':
36627c478bd9Sstevel@tonic-gate case '\0':
36637c478bd9Sstevel@tonic-gate cs--;
36647c478bd9Sstevel@tonic-gate string = cs;
36657c478bd9Sstevel@tonic-gate return (n);
36667c478bd9Sstevel@tonic-gate
36677c478bd9Sstevel@tonic-gate case '%':
36687c478bd9Sstevel@tonic-gate if (flags & ALLOW_END_ONLY)
36697c478bd9Sstevel@tonic-gate goto bail_out;
36707c478bd9Sstevel@tonic-gate if (flags & ALLOW_PERCENT) {
36717c478bd9Sstevel@tonic-gate flags &= ~ALLOW_PERCENT;
36727c478bd9Sstevel@tonic-gate flags |= ALLOW_END_ONLY;
36737c478bd9Sstevel@tonic-gate continue;
36747c478bd9Sstevel@tonic-gate }
36757c478bd9Sstevel@tonic-gate goto bail_out;
36767c478bd9Sstevel@tonic-gate
36777c478bd9Sstevel@tonic-gate case 'm':
36787c478bd9Sstevel@tonic-gate if (flags & ALLOW_END_ONLY)
36797c478bd9Sstevel@tonic-gate goto bail_out;
36807c478bd9Sstevel@tonic-gate if (flags & ALLOW_MS1) {
36817c478bd9Sstevel@tonic-gate flags &= ~ALLOW_MS1;
36827c478bd9Sstevel@tonic-gate flags |= ALLOW_MS2;
36837c478bd9Sstevel@tonic-gate continue;
36847c478bd9Sstevel@tonic-gate }
36857c478bd9Sstevel@tonic-gate goto bail_out;
36867c478bd9Sstevel@tonic-gate
36877c478bd9Sstevel@tonic-gate case 's':
36887c478bd9Sstevel@tonic-gate if (flags & ALLOW_END_ONLY)
36897c478bd9Sstevel@tonic-gate goto bail_out;
36907c478bd9Sstevel@tonic-gate if (flags & ALLOW_MS2) {
36917c478bd9Sstevel@tonic-gate flags &= ~ALLOW_MS2;
36927c478bd9Sstevel@tonic-gate flags |= ALLOW_END_ONLY;
36937c478bd9Sstevel@tonic-gate continue;
36947c478bd9Sstevel@tonic-gate }
36957c478bd9Sstevel@tonic-gate goto bail_out;
36967c478bd9Sstevel@tonic-gate
36977c478bd9Sstevel@tonic-gate case '0': case '1': case '2': case '3': case '4':
36987c478bd9Sstevel@tonic-gate case '5': case '6': case '7': case '8': case '9':
36997c478bd9Sstevel@tonic-gate overflow:
37007c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
37017c478bd9Sstevel@tonic-gate gettext("mkfs: value for %s overflowed\n"),
37027c478bd9Sstevel@tonic-gate param);
37037c478bd9Sstevel@tonic-gate while ((*cs != '\0') && (*cs != ','))
37047c478bd9Sstevel@tonic-gate cs++;
37057c478bd9Sstevel@tonic-gate string = cs;
37067c478bd9Sstevel@tonic-gate return (BIG);
37077c478bd9Sstevel@tonic-gate
37087c478bd9Sstevel@tonic-gate default:
37097c478bd9Sstevel@tonic-gate bail_out:
37107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
37117c478bd9Sstevel@tonic-gate "mkfs: bad numeric arg for %s: \"%s\"\n"),
37127c478bd9Sstevel@tonic-gate param, string);
37137c478bd9Sstevel@tonic-gate while ((*cs != '\0') && (*cs != ','))
37147c478bd9Sstevel@tonic-gate cs++;
37157c478bd9Sstevel@tonic-gate string = cs;
37167c478bd9Sstevel@tonic-gate if (d_value != NO_DEFAULT) {
37177c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
37187c478bd9Sstevel@tonic-gate gettext("mkfs: %s reset to default %lld\n"),
37197c478bd9Sstevel@tonic-gate param, d_value);
37207c478bd9Sstevel@tonic-gate return (d_value);
37217c478bd9Sstevel@tonic-gate }
37227c478bd9Sstevel@tonic-gate lockexit(2);
37237c478bd9Sstevel@tonic-gate
37247c478bd9Sstevel@tonic-gate }
37257c478bd9Sstevel@tonic-gate } /* never gets here */
37267c478bd9Sstevel@tonic-gate }
37277c478bd9Sstevel@tonic-gate
37287c478bd9Sstevel@tonic-gate /* match ************************************************************** */
37297c478bd9Sstevel@tonic-gate /* */
37307c478bd9Sstevel@tonic-gate /* Compare two text strings for equality */
37317c478bd9Sstevel@tonic-gate /* */
37327c478bd9Sstevel@tonic-gate /* Arg: s - pointer to string to match with a command arg */
37337c478bd9Sstevel@tonic-gate /* Global arg: string - pointer to command arg */
37347c478bd9Sstevel@tonic-gate /* */
37357c478bd9Sstevel@tonic-gate /* Return: 1 if match, 0 if no match */
37367c478bd9Sstevel@tonic-gate /* If match, also reset `string' to point to the text */
37377c478bd9Sstevel@tonic-gate /* that follows the matching text. */
37387c478bd9Sstevel@tonic-gate /* */
37397c478bd9Sstevel@tonic-gate /* ******************************************************************** */
37407c478bd9Sstevel@tonic-gate
37417c478bd9Sstevel@tonic-gate static int
match(char * s)37427c478bd9Sstevel@tonic-gate match(char *s)
37437c478bd9Sstevel@tonic-gate {
37447c478bd9Sstevel@tonic-gate char *cs;
37457c478bd9Sstevel@tonic-gate
37467c478bd9Sstevel@tonic-gate cs = string;
37477c478bd9Sstevel@tonic-gate while (*cs++ == *s) {
37487c478bd9Sstevel@tonic-gate if (*s++ == '\0') {
37497c478bd9Sstevel@tonic-gate goto true;
37507c478bd9Sstevel@tonic-gate }
37517c478bd9Sstevel@tonic-gate }
37527c478bd9Sstevel@tonic-gate if (*s != '\0') {
37537c478bd9Sstevel@tonic-gate return (0);
37547c478bd9Sstevel@tonic-gate }
37557c478bd9Sstevel@tonic-gate
37567c478bd9Sstevel@tonic-gate true:
37577c478bd9Sstevel@tonic-gate cs--;
37587c478bd9Sstevel@tonic-gate string = cs;
37597c478bd9Sstevel@tonic-gate return (1);
37607c478bd9Sstevel@tonic-gate }
37617c478bd9Sstevel@tonic-gate
37627c478bd9Sstevel@tonic-gate /*
37637c478bd9Sstevel@tonic-gate * GROWFS ROUTINES
37647c478bd9Sstevel@tonic-gate */
37657c478bd9Sstevel@tonic-gate
37667c478bd9Sstevel@tonic-gate /* ARGSUSED */
37677c478bd9Sstevel@tonic-gate void
lockexit(int exitstatus)37687c478bd9Sstevel@tonic-gate lockexit(int exitstatus)
37697c478bd9Sstevel@tonic-gate {
37707c478bd9Sstevel@tonic-gate if (Pflag) {
37717c478bd9Sstevel@tonic-gate /* the probe mode neither changes nor locks the filesystem */
37727c478bd9Sstevel@tonic-gate exit(exitstatus);
37737c478bd9Sstevel@tonic-gate }
37747c478bd9Sstevel@tonic-gate
37757c478bd9Sstevel@tonic-gate /*
37767c478bd9Sstevel@tonic-gate * flush the dirty cylinder group
37777c478bd9Sstevel@tonic-gate */
37787c478bd9Sstevel@tonic-gate if (inlockexit == 0) {
37797c478bd9Sstevel@tonic-gate inlockexit = 1;
37807c478bd9Sstevel@tonic-gate flcg();
37817c478bd9Sstevel@tonic-gate }
37827c478bd9Sstevel@tonic-gate
37837c478bd9Sstevel@tonic-gate if (aio_inited) {
37847c478bd9Sstevel@tonic-gate flush_writes();
37857c478bd9Sstevel@tonic-gate }
37867c478bd9Sstevel@tonic-gate
37877c478bd9Sstevel@tonic-gate /*
37887c478bd9Sstevel@tonic-gate * make sure the file system is unlocked before exiting
37897c478bd9Sstevel@tonic-gate */
37907c478bd9Sstevel@tonic-gate if ((inlockexit == 1) && (!isbad)) {
37917c478bd9Sstevel@tonic-gate inlockexit = 2;
37927c478bd9Sstevel@tonic-gate ulockfs();
37937c478bd9Sstevel@tonic-gate /*
37947c478bd9Sstevel@tonic-gate * if logging was enabled, then re-enable it
37957c478bd9Sstevel@tonic-gate */
37967c478bd9Sstevel@tonic-gate if (waslog) {
37977c478bd9Sstevel@tonic-gate if (rl_log_control(fsys, _FIOLOGENABLE) != RL_SUCCESS) {
37987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
37997c478bd9Sstevel@tonic-gate "failed to re-enable logging\n"));
38007c478bd9Sstevel@tonic-gate }
38017c478bd9Sstevel@tonic-gate }
38027c478bd9Sstevel@tonic-gate } else if (grow) {
38037c478bd9Sstevel@tonic-gate if (isbad) {
38047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38057c478bd9Sstevel@tonic-gate "Filesystem is currently inconsistent. It "
38067c478bd9Sstevel@tonic-gate "must be repaired with fsck(1M)\nbefore being "
38077c478bd9Sstevel@tonic-gate "used. Use the following command to "
3808d50c8f90Svsakar "do this:\n\n\tfsck %s\n\n"), fsys);
38097c478bd9Sstevel@tonic-gate
38107c478bd9Sstevel@tonic-gate if (ismounted) {
38117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38127c478bd9Sstevel@tonic-gate "You will be told that the filesystem "
38137c478bd9Sstevel@tonic-gate "is already mounted, and asked if you\n"
38147c478bd9Sstevel@tonic-gate "wish to continue. Answer `yes' to "
38157c478bd9Sstevel@tonic-gate "this question.\n\n"));
38167c478bd9Sstevel@tonic-gate }
38177c478bd9Sstevel@tonic-gate
38187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
3819d50c8f90Svsakar "One problem should be reported, that the summary "
3820d50c8f90Svsakar "information is bad.\nYou will then be asked if it "
3821d50c8f90Svsakar "should be salvaged. Answer `yes' to\nthis "
3822d50c8f90Svsakar "question.\n\n"));
38237c478bd9Sstevel@tonic-gate }
38247c478bd9Sstevel@tonic-gate
38257c478bd9Sstevel@tonic-gate if (ismounted) {
38267c478bd9Sstevel@tonic-gate /*
38277c478bd9Sstevel@tonic-gate * In theory, there's no way to get here without
38287c478bd9Sstevel@tonic-gate * isbad also being set, but be robust in the
38297c478bd9Sstevel@tonic-gate * face of future code changes.
38307c478bd9Sstevel@tonic-gate */
38317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38327c478bd9Sstevel@tonic-gate "The filesystem is currently mounted "
38337c478bd9Sstevel@tonic-gate "read-only and write-locked. "));
38347c478bd9Sstevel@tonic-gate if (isbad) {
38357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38367c478bd9Sstevel@tonic-gate "After\nrunning fsck, unlock the "
38377c478bd9Sstevel@tonic-gate "filesystem and "));
38387c478bd9Sstevel@tonic-gate } else {
38397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38407c478bd9Sstevel@tonic-gate "Unlock the filesystem\nand "));
38417c478bd9Sstevel@tonic-gate }
38427c478bd9Sstevel@tonic-gate
38437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
38447c478bd9Sstevel@tonic-gate "re-enable writing with\nthe following "
3845d50c8f90Svsakar "command:\n\n\tlockfs -u %s\n\n"), directory);
38467c478bd9Sstevel@tonic-gate }
38477c478bd9Sstevel@tonic-gate }
38487c478bd9Sstevel@tonic-gate
38497c478bd9Sstevel@tonic-gate exit(exitstatus);
38507c478bd9Sstevel@tonic-gate }
38517c478bd9Sstevel@tonic-gate
38527c478bd9Sstevel@tonic-gate void
randomgeneration()38537c478bd9Sstevel@tonic-gate randomgeneration()
38547c478bd9Sstevel@tonic-gate {
38557c478bd9Sstevel@tonic-gate int i;
38567c478bd9Sstevel@tonic-gate struct dinode *dp;
38577c478bd9Sstevel@tonic-gate
38587c478bd9Sstevel@tonic-gate /*
38597c478bd9Sstevel@tonic-gate * always perform fsirand(1) function... newfs will notice that
38607c478bd9Sstevel@tonic-gate * the inodes have been randomized and will not call fsirand itself
38617c478bd9Sstevel@tonic-gate */
38627c478bd9Sstevel@tonic-gate for (i = 0, dp = zino; i < sblock.fs_inopb; ++i, ++dp)
38637c478bd9Sstevel@tonic-gate IRANDOMIZE(&dp->di_ic);
38647c478bd9Sstevel@tonic-gate }
38657c478bd9Sstevel@tonic-gate
38667c478bd9Sstevel@tonic-gate /*
38677c478bd9Sstevel@tonic-gate * Check the size of the summary information.
38687c478bd9Sstevel@tonic-gate * Fields in sblock are not changed in this function.
38697c478bd9Sstevel@tonic-gate *
38707c478bd9Sstevel@tonic-gate * For an 8K filesystem block, the maximum number of cylinder groups is 16384.
38717c478bd9Sstevel@tonic-gate * MAXCSBUFS {32} * 8K {FS block size}
38727c478bd9Sstevel@tonic-gate * divided by (sizeof csum) {16}
38737c478bd9Sstevel@tonic-gate *
38747c478bd9Sstevel@tonic-gate * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32,
38757c478bd9Sstevel@tonic-gate * this is the only place where it's referenced.
38767c478bd9Sstevel@tonic-gate */
38777c478bd9Sstevel@tonic-gate void
checksummarysize()38787c478bd9Sstevel@tonic-gate checksummarysize()
38797c478bd9Sstevel@tonic-gate {
38807c478bd9Sstevel@tonic-gate diskaddr_t dmax;
38817c478bd9Sstevel@tonic-gate diskaddr_t dmin;
38827c478bd9Sstevel@tonic-gate int64_t cg0frags;
38837c478bd9Sstevel@tonic-gate int64_t cg0blocks;
38847c478bd9Sstevel@tonic-gate int64_t maxncg;
38857c478bd9Sstevel@tonic-gate int64_t maxfrags;
38867c478bd9Sstevel@tonic-gate uint64_t fs_size;
38877c478bd9Sstevel@tonic-gate uint64_t maxfs_blocks; /* filesystem blocks for max filesystem size */
38887c478bd9Sstevel@tonic-gate
38897c478bd9Sstevel@tonic-gate /*
38907c478bd9Sstevel@tonic-gate * compute the maximum summary info size
38917c478bd9Sstevel@tonic-gate */
38927c478bd9Sstevel@tonic-gate dmin = cgdmin(&sblock, 0);
38937c478bd9Sstevel@tonic-gate dmax = cgbase(&sblock, 0) + sblock.fs_fpg;
38947c478bd9Sstevel@tonic-gate fs_size = (grow) ? grow_fs_size : sblock.fs_size;
38957c478bd9Sstevel@tonic-gate if (dmax > fs_size)
38967c478bd9Sstevel@tonic-gate dmax = fs_size;
38977c478bd9Sstevel@tonic-gate cg0frags = dmax - dmin;
38987c478bd9Sstevel@tonic-gate cg0blocks = cg0frags / sblock.fs_frag;
38997c478bd9Sstevel@tonic-gate cg0frags = cg0blocks * sblock.fs_frag;
39007c478bd9Sstevel@tonic-gate maxncg = (longlong_t)cg0blocks *
39017c478bd9Sstevel@tonic-gate (longlong_t)(sblock.fs_bsize / sizeof (struct csum));
39027c478bd9Sstevel@tonic-gate
39037c478bd9Sstevel@tonic-gate maxfs_blocks = FS_MAX;
39047c478bd9Sstevel@tonic-gate
39057c478bd9Sstevel@tonic-gate if (maxncg > ((longlong_t)maxfs_blocks / (longlong_t)sblock.fs_fpg) + 1)
39067c478bd9Sstevel@tonic-gate maxncg = ((longlong_t)maxfs_blocks /
39077c478bd9Sstevel@tonic-gate (longlong_t)sblock.fs_fpg) + 1;
39087c478bd9Sstevel@tonic-gate
39097c478bd9Sstevel@tonic-gate maxfrags = maxncg * (longlong_t)sblock.fs_fpg;
39107c478bd9Sstevel@tonic-gate
39117c478bd9Sstevel@tonic-gate if (maxfrags > maxfs_blocks)
39127c478bd9Sstevel@tonic-gate maxfrags = maxfs_blocks;
39137c478bd9Sstevel@tonic-gate
39147c478bd9Sstevel@tonic-gate
39157c478bd9Sstevel@tonic-gate /*
39167c478bd9Sstevel@tonic-gate * remember for later processing in extendsummaryinfo()
39177c478bd9Sstevel@tonic-gate */
39187c478bd9Sstevel@tonic-gate if (test)
39197c478bd9Sstevel@tonic-gate grow_sifrag = dmin + (cg0blocks * sblock.fs_frag);
39207c478bd9Sstevel@tonic-gate if (testfrags == 0)
39217c478bd9Sstevel@tonic-gate testfrags = cg0frags;
39227c478bd9Sstevel@tonic-gate if (testforce)
39237c478bd9Sstevel@tonic-gate if (testfrags > cg0frags) {
39247c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
39257c478bd9Sstevel@tonic-gate gettext("Too many test frags (%lld); "
39267c478bd9Sstevel@tonic-gate "try %lld\n"), testfrags, cg0frags);
39277c478bd9Sstevel@tonic-gate lockexit(32);
39287c478bd9Sstevel@tonic-gate }
39297c478bd9Sstevel@tonic-gate
39307c478bd9Sstevel@tonic-gate /*
39317c478bd9Sstevel@tonic-gate * if summary info is too large (too many cg's) tell the user and exit
39327c478bd9Sstevel@tonic-gate */
39337c478bd9Sstevel@tonic-gate if ((longlong_t)sblock.fs_size > maxfrags) {
39347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
39357c478bd9Sstevel@tonic-gate "Too many cylinder groups with %llu sectors;\n try "
39367c478bd9Sstevel@tonic-gate "increasing cgsize, or decreasing fssize to %llu\n"),
39377c478bd9Sstevel@tonic-gate fsbtodb(&sblock, (uint64_t)sblock.fs_size),
39387c478bd9Sstevel@tonic-gate fsbtodb(&sblock, (uint64_t)maxfrags));
39397c478bd9Sstevel@tonic-gate lockexit(32);
39407c478bd9Sstevel@tonic-gate }
39417c478bd9Sstevel@tonic-gate }
39427c478bd9Sstevel@tonic-gate
39437c478bd9Sstevel@tonic-gate /*
39446451fdbcSvsakar * checksblock() has two uses:
39456451fdbcSvsakar * - One is to sanity test the superblock and is used when newfs(1M)
39466451fdbcSvsakar * is invoked with the "-N" option. If any discrepancy was found,
39476451fdbcSvsakar * just return whatever error was found and do not exit.
39486451fdbcSvsakar * - the other use of it is in places where you expect the superblock
39496451fdbcSvsakar * to be sane, and if it isn't, then we exit.
39506451fdbcSvsakar * Which of the above two actions to take is indicated with the second argument.
39517c478bd9Sstevel@tonic-gate */
39526451fdbcSvsakar
39536451fdbcSvsakar int
checksblock(struct fs sb,int proceed)39546451fdbcSvsakar checksblock(struct fs sb, int proceed)
39556451fdbcSvsakar {
39566451fdbcSvsakar int err = 0;
39576451fdbcSvsakar char *errmsg;
39586451fdbcSvsakar
39596451fdbcSvsakar if ((sb.fs_magic != FS_MAGIC) && (sb.fs_magic != MTB_UFS_MAGIC)) {
39606451fdbcSvsakar err = 1;
39616451fdbcSvsakar errmsg = gettext("Bad superblock; magic number wrong\n");
39626451fdbcSvsakar } else if ((sb.fs_magic == FS_MAGIC &&
39636451fdbcSvsakar (sb.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
39646451fdbcSvsakar sb.fs_version != UFS_VERSION_MIN)) ||
39656451fdbcSvsakar (sb.fs_magic == MTB_UFS_MAGIC &&
39666451fdbcSvsakar (sb.fs_version > MTB_UFS_VERSION_1 ||
39676451fdbcSvsakar sb.fs_version < MTB_UFS_VERSION_MIN))) {
39686451fdbcSvsakar err = 2;
39696451fdbcSvsakar errmsg = gettext("Unrecognized version of UFS\n");
39706451fdbcSvsakar } else if (sb.fs_ncg < 1) {
39716451fdbcSvsakar err = 3;
39726451fdbcSvsakar errmsg = gettext("Bad superblock; ncg out of range\n");
39736451fdbcSvsakar } else if (sb.fs_cpg < 1) {
39746451fdbcSvsakar err = 4;
39756451fdbcSvsakar errmsg = gettext("Bad superblock; cpg out of range\n");
39766451fdbcSvsakar } else if (sb.fs_ncg * sb.fs_cpg < sb.fs_ncyl ||
39776451fdbcSvsakar (sb.fs_ncg - 1) * sb.fs_cpg >= sb.fs_ncyl) {
39786451fdbcSvsakar err = 5;
39796451fdbcSvsakar errmsg = gettext("Bad superblock; ncyl out of range\n");
39806451fdbcSvsakar } else if (sb.fs_sbsize <= 0 || sb.fs_sbsize > sb.fs_bsize) {
39816451fdbcSvsakar err = 6;
3982d50c8f90Svsakar errmsg = gettext("Bad superblock; superblock size out of "
3983d50c8f90Svsakar "range\n");
39847c478bd9Sstevel@tonic-gate }
39857c478bd9Sstevel@tonic-gate
39866451fdbcSvsakar if (proceed) {
39876451fdbcSvsakar if (err) dprintf(("%s", errmsg));
39886451fdbcSvsakar return (err);
39897c478bd9Sstevel@tonic-gate }
39907c478bd9Sstevel@tonic-gate
39916451fdbcSvsakar if (err) {
39926451fdbcSvsakar fprintf(stderr, "%s", errmsg);
39937c478bd9Sstevel@tonic-gate lockexit(32);
39947c478bd9Sstevel@tonic-gate }
3995d1a180b0Smaheshvs return (32);
39967c478bd9Sstevel@tonic-gate }
39977c478bd9Sstevel@tonic-gate
39987c478bd9Sstevel@tonic-gate /*
39997c478bd9Sstevel@tonic-gate * Roll the embedded log, if any, and set up the global variables
40007c478bd9Sstevel@tonic-gate * islog, islogok and isufslog.
40017c478bd9Sstevel@tonic-gate */
40027c478bd9Sstevel@tonic-gate static void
logsetup(char * devstr)40037c478bd9Sstevel@tonic-gate logsetup(char *devstr)
40047c478bd9Sstevel@tonic-gate {
40057c478bd9Sstevel@tonic-gate void *buf, *ud_buf;
40067c478bd9Sstevel@tonic-gate extent_block_t *ebp;
40077c478bd9Sstevel@tonic-gate ml_unit_t *ul;
40087c478bd9Sstevel@tonic-gate ml_odunit_t *ud;
40097c478bd9Sstevel@tonic-gate
40107c478bd9Sstevel@tonic-gate /*
40117c478bd9Sstevel@tonic-gate * Does the superblock indicate that we are supposed to have a log ?
40127c478bd9Sstevel@tonic-gate */
40137c478bd9Sstevel@tonic-gate if (sblock.fs_logbno == 0) {
40147c478bd9Sstevel@tonic-gate /*
40157c478bd9Sstevel@tonic-gate * No log present, nothing to do.
40167c478bd9Sstevel@tonic-gate */
40177c478bd9Sstevel@tonic-gate islogok = 0;
40187c478bd9Sstevel@tonic-gate islog = 0;
40197c478bd9Sstevel@tonic-gate isufslog = 0;
40207c478bd9Sstevel@tonic-gate return;
40217c478bd9Sstevel@tonic-gate } else {
40227c478bd9Sstevel@tonic-gate /*
40237c478bd9Sstevel@tonic-gate * There's a log in a yet unknown state, attempt to roll it.
40247c478bd9Sstevel@tonic-gate */
40257c478bd9Sstevel@tonic-gate islog = 1;
40267c478bd9Sstevel@tonic-gate islogok = 0;
40277c478bd9Sstevel@tonic-gate isufslog = 0;
40287c478bd9Sstevel@tonic-gate
40297c478bd9Sstevel@tonic-gate /*
40307c478bd9Sstevel@tonic-gate * We failed to roll the log, bail out.
40317c478bd9Sstevel@tonic-gate */
40327c478bd9Sstevel@tonic-gate if (rl_roll_log(devstr) != RL_SUCCESS)
40337c478bd9Sstevel@tonic-gate return;
40347c478bd9Sstevel@tonic-gate
40357c478bd9Sstevel@tonic-gate isufslog = 1;
40367c478bd9Sstevel@tonic-gate
40377c478bd9Sstevel@tonic-gate /* log is not okay; check the fs */
40387c478bd9Sstevel@tonic-gate if ((FSOKAY != (sblock.fs_state + sblock.fs_time)) ||
40397c478bd9Sstevel@tonic-gate (sblock.fs_clean != FSLOG))
40407c478bd9Sstevel@tonic-gate return;
40417c478bd9Sstevel@tonic-gate
40427c478bd9Sstevel@tonic-gate /* get the log allocation block */
40437c478bd9Sstevel@tonic-gate buf = (void *)malloc(DEV_BSIZE);
40447c478bd9Sstevel@tonic-gate if (buf == (void *) NULL)
40457c478bd9Sstevel@tonic-gate return;
40467c478bd9Sstevel@tonic-gate
40477c478bd9Sstevel@tonic-gate ud_buf = (void *)malloc(DEV_BSIZE);
40487c478bd9Sstevel@tonic-gate if (ud_buf == (void *) NULL) {
40497c478bd9Sstevel@tonic-gate free(buf);
40507c478bd9Sstevel@tonic-gate return;
40517c478bd9Sstevel@tonic-gate }
40527c478bd9Sstevel@tonic-gate
40537c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)logbtodb(&sblock, sblock.fs_logbno),
40547c478bd9Sstevel@tonic-gate DEV_BSIZE, buf);
40557c478bd9Sstevel@tonic-gate ebp = (extent_block_t *)buf;
40567c478bd9Sstevel@tonic-gate
40577c478bd9Sstevel@tonic-gate /* log allocation block is not okay; check the fs */
40587c478bd9Sstevel@tonic-gate if (ebp->type != LUFS_EXTENTS) {
40597c478bd9Sstevel@tonic-gate free(buf);
40607c478bd9Sstevel@tonic-gate free(ud_buf);
40617c478bd9Sstevel@tonic-gate return;
40627c478bd9Sstevel@tonic-gate }
40637c478bd9Sstevel@tonic-gate
40647c478bd9Sstevel@tonic-gate /* get the log state block(s) */
40657c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)logbtodb(&sblock, ebp->extents[0].pbno),
40667c478bd9Sstevel@tonic-gate DEV_BSIZE, ud_buf);
40677c478bd9Sstevel@tonic-gate ud = (ml_odunit_t *)ud_buf;
40687c478bd9Sstevel@tonic-gate ul = (ml_unit_t *)malloc(sizeof (*ul));
40697c478bd9Sstevel@tonic-gate ul->un_ondisk = *ud;
40707c478bd9Sstevel@tonic-gate
40717c478bd9Sstevel@tonic-gate /* log state is okay */
40727c478bd9Sstevel@tonic-gate if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
40737c478bd9Sstevel@tonic-gate (ul->un_version == LUFS_VERSION_LATEST) &&
40747c478bd9Sstevel@tonic-gate (ul->un_badlog == 0))
40757c478bd9Sstevel@tonic-gate islogok = 1;
40767c478bd9Sstevel@tonic-gate free(ud_buf);
40777c478bd9Sstevel@tonic-gate free(buf);
40787c478bd9Sstevel@tonic-gate free(ul);
40797c478bd9Sstevel@tonic-gate }
40807c478bd9Sstevel@tonic-gate }
40817c478bd9Sstevel@tonic-gate
40827c478bd9Sstevel@tonic-gate void
growinit(char * devstr)40837c478bd9Sstevel@tonic-gate growinit(char *devstr)
40847c478bd9Sstevel@tonic-gate {
40857c478bd9Sstevel@tonic-gate int i;
40867c478bd9Sstevel@tonic-gate char buf[DEV_BSIZE];
40877c478bd9Sstevel@tonic-gate
40887c478bd9Sstevel@tonic-gate /*
40897c478bd9Sstevel@tonic-gate * Read and verify the superblock
40907c478bd9Sstevel@tonic-gate */
40917c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
40926451fdbcSvsakar (void) checksblock(sblock, 0);
40937c478bd9Sstevel@tonic-gate if (sblock.fs_postblformat != FS_DYNAMICPOSTBLFMT) {
40947c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
40957c478bd9Sstevel@tonic-gate gettext("old file system format; can't growfs\n"));
40967c478bd9Sstevel@tonic-gate lockexit(32);
40977c478bd9Sstevel@tonic-gate }
40987c478bd9Sstevel@tonic-gate
40997c478bd9Sstevel@tonic-gate /*
41007c478bd9Sstevel@tonic-gate * can't shrink a file system
41017c478bd9Sstevel@tonic-gate */
41027c478bd9Sstevel@tonic-gate grow_fssize = fsbtodb(&sblock, (uint64_t)sblock.fs_size);
41037c478bd9Sstevel@tonic-gate if (fssize_db < grow_fssize) {
41047c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
41057c478bd9Sstevel@tonic-gate gettext("%lld sectors < current size of %lld sectors\n"),
41067c478bd9Sstevel@tonic-gate fssize_db, grow_fssize);
41077c478bd9Sstevel@tonic-gate lockexit(32);
41087c478bd9Sstevel@tonic-gate }
41097c478bd9Sstevel@tonic-gate
41107c478bd9Sstevel@tonic-gate /*
41117c478bd9Sstevel@tonic-gate * can't grow a system to over a terabyte unless it was set up
41127c478bd9Sstevel@tonic-gate * as an MTB UFS file system.
41137c478bd9Sstevel@tonic-gate */
41147c478bd9Sstevel@tonic-gate if (mtb == 'y' && sblock.fs_magic != MTB_UFS_MAGIC) {
41157c478bd9Sstevel@tonic-gate if (fssize_db >= SECTORS_PER_TERABYTE) {
41167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
41177c478bd9Sstevel@tonic-gate "File system was not set up with the multi-terabyte format.\n"));
41187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
41197c478bd9Sstevel@tonic-gate "Its size cannot be increased to a terabyte or more.\n"));
41207c478bd9Sstevel@tonic-gate } else {
41217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
41227c478bd9Sstevel@tonic-gate "Cannot convert file system to multi-terabyte format.\n"));
41237c478bd9Sstevel@tonic-gate }
41247c478bd9Sstevel@tonic-gate lockexit(32);
41257c478bd9Sstevel@tonic-gate }
41267c478bd9Sstevel@tonic-gate
41277c478bd9Sstevel@tonic-gate logsetup(devstr);
41287c478bd9Sstevel@tonic-gate
41297c478bd9Sstevel@tonic-gate /*
41307c478bd9Sstevel@tonic-gate * can't growfs when logging device has errors
41317c478bd9Sstevel@tonic-gate */
41327c478bd9Sstevel@tonic-gate if ((islog && !islogok) ||
41337c478bd9Sstevel@tonic-gate ((FSOKAY == (sblock.fs_state + sblock.fs_time)) &&
41347c478bd9Sstevel@tonic-gate (sblock.fs_clean == FSLOG && !islog))) {
41357c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
41367c478bd9Sstevel@tonic-gate gettext("logging device has errors; can't growfs\n"));
41377c478bd9Sstevel@tonic-gate lockexit(32);
41387c478bd9Sstevel@tonic-gate }
41397c478bd9Sstevel@tonic-gate
41407c478bd9Sstevel@tonic-gate /*
41417c478bd9Sstevel@tonic-gate * disable ufs logging for growing
41427c478bd9Sstevel@tonic-gate */
41437c478bd9Sstevel@tonic-gate if (isufslog) {
41447c478bd9Sstevel@tonic-gate if (rl_log_control(devstr, _FIOLOGDISABLE) != RL_SUCCESS) {
41457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
41467c478bd9Sstevel@tonic-gate "failed to disable logging\n"));
41477c478bd9Sstevel@tonic-gate lockexit(32);
41487c478bd9Sstevel@tonic-gate }
41497c478bd9Sstevel@tonic-gate islog = 0;
41507c478bd9Sstevel@tonic-gate waslog = 1;
41517c478bd9Sstevel@tonic-gate }
41527c478bd9Sstevel@tonic-gate
41537c478bd9Sstevel@tonic-gate /*
41547c478bd9Sstevel@tonic-gate * if mounted write lock the file system to be grown
41557c478bd9Sstevel@tonic-gate */
41567c478bd9Sstevel@tonic-gate if (ismounted)
41577c478bd9Sstevel@tonic-gate wlockfs();
41587c478bd9Sstevel@tonic-gate
41597c478bd9Sstevel@tonic-gate /*
41607c478bd9Sstevel@tonic-gate * refresh dynamic superblock state - disabling logging will have
41617c478bd9Sstevel@tonic-gate * changed the amount of free space available in the file system
41627c478bd9Sstevel@tonic-gate */
41637c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
41647c478bd9Sstevel@tonic-gate
41657c478bd9Sstevel@tonic-gate /*
41667c478bd9Sstevel@tonic-gate * make sure device is big enough
41677c478bd9Sstevel@tonic-gate */
41687c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
41697c478bd9Sstevel@tonic-gate wtfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
41707c478bd9Sstevel@tonic-gate
41717c478bd9Sstevel@tonic-gate /*
41727c478bd9Sstevel@tonic-gate * read current summary information
41737c478bd9Sstevel@tonic-gate */
41747c478bd9Sstevel@tonic-gate grow_fscs = read_summaryinfo(&sblock);
41757c478bd9Sstevel@tonic-gate
41767c478bd9Sstevel@tonic-gate /*
41777c478bd9Sstevel@tonic-gate * save some current size related fields from the superblock
41787c478bd9Sstevel@tonic-gate * These are used in extendsummaryinfo()
41797c478bd9Sstevel@tonic-gate */
41807c478bd9Sstevel@tonic-gate grow_fs_size = sblock.fs_size;
41817c478bd9Sstevel@tonic-gate grow_fs_ncg = sblock.fs_ncg;
41827c478bd9Sstevel@tonic-gate grow_fs_csaddr = (diskaddr_t)sblock.fs_csaddr;
41837c478bd9Sstevel@tonic-gate grow_fs_cssize = sblock.fs_cssize;
41847c478bd9Sstevel@tonic-gate
41857c478bd9Sstevel@tonic-gate /*
41867c478bd9Sstevel@tonic-gate * save and reset the clean flag
41877c478bd9Sstevel@tonic-gate */
41887c478bd9Sstevel@tonic-gate if (FSOKAY == (sblock.fs_state + sblock.fs_time))
41897c478bd9Sstevel@tonic-gate grow_fs_clean = sblock.fs_clean;
41907c478bd9Sstevel@tonic-gate else
41917c478bd9Sstevel@tonic-gate grow_fs_clean = FSBAD;
41927c478bd9Sstevel@tonic-gate sblock.fs_clean = FSBAD;
41937c478bd9Sstevel@tonic-gate sblock.fs_state = FSOKAY - sblock.fs_time;
41947c478bd9Sstevel@tonic-gate isbad = 1;
41957c478bd9Sstevel@tonic-gate wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
41967c478bd9Sstevel@tonic-gate }
41977c478bd9Sstevel@tonic-gate
41987c478bd9Sstevel@tonic-gate void
checkdev(char * rdev,char * bdev)41997c478bd9Sstevel@tonic-gate checkdev(char *rdev, char *bdev)
42007c478bd9Sstevel@tonic-gate {
42017c478bd9Sstevel@tonic-gate struct stat64 statarea;
42027c478bd9Sstevel@tonic-gate
42037c478bd9Sstevel@tonic-gate if (stat64(bdev, &statarea) < 0) {
42047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't check mount point; "));
42057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't stat %s\n"), bdev);
42067c478bd9Sstevel@tonic-gate lockexit(32);
42077c478bd9Sstevel@tonic-gate }
42087c478bd9Sstevel@tonic-gate if ((statarea.st_mode & S_IFMT) != S_IFBLK) {
42097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
42107c478bd9Sstevel@tonic-gate "can't check mount point; %s is not a block device\n"),
42117c478bd9Sstevel@tonic-gate bdev);
42127c478bd9Sstevel@tonic-gate lockexit(32);
42137c478bd9Sstevel@tonic-gate }
42147c478bd9Sstevel@tonic-gate if (stat64(rdev, &statarea) < 0) {
42157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't stat %s\n"), rdev);
42167c478bd9Sstevel@tonic-gate lockexit(32);
42177c478bd9Sstevel@tonic-gate }
42187c478bd9Sstevel@tonic-gate if ((statarea.st_mode & S_IFMT) != S_IFCHR) {
42197c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
42207c478bd9Sstevel@tonic-gate gettext("%s is not a character device\n"), rdev);
42217c478bd9Sstevel@tonic-gate lockexit(32);
42227c478bd9Sstevel@tonic-gate }
42237c478bd9Sstevel@tonic-gate }
42247c478bd9Sstevel@tonic-gate
42257c478bd9Sstevel@tonic-gate void
checkmount(struct mnttab * mntp,char * bdevname)42267c478bd9Sstevel@tonic-gate checkmount(struct mnttab *mntp, char *bdevname)
42277c478bd9Sstevel@tonic-gate {
42287c478bd9Sstevel@tonic-gate struct stat64 statdir;
42297c478bd9Sstevel@tonic-gate struct stat64 statdev;
42307c478bd9Sstevel@tonic-gate
42317c478bd9Sstevel@tonic-gate if (strcmp(bdevname, mntp->mnt_special) == 0) {
42327c478bd9Sstevel@tonic-gate if (stat64(mntp->mnt_mountp, &statdir) == -1) {
42337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't stat %s\n"),
42347c478bd9Sstevel@tonic-gate mntp->mnt_mountp);
42357c478bd9Sstevel@tonic-gate lockexit(32);
42367c478bd9Sstevel@tonic-gate }
42377c478bd9Sstevel@tonic-gate if (stat64(mntp->mnt_special, &statdev) == -1) {
42387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("can't stat %s\n"),
42397c478bd9Sstevel@tonic-gate mntp->mnt_special);
42407c478bd9Sstevel@tonic-gate lockexit(32);
42417c478bd9Sstevel@tonic-gate }
42427c478bd9Sstevel@tonic-gate if (statdir.st_dev != statdev.st_rdev) {
42437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
42447c478bd9Sstevel@tonic-gate "%s is not mounted on %s; mnttab(4) wrong\n"),
42457c478bd9Sstevel@tonic-gate mntp->mnt_special, mntp->mnt_mountp);
42467c478bd9Sstevel@tonic-gate lockexit(32);
42477c478bd9Sstevel@tonic-gate }
42487c478bd9Sstevel@tonic-gate ismounted = 1;
42497c478bd9Sstevel@tonic-gate if (directory) {
42507c478bd9Sstevel@tonic-gate if (strcmp(mntp->mnt_mountp, directory) != 0) {
42517c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
42527c478bd9Sstevel@tonic-gate gettext("%s is mounted on %s, not %s\n"),
42537c478bd9Sstevel@tonic-gate bdevname, mntp->mnt_mountp, directory);
42547c478bd9Sstevel@tonic-gate lockexit(32);
42557c478bd9Sstevel@tonic-gate }
42567c478bd9Sstevel@tonic-gate } else {
42577c478bd9Sstevel@tonic-gate if (grow)
42587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
42597c478bd9Sstevel@tonic-gate "%s is mounted on %s; can't growfs\n"),
42607c478bd9Sstevel@tonic-gate bdevname, mntp->mnt_mountp);
42617c478bd9Sstevel@tonic-gate else
42627c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
42637c478bd9Sstevel@tonic-gate gettext("%s is mounted, can't mkfs\n"),
42647c478bd9Sstevel@tonic-gate bdevname);
42657c478bd9Sstevel@tonic-gate lockexit(32);
42667c478bd9Sstevel@tonic-gate }
42677c478bd9Sstevel@tonic-gate }
42687c478bd9Sstevel@tonic-gate }
42697c478bd9Sstevel@tonic-gate
42707c478bd9Sstevel@tonic-gate struct dinode *dibuf = 0;
42717c478bd9Sstevel@tonic-gate diskaddr_t difrag = 0;
42727c478bd9Sstevel@tonic-gate
42737c478bd9Sstevel@tonic-gate struct dinode *
gdinode(ino_t ino)42747c478bd9Sstevel@tonic-gate gdinode(ino_t ino)
42757c478bd9Sstevel@tonic-gate {
42767c478bd9Sstevel@tonic-gate /*
42777c478bd9Sstevel@tonic-gate * read the block of inodes containing inode number ino
42787c478bd9Sstevel@tonic-gate */
42797c478bd9Sstevel@tonic-gate if (dibuf == 0)
42807c478bd9Sstevel@tonic-gate dibuf = (struct dinode *)malloc((unsigned)sblock.fs_bsize);
42817c478bd9Sstevel@tonic-gate if (itod(&sblock, ino) != difrag) {
42827c478bd9Sstevel@tonic-gate difrag = itod(&sblock, ino);
42837c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)difrag), (int)sblock.fs_bsize,
42847c478bd9Sstevel@tonic-gate (char *)dibuf);
42857c478bd9Sstevel@tonic-gate }
42867c478bd9Sstevel@tonic-gate return (dibuf + (ino % INOPB(&sblock)));
42877c478bd9Sstevel@tonic-gate }
42887c478bd9Sstevel@tonic-gate
42897c478bd9Sstevel@tonic-gate /*
42907c478bd9Sstevel@tonic-gate * structure that manages the frags we need for extended summary info
42917c478bd9Sstevel@tonic-gate * These frags can be:
42927c478bd9Sstevel@tonic-gate * free
42937c478bd9Sstevel@tonic-gate * data block
42947c478bd9Sstevel@tonic-gate * alloc block
42957c478bd9Sstevel@tonic-gate */
42967c478bd9Sstevel@tonic-gate struct csfrag {
42977c478bd9Sstevel@tonic-gate struct csfrag *next; /* next entry */
42987c478bd9Sstevel@tonic-gate daddr32_t ofrag; /* old frag */
42997c478bd9Sstevel@tonic-gate daddr32_t nfrag; /* new frag */
43007c478bd9Sstevel@tonic-gate long cylno; /* cylno of nfrag */
43017c478bd9Sstevel@tonic-gate long frags; /* number of frags */
43027c478bd9Sstevel@tonic-gate long size; /* size in bytes */
43037c478bd9Sstevel@tonic-gate ino_t ino; /* inode number */
43047c478bd9Sstevel@tonic-gate long fixed; /* Boolean - Already fixed? */
43057c478bd9Sstevel@tonic-gate };
43067c478bd9Sstevel@tonic-gate struct csfrag *csfrag; /* state unknown */
43077c478bd9Sstevel@tonic-gate struct csfrag *csfragino; /* frags belonging to an inode */
43087c478bd9Sstevel@tonic-gate struct csfrag *csfragfree; /* frags that are free */
43097c478bd9Sstevel@tonic-gate
43107c478bd9Sstevel@tonic-gate daddr32_t maxcsfrag = 0; /* maximum in range */
43117c478bd9Sstevel@tonic-gate daddr32_t mincsfrag = 0x7fffffff; /* minimum in range */
43127c478bd9Sstevel@tonic-gate
43137c478bd9Sstevel@tonic-gate int
csfraginrange(daddr32_t frag)43147c478bd9Sstevel@tonic-gate csfraginrange(daddr32_t frag)
43157c478bd9Sstevel@tonic-gate {
43167c478bd9Sstevel@tonic-gate return ((frag >= mincsfrag) && (frag <= maxcsfrag));
43177c478bd9Sstevel@tonic-gate }
43187c478bd9Sstevel@tonic-gate
43197c478bd9Sstevel@tonic-gate struct csfrag *
findcsfrag(daddr32_t frag,struct csfrag ** cfap)43207c478bd9Sstevel@tonic-gate findcsfrag(daddr32_t frag, struct csfrag **cfap)
43217c478bd9Sstevel@tonic-gate {
43227c478bd9Sstevel@tonic-gate struct csfrag *cfp;
43237c478bd9Sstevel@tonic-gate
43247c478bd9Sstevel@tonic-gate if (!csfraginrange(frag))
43257c478bd9Sstevel@tonic-gate return (NULL);
43267c478bd9Sstevel@tonic-gate
43277c478bd9Sstevel@tonic-gate for (cfp = *cfap; cfp; cfp = cfp->next)
43287c478bd9Sstevel@tonic-gate if (cfp->ofrag == frag)
43297c478bd9Sstevel@tonic-gate return (cfp);
43307c478bd9Sstevel@tonic-gate return (NULL);
43317c478bd9Sstevel@tonic-gate }
43327c478bd9Sstevel@tonic-gate
43337c478bd9Sstevel@tonic-gate void
checkindirect(ino_t ino,daddr32_t * fragsp,daddr32_t frag,int level)43347c478bd9Sstevel@tonic-gate checkindirect(ino_t ino, daddr32_t *fragsp, daddr32_t frag, int level)
43357c478bd9Sstevel@tonic-gate {
43367c478bd9Sstevel@tonic-gate int i;
43377c478bd9Sstevel@tonic-gate int ne = sblock.fs_bsize / sizeof (daddr32_t);
43387c478bd9Sstevel@tonic-gate daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)];
43397c478bd9Sstevel@tonic-gate
43407c478bd9Sstevel@tonic-gate if (frag == 0)
43417c478bd9Sstevel@tonic-gate return;
43427c478bd9Sstevel@tonic-gate
43437c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, frag), (int)sblock.fs_bsize,
43447c478bd9Sstevel@tonic-gate (char *)fsb);
43457c478bd9Sstevel@tonic-gate
43467c478bd9Sstevel@tonic-gate checkdirect(ino, fragsp, fsb, sblock.fs_bsize / sizeof (daddr32_t));
43477c478bd9Sstevel@tonic-gate
43487c478bd9Sstevel@tonic-gate if (level)
43497c478bd9Sstevel@tonic-gate for (i = 0; i < ne && *fragsp; ++i)
43507c478bd9Sstevel@tonic-gate checkindirect(ino, fragsp, fsb[i], level-1);
43517c478bd9Sstevel@tonic-gate }
43527c478bd9Sstevel@tonic-gate
43537c478bd9Sstevel@tonic-gate void
addcsfrag(ino_t ino,daddr32_t frag,struct csfrag ** cfap)43547c478bd9Sstevel@tonic-gate addcsfrag(ino_t ino, daddr32_t frag, struct csfrag **cfap)
43557c478bd9Sstevel@tonic-gate {
43567c478bd9Sstevel@tonic-gate struct csfrag *cfp, *curr, *prev;
43577c478bd9Sstevel@tonic-gate
43587c478bd9Sstevel@tonic-gate /*
43597c478bd9Sstevel@tonic-gate * establish a range for faster checking in csfraginrange()
43607c478bd9Sstevel@tonic-gate */
43617c478bd9Sstevel@tonic-gate if (frag > maxcsfrag)
43627c478bd9Sstevel@tonic-gate maxcsfrag = frag;
43637c478bd9Sstevel@tonic-gate if (frag < mincsfrag)
43647c478bd9Sstevel@tonic-gate mincsfrag = frag;
43657c478bd9Sstevel@tonic-gate
43667c478bd9Sstevel@tonic-gate /*
43677c478bd9Sstevel@tonic-gate * if this frag belongs to an inode and is not the start of a block
43687c478bd9Sstevel@tonic-gate * then see if it is part of a frag range for this inode
43697c478bd9Sstevel@tonic-gate */
43707c478bd9Sstevel@tonic-gate if (ino && (frag % sblock.fs_frag))
43717c478bd9Sstevel@tonic-gate for (cfp = *cfap; cfp; cfp = cfp->next) {
43727c478bd9Sstevel@tonic-gate if (ino != cfp->ino)
43737c478bd9Sstevel@tonic-gate continue;
43747c478bd9Sstevel@tonic-gate if (frag != cfp->ofrag + cfp->frags)
43757c478bd9Sstevel@tonic-gate continue;
43767c478bd9Sstevel@tonic-gate cfp->frags++;
43777c478bd9Sstevel@tonic-gate cfp->size += sblock.fs_fsize;
43787c478bd9Sstevel@tonic-gate return;
43797c478bd9Sstevel@tonic-gate }
43807c478bd9Sstevel@tonic-gate /*
43817c478bd9Sstevel@tonic-gate * allocate a csfrag entry and insert it in an increasing order into the
43827c478bd9Sstevel@tonic-gate * specified list
43837c478bd9Sstevel@tonic-gate */
43847c478bd9Sstevel@tonic-gate cfp = (struct csfrag *)calloc(1, sizeof (struct csfrag));
43857c478bd9Sstevel@tonic-gate cfp->ino = ino;
43867c478bd9Sstevel@tonic-gate cfp->ofrag = frag;
43877c478bd9Sstevel@tonic-gate cfp->frags = 1;
43887c478bd9Sstevel@tonic-gate cfp->size = sblock.fs_fsize;
43897c478bd9Sstevel@tonic-gate for (prev = NULL, curr = *cfap; curr != NULL;
43907c478bd9Sstevel@tonic-gate prev = curr, curr = curr->next) {
43917c478bd9Sstevel@tonic-gate if (frag < curr->ofrag) {
43927c478bd9Sstevel@tonic-gate cfp->next = curr;
43937c478bd9Sstevel@tonic-gate if (prev)
43947c478bd9Sstevel@tonic-gate prev->next = cfp; /* middle element */
43957c478bd9Sstevel@tonic-gate else
43967c478bd9Sstevel@tonic-gate *cfap = cfp; /* first element */
43977c478bd9Sstevel@tonic-gate break;
43987c478bd9Sstevel@tonic-gate }
43997c478bd9Sstevel@tonic-gate if (curr->next == NULL) {
44007c478bd9Sstevel@tonic-gate curr->next = cfp; /* last element */
44017c478bd9Sstevel@tonic-gate break;
44027c478bd9Sstevel@tonic-gate }
44037c478bd9Sstevel@tonic-gate }
44047c478bd9Sstevel@tonic-gate if (*cfap == NULL) /* will happen only once */
44057c478bd9Sstevel@tonic-gate *cfap = cfp;
44067c478bd9Sstevel@tonic-gate }
44077c478bd9Sstevel@tonic-gate
44087c478bd9Sstevel@tonic-gate void
delcsfrag(daddr32_t frag,struct csfrag ** cfap)44097c478bd9Sstevel@tonic-gate delcsfrag(daddr32_t frag, struct csfrag **cfap)
44107c478bd9Sstevel@tonic-gate {
44117c478bd9Sstevel@tonic-gate struct csfrag *cfp;
44127c478bd9Sstevel@tonic-gate struct csfrag **cfpp;
44137c478bd9Sstevel@tonic-gate
44147c478bd9Sstevel@tonic-gate /*
44157c478bd9Sstevel@tonic-gate * free up entry whose beginning frag matches
44167c478bd9Sstevel@tonic-gate */
44177c478bd9Sstevel@tonic-gate for (cfpp = cfap; *cfpp; cfpp = &(*cfpp)->next) {
44187c478bd9Sstevel@tonic-gate if (frag == (*cfpp)->ofrag) {
44197c478bd9Sstevel@tonic-gate cfp = *cfpp;
44207c478bd9Sstevel@tonic-gate *cfpp = (*cfpp)->next;
44217c478bd9Sstevel@tonic-gate free((char *)cfp);
44227c478bd9Sstevel@tonic-gate return;
44237c478bd9Sstevel@tonic-gate }
44247c478bd9Sstevel@tonic-gate }
44257c478bd9Sstevel@tonic-gate }
44267c478bd9Sstevel@tonic-gate
44277c478bd9Sstevel@tonic-gate /*
44287c478bd9Sstevel@tonic-gate * See whether any of the direct blocks in the array pointed by "db" and of
44297c478bd9Sstevel@tonic-gate * length "ne" are within the range of frags needed to extend the cylinder
44307c478bd9Sstevel@tonic-gate * summary. If so, remove those frags from the "as-yet-unclassified" list
44317c478bd9Sstevel@tonic-gate * (csfrag) and add them to the "owned-by-inode" list (csfragino).
44327c478bd9Sstevel@tonic-gate * For each such frag found, decrement the frag count pointed to by fragsp.
44337c478bd9Sstevel@tonic-gate * "ino" is the inode that contains (either directly or indirectly) the frags
44347c478bd9Sstevel@tonic-gate * being checked.
44357c478bd9Sstevel@tonic-gate */
44367c478bd9Sstevel@tonic-gate void
checkdirect(ino_t ino,daddr32_t * fragsp,daddr32_t * db,int ne)44377c478bd9Sstevel@tonic-gate checkdirect(ino_t ino, daddr32_t *fragsp, daddr32_t *db, int ne)
44387c478bd9Sstevel@tonic-gate {
44397c478bd9Sstevel@tonic-gate int i;
44407c478bd9Sstevel@tonic-gate int j;
44417c478bd9Sstevel@tonic-gate int found;
44427c478bd9Sstevel@tonic-gate diskaddr_t frag;
44437c478bd9Sstevel@tonic-gate
44447c478bd9Sstevel@tonic-gate /*
44457c478bd9Sstevel@tonic-gate * scan for allocation within the new summary info range
44467c478bd9Sstevel@tonic-gate */
44477c478bd9Sstevel@tonic-gate for (i = 0; i < ne && *fragsp; ++i) {
44487c478bd9Sstevel@tonic-gate if ((frag = *db++) != 0) {
44497c478bd9Sstevel@tonic-gate found = 0;
44507c478bd9Sstevel@tonic-gate for (j = 0; j < sblock.fs_frag && *fragsp; ++j) {
44517c478bd9Sstevel@tonic-gate if (found || (found = csfraginrange(frag))) {
44527c478bd9Sstevel@tonic-gate addcsfrag(ino, frag, &csfragino);
44537c478bd9Sstevel@tonic-gate delcsfrag(frag, &csfrag);
44547c478bd9Sstevel@tonic-gate }
44557c478bd9Sstevel@tonic-gate ++frag;
44567c478bd9Sstevel@tonic-gate --(*fragsp);
44577c478bd9Sstevel@tonic-gate }
44587c478bd9Sstevel@tonic-gate }
44597c478bd9Sstevel@tonic-gate }
44607c478bd9Sstevel@tonic-gate }
44617c478bd9Sstevel@tonic-gate
44627c478bd9Sstevel@tonic-gate void
findcsfragino()44637c478bd9Sstevel@tonic-gate findcsfragino()
44647c478bd9Sstevel@tonic-gate {
44657c478bd9Sstevel@tonic-gate int i;
44667c478bd9Sstevel@tonic-gate int j;
44677c478bd9Sstevel@tonic-gate daddr32_t frags;
44687c478bd9Sstevel@tonic-gate struct dinode *dp;
44697c478bd9Sstevel@tonic-gate
44707c478bd9Sstevel@tonic-gate /*
44717c478bd9Sstevel@tonic-gate * scan all old inodes looking for allocations in the new
44727c478bd9Sstevel@tonic-gate * summary info range. Move the affected frag from the
44737c478bd9Sstevel@tonic-gate * generic csfrag list onto the `owned-by-inode' list csfragino.
44747c478bd9Sstevel@tonic-gate */
44757c478bd9Sstevel@tonic-gate for (i = UFSROOTINO; i < grow_fs_ncg*sblock.fs_ipg && csfrag; ++i) {
44767c478bd9Sstevel@tonic-gate dp = gdinode((ino_t)i);
44777c478bd9Sstevel@tonic-gate switch (dp->di_mode & IFMT) {
44787c478bd9Sstevel@tonic-gate case IFSHAD :
44797c478bd9Sstevel@tonic-gate case IFLNK :
44807c478bd9Sstevel@tonic-gate case IFDIR :
44817c478bd9Sstevel@tonic-gate case IFREG : break;
44827c478bd9Sstevel@tonic-gate default : continue;
44837c478bd9Sstevel@tonic-gate }
44847c478bd9Sstevel@tonic-gate
44857c478bd9Sstevel@tonic-gate frags = dbtofsb(&sblock, dp->di_blocks);
44867c478bd9Sstevel@tonic-gate
44877c478bd9Sstevel@tonic-gate checkdirect((ino_t)i, &frags, &dp->di_db[0], NDADDR+NIADDR);
4488303bf60bSsdebnath for (j = 0; j < NIADDR && frags; ++j) {
4489303bf60bSsdebnath /* Negate the block if its an fallocate'd block */
4490303bf60bSsdebnath if (dp->di_ib[j] < 0 && dp->di_ib[j] != UFS_HOLE)
4491303bf60bSsdebnath checkindirect((ino_t)i, &frags,
4492303bf60bSsdebnath -(dp->di_ib[j]), j);
4493303bf60bSsdebnath else
4494303bf60bSsdebnath checkindirect((ino_t)i, &frags,
4495303bf60bSsdebnath dp->di_ib[j], j);
4496303bf60bSsdebnath }
44977c478bd9Sstevel@tonic-gate }
44987c478bd9Sstevel@tonic-gate }
44997c478bd9Sstevel@tonic-gate
45007c478bd9Sstevel@tonic-gate void
fixindirect(daddr32_t frag,int level)45017c478bd9Sstevel@tonic-gate fixindirect(daddr32_t frag, int level)
45027c478bd9Sstevel@tonic-gate {
45037c478bd9Sstevel@tonic-gate int i;
45047c478bd9Sstevel@tonic-gate int ne = sblock.fs_bsize / sizeof (daddr32_t);
45057c478bd9Sstevel@tonic-gate daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)];
45067c478bd9Sstevel@tonic-gate
45077c478bd9Sstevel@tonic-gate if (frag == 0)
45087c478bd9Sstevel@tonic-gate return;
45097c478bd9Sstevel@tonic-gate
45107c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
45117c478bd9Sstevel@tonic-gate (char *)fsb);
45127c478bd9Sstevel@tonic-gate
45137c478bd9Sstevel@tonic-gate fixdirect((caddr_t)fsb, frag, fsb, ne);
45147c478bd9Sstevel@tonic-gate
45157c478bd9Sstevel@tonic-gate if (level)
45167c478bd9Sstevel@tonic-gate for (i = 0; i < ne; ++i)
45177c478bd9Sstevel@tonic-gate fixindirect(fsb[i], level-1);
45187c478bd9Sstevel@tonic-gate }
45197c478bd9Sstevel@tonic-gate
45207c478bd9Sstevel@tonic-gate void
fixdirect(caddr_t bp,daddr32_t frag,daddr32_t * db,int ne)45217c478bd9Sstevel@tonic-gate fixdirect(caddr_t bp, daddr32_t frag, daddr32_t *db, int ne)
45227c478bd9Sstevel@tonic-gate {
45237c478bd9Sstevel@tonic-gate int i;
45247c478bd9Sstevel@tonic-gate struct csfrag *cfp;
45257c478bd9Sstevel@tonic-gate
45267c478bd9Sstevel@tonic-gate for (i = 0; i < ne; ++i, ++db) {
45277c478bd9Sstevel@tonic-gate if (*db == 0)
45287c478bd9Sstevel@tonic-gate continue;
45297c478bd9Sstevel@tonic-gate if ((cfp = findcsfrag(*db, &csfragino)) == NULL)
45307c478bd9Sstevel@tonic-gate continue;
45317c478bd9Sstevel@tonic-gate *db = cfp->nfrag;
45327c478bd9Sstevel@tonic-gate cfp->fixed = 1;
45337c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
45347c478bd9Sstevel@tonic-gate bp);
45357c478bd9Sstevel@tonic-gate }
45367c478bd9Sstevel@tonic-gate }
45377c478bd9Sstevel@tonic-gate
45387c478bd9Sstevel@tonic-gate void
fixcsfragino()45397c478bd9Sstevel@tonic-gate fixcsfragino()
45407c478bd9Sstevel@tonic-gate {
45417c478bd9Sstevel@tonic-gate int i;
45427c478bd9Sstevel@tonic-gate struct dinode *dp;
45437c478bd9Sstevel@tonic-gate struct csfrag *cfp;
45447c478bd9Sstevel@tonic-gate
45457c478bd9Sstevel@tonic-gate for (cfp = csfragino; cfp; cfp = cfp->next) {
45467c478bd9Sstevel@tonic-gate if (cfp->fixed)
45477c478bd9Sstevel@tonic-gate continue;
45487c478bd9Sstevel@tonic-gate dp = gdinode((ino_t)cfp->ino);
45497c478bd9Sstevel@tonic-gate fixdirect((caddr_t)dibuf, difrag, dp->di_db, NDADDR+NIADDR);
45507c478bd9Sstevel@tonic-gate for (i = 0; i < NIADDR; ++i)
45517c478bd9Sstevel@tonic-gate fixindirect(dp->di_ib[i], i);
45527c478bd9Sstevel@tonic-gate }
45537c478bd9Sstevel@tonic-gate }
45547c478bd9Sstevel@tonic-gate
45557c478bd9Sstevel@tonic-gate /*
45567c478bd9Sstevel@tonic-gate * Read the cylinders summary information specified by settings in the
45577c478bd9Sstevel@tonic-gate * passed 'fs' structure into a new allocated array of csum structures.
45587c478bd9Sstevel@tonic-gate * The caller is responsible for freeing the returned array.
45597c478bd9Sstevel@tonic-gate * Return a pointer to an array of csum structures.
45607c478bd9Sstevel@tonic-gate */
45617c478bd9Sstevel@tonic-gate static struct csum *
read_summaryinfo(struct fs * fsp)45627c478bd9Sstevel@tonic-gate read_summaryinfo(struct fs *fsp)
45637c478bd9Sstevel@tonic-gate {
45647c478bd9Sstevel@tonic-gate struct csum *csp;
45657c478bd9Sstevel@tonic-gate int i;
45667c478bd9Sstevel@tonic-gate
45677c478bd9Sstevel@tonic-gate if ((csp = malloc((size_t)fsp->fs_cssize)) == NULL) {
45687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cannot create csum list,"
45697c478bd9Sstevel@tonic-gate " not enough memory\n"));
45707c478bd9Sstevel@tonic-gate exit(32);
45717c478bd9Sstevel@tonic-gate }
45727c478bd9Sstevel@tonic-gate
45737c478bd9Sstevel@tonic-gate for (i = 0; i < fsp->fs_cssize; i += fsp->fs_bsize) {
45747c478bd9Sstevel@tonic-gate rdfs(fsbtodb(fsp,
45757c478bd9Sstevel@tonic-gate (uint64_t)(fsp->fs_csaddr + numfrags(fsp, i))),
45767c478bd9Sstevel@tonic-gate (int)(fsp->fs_cssize - i < fsp->fs_bsize ?
4577d50c8f90Svsakar fsp->fs_cssize - i : fsp->fs_bsize), ((caddr_t)csp) + i);
45787c478bd9Sstevel@tonic-gate }
45797c478bd9Sstevel@tonic-gate
45807c478bd9Sstevel@tonic-gate return (csp);
45817c478bd9Sstevel@tonic-gate }
45827c478bd9Sstevel@tonic-gate
45837c478bd9Sstevel@tonic-gate /*
45847c478bd9Sstevel@tonic-gate * Check the allocation of fragments that are to be made part of a csum block.
45857c478bd9Sstevel@tonic-gate * A fragment is allocated if it is either in the csfragfree list or, it is
45867c478bd9Sstevel@tonic-gate * in the csfragino list and has new frags associated with it.
45877c478bd9Sstevel@tonic-gate * Return the number of allocated fragments.
45887c478bd9Sstevel@tonic-gate */
45897c478bd9Sstevel@tonic-gate int64_t
checkfragallocated(daddr32_t frag)45907c478bd9Sstevel@tonic-gate checkfragallocated(daddr32_t frag)
45917c478bd9Sstevel@tonic-gate {
45927c478bd9Sstevel@tonic-gate struct csfrag *cfp;
45937c478bd9Sstevel@tonic-gate /*
45947c478bd9Sstevel@tonic-gate * Since the lists are sorted we can break the search if the asked
45957c478bd9Sstevel@tonic-gate * frag is smaller then the one in the list.
45967c478bd9Sstevel@tonic-gate */
45977c478bd9Sstevel@tonic-gate for (cfp = csfragfree; cfp != NULL && frag >= cfp->ofrag;
45987c478bd9Sstevel@tonic-gate cfp = cfp->next) {
45997c478bd9Sstevel@tonic-gate if (frag == cfp->ofrag)
46007c478bd9Sstevel@tonic-gate return (1);
46017c478bd9Sstevel@tonic-gate }
46027c478bd9Sstevel@tonic-gate for (cfp = csfragino; cfp != NULL && frag >= cfp->ofrag;
46037c478bd9Sstevel@tonic-gate cfp = cfp->next) {
46047c478bd9Sstevel@tonic-gate if (frag == cfp->ofrag && cfp->nfrag != 0)
46057c478bd9Sstevel@tonic-gate return (cfp->frags);
46067c478bd9Sstevel@tonic-gate }
46077c478bd9Sstevel@tonic-gate
46087c478bd9Sstevel@tonic-gate return (0);
46097c478bd9Sstevel@tonic-gate }
46107c478bd9Sstevel@tonic-gate
46117c478bd9Sstevel@tonic-gate /*
46127c478bd9Sstevel@tonic-gate * Figure out how much the filesystem can be grown. The limiting factor is
46137c478bd9Sstevel@tonic-gate * the available free space needed to extend the cg summary info block.
46147c478bd9Sstevel@tonic-gate * The free space is determined in three steps:
46157c478bd9Sstevel@tonic-gate * - Try to extend the cg summary block to the required size.
46167c478bd9Sstevel@tonic-gate * - Find free blocks in last cg.
46177c478bd9Sstevel@tonic-gate * - Find free space in the last already allocated fragment of the summary info
46187c478bd9Sstevel@tonic-gate * block, and use it for additional csum structures.
46197c478bd9Sstevel@tonic-gate * Return the maximum size of the new filesystem or 0 if it can't be grown.
46207c478bd9Sstevel@tonic-gate * Please note that this function leaves the global list pointers csfrag,
46217c478bd9Sstevel@tonic-gate * csfragfree, and csfragino initialized, and the caller is responsible for
46227c478bd9Sstevel@tonic-gate * freeing the lists.
46237c478bd9Sstevel@tonic-gate */
46247c478bd9Sstevel@tonic-gate diskaddr_t
probe_summaryinfo()46257c478bd9Sstevel@tonic-gate probe_summaryinfo()
46267c478bd9Sstevel@tonic-gate {
46277c478bd9Sstevel@tonic-gate /* fragments by which the csum block can be extended. */
46287c478bd9Sstevel@tonic-gate int64_t growth_csum_frags = 0;
46297c478bd9Sstevel@tonic-gate /* fragments by which the filesystem can be extended. */
46307c478bd9Sstevel@tonic-gate int64_t growth_fs_frags = 0;
46317c478bd9Sstevel@tonic-gate int64_t new_fs_cssize; /* size of csum blk in the new FS */
46327c478bd9Sstevel@tonic-gate int64_t new_fs_ncg; /* number of cg in the new FS */
46337c478bd9Sstevel@tonic-gate int64_t spare_csum;
46347c478bd9Sstevel@tonic-gate daddr32_t oldfrag_daddr;
46357c478bd9Sstevel@tonic-gate daddr32_t newfrag_daddr;
46367c478bd9Sstevel@tonic-gate daddr32_t daddr;
46377c478bd9Sstevel@tonic-gate int i;
46387c478bd9Sstevel@tonic-gate
46397c478bd9Sstevel@tonic-gate /*
46407c478bd9Sstevel@tonic-gate * read and verify the superblock
46417c478bd9Sstevel@tonic-gate */
46427c478bd9Sstevel@tonic-gate rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
46436451fdbcSvsakar (void) checksblock(sblock, 0);
46447c478bd9Sstevel@tonic-gate
46457c478bd9Sstevel@tonic-gate /*
46467c478bd9Sstevel@tonic-gate * check how much we can extend the cg summary info block
46477c478bd9Sstevel@tonic-gate */
46487c478bd9Sstevel@tonic-gate
46497c478bd9Sstevel@tonic-gate /*
46507c478bd9Sstevel@tonic-gate * read current summary information
46517c478bd9Sstevel@tonic-gate */
46527c478bd9Sstevel@tonic-gate fscs = read_summaryinfo(&sblock);
46537c478bd9Sstevel@tonic-gate
46547c478bd9Sstevel@tonic-gate /*
46557c478bd9Sstevel@tonic-gate * build list of frags needed for cg summary info block extension
46567c478bd9Sstevel@tonic-gate */
46577c478bd9Sstevel@tonic-gate oldfrag_daddr = howmany(sblock.fs_cssize, sblock.fs_fsize) +
46587c478bd9Sstevel@tonic-gate sblock.fs_csaddr;
46597c478bd9Sstevel@tonic-gate new_fs_ncg = howmany(dbtofsb(&sblock, fssize_db), sblock.fs_fpg);
46607c478bd9Sstevel@tonic-gate new_fs_cssize = fragroundup(&sblock, new_fs_ncg * sizeof (struct csum));
46617c478bd9Sstevel@tonic-gate newfrag_daddr = howmany(new_fs_cssize, sblock.fs_fsize) +
46627c478bd9Sstevel@tonic-gate sblock.fs_csaddr;
46637c478bd9Sstevel@tonic-gate /*
46647c478bd9Sstevel@tonic-gate * add all of the frags that are required to grow the cyl summary to the
46657c478bd9Sstevel@tonic-gate * csfrag list, which is the generic/unknown list, since at this point
46667c478bd9Sstevel@tonic-gate * we don't yet know the state of those frags.
46677c478bd9Sstevel@tonic-gate */
46687c478bd9Sstevel@tonic-gate for (daddr = oldfrag_daddr; daddr < newfrag_daddr; daddr++)
46697c478bd9Sstevel@tonic-gate addcsfrag((ino_t)0, daddr, &csfrag);
46707c478bd9Sstevel@tonic-gate
46717c478bd9Sstevel@tonic-gate /*
46727c478bd9Sstevel@tonic-gate * filter free fragments and allocate them. Note that the free frags
46737c478bd9Sstevel@tonic-gate * must be allocated first otherwise they could be grabbed by
46747c478bd9Sstevel@tonic-gate * alloccsfragino() for data frags.
46757c478bd9Sstevel@tonic-gate */
46767c478bd9Sstevel@tonic-gate findcsfragfree();
46777c478bd9Sstevel@tonic-gate alloccsfragfree();
46787c478bd9Sstevel@tonic-gate
46797c478bd9Sstevel@tonic-gate /*
46807c478bd9Sstevel@tonic-gate * filter fragments owned by inodes and allocate them
46817c478bd9Sstevel@tonic-gate */
46827c478bd9Sstevel@tonic-gate grow_fs_ncg = sblock.fs_ncg; /* findcsfragino() needs this glob. var. */
46837c478bd9Sstevel@tonic-gate findcsfragino();
46847c478bd9Sstevel@tonic-gate alloccsfragino();
46857c478bd9Sstevel@tonic-gate
46867c478bd9Sstevel@tonic-gate if (notenoughspace()) {
46877c478bd9Sstevel@tonic-gate /*
46887c478bd9Sstevel@tonic-gate * check how many consecutive fragments could be allocated
46897c478bd9Sstevel@tonic-gate * in both lists.
46907c478bd9Sstevel@tonic-gate */
46917c478bd9Sstevel@tonic-gate int64_t tmp_frags;
46927c478bd9Sstevel@tonic-gate for (daddr = oldfrag_daddr; daddr < newfrag_daddr;
46937c478bd9Sstevel@tonic-gate daddr += tmp_frags) {
46947c478bd9Sstevel@tonic-gate if ((tmp_frags = checkfragallocated(daddr)) > 0)
46957c478bd9Sstevel@tonic-gate growth_csum_frags += tmp_frags;
46967c478bd9Sstevel@tonic-gate else
46977c478bd9Sstevel@tonic-gate break;
46987c478bd9Sstevel@tonic-gate }
46997c478bd9Sstevel@tonic-gate } else {
47007c478bd9Sstevel@tonic-gate /*
47017c478bd9Sstevel@tonic-gate * We have all we need for the new desired size,
47027c478bd9Sstevel@tonic-gate * so clean up and report back.
47037c478bd9Sstevel@tonic-gate */
47047c478bd9Sstevel@tonic-gate return (fssize_db);
47057c478bd9Sstevel@tonic-gate }
47067c478bd9Sstevel@tonic-gate
47077c478bd9Sstevel@tonic-gate /*
47087c478bd9Sstevel@tonic-gate * given the number of fragments by which the csum block can be grown
47097c478bd9Sstevel@tonic-gate * compute by how many new fragments the FS can be increased.
47107c478bd9Sstevel@tonic-gate * It is the number of csum instances per fragment multiplied by
47117c478bd9Sstevel@tonic-gate * `growth_csum_frags' and the number of fragments per cylinder group.
47127c478bd9Sstevel@tonic-gate */
47137c478bd9Sstevel@tonic-gate growth_fs_frags = howmany(sblock.fs_fsize, sizeof (struct csum)) *
47147c478bd9Sstevel@tonic-gate growth_csum_frags * sblock.fs_fpg;
47157c478bd9Sstevel@tonic-gate
47167c478bd9Sstevel@tonic-gate /*
47177c478bd9Sstevel@tonic-gate * compute free fragments in the last cylinder group
47187c478bd9Sstevel@tonic-gate */
47197c478bd9Sstevel@tonic-gate rdcg(sblock.fs_ncg - 1);
47207c478bd9Sstevel@tonic-gate growth_fs_frags += sblock.fs_fpg - acg.cg_ndblk;
47217c478bd9Sstevel@tonic-gate
47227c478bd9Sstevel@tonic-gate /*
47237c478bd9Sstevel@tonic-gate * compute how many csum instances are unused in the old csum block.
47247c478bd9Sstevel@tonic-gate * For each unused csum instance the FS can be grown by one cylinder
47257c478bd9Sstevel@tonic-gate * group without extending the csum block.
47267c478bd9Sstevel@tonic-gate */
47277c478bd9Sstevel@tonic-gate spare_csum = howmany(sblock.fs_cssize, sizeof (struct csum)) -
47287c478bd9Sstevel@tonic-gate sblock.fs_ncg;
47297c478bd9Sstevel@tonic-gate if (spare_csum > 0)
47307c478bd9Sstevel@tonic-gate growth_fs_frags += spare_csum * sblock.fs_fpg;
47317c478bd9Sstevel@tonic-gate
47327c478bd9Sstevel@tonic-gate /*
47337c478bd9Sstevel@tonic-gate * recalculate the new filesystem size in sectors, shorten it by
47347c478bd9Sstevel@tonic-gate * the requested size `fssize_db' if necessary.
47357c478bd9Sstevel@tonic-gate */
47367c478bd9Sstevel@tonic-gate if (growth_fs_frags > 0) {
47377c478bd9Sstevel@tonic-gate diskaddr_t sect;
47387c478bd9Sstevel@tonic-gate sect = (sblock.fs_size + growth_fs_frags) * sblock.fs_nspf;
47397c478bd9Sstevel@tonic-gate return ((sect > fssize_db) ? fssize_db : sect);
47407c478bd9Sstevel@tonic-gate }
47417c478bd9Sstevel@tonic-gate
47427c478bd9Sstevel@tonic-gate return (0);
47437c478bd9Sstevel@tonic-gate }
47447c478bd9Sstevel@tonic-gate
47457c478bd9Sstevel@tonic-gate void
extendsummaryinfo()47467c478bd9Sstevel@tonic-gate extendsummaryinfo()
47477c478bd9Sstevel@tonic-gate {
47487c478bd9Sstevel@tonic-gate int64_t i;
47497c478bd9Sstevel@tonic-gate int localtest = test;
47507c478bd9Sstevel@tonic-gate int64_t frags;
47517c478bd9Sstevel@tonic-gate daddr32_t oldfrag;
47527c478bd9Sstevel@tonic-gate daddr32_t newfrag;
47537c478bd9Sstevel@tonic-gate
47547c478bd9Sstevel@tonic-gate /*
47557c478bd9Sstevel@tonic-gate * if no-write (-N), don't bother
47567c478bd9Sstevel@tonic-gate */
47577c478bd9Sstevel@tonic-gate if (Nflag)
47587c478bd9Sstevel@tonic-gate return;
47597c478bd9Sstevel@tonic-gate
47607c478bd9Sstevel@tonic-gate again:
47617c478bd9Sstevel@tonic-gate flcg();
47627c478bd9Sstevel@tonic-gate /*
47637c478bd9Sstevel@tonic-gate * summary info did not change size -- do nothing unless in test mode
47647c478bd9Sstevel@tonic-gate */
47657c478bd9Sstevel@tonic-gate if (grow_fs_cssize == sblock.fs_cssize)
47667c478bd9Sstevel@tonic-gate if (!localtest)
47677c478bd9Sstevel@tonic-gate return;
47687c478bd9Sstevel@tonic-gate
47697c478bd9Sstevel@tonic-gate /*
47707c478bd9Sstevel@tonic-gate * build list of frags needed for additional summary information
47717c478bd9Sstevel@tonic-gate */
47727c478bd9Sstevel@tonic-gate oldfrag = howmany(grow_fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
47737c478bd9Sstevel@tonic-gate newfrag = howmany(sblock.fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
47747c478bd9Sstevel@tonic-gate /*
47757c478bd9Sstevel@tonic-gate * add all of the frags that are required to grow the cyl summary to the
47767c478bd9Sstevel@tonic-gate * csfrag list, which is the generic/unknown list, since at this point
47777c478bd9Sstevel@tonic-gate * we don't yet know the state of those frags.
47787c478bd9Sstevel@tonic-gate */
47797c478bd9Sstevel@tonic-gate for (i = oldfrag, frags = 0; i < newfrag; ++i, ++frags)
47807c478bd9Sstevel@tonic-gate addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
47817c478bd9Sstevel@tonic-gate /*
47827c478bd9Sstevel@tonic-gate * reduce the number of data blocks in the file system (fs_dsize) by
47837c478bd9Sstevel@tonic-gate * the number of frags that need to be added to the cyl summary
47847c478bd9Sstevel@tonic-gate */
47857c478bd9Sstevel@tonic-gate sblock.fs_dsize -= (newfrag - oldfrag);
47867c478bd9Sstevel@tonic-gate
47877c478bd9Sstevel@tonic-gate /*
47887c478bd9Sstevel@tonic-gate * In test mode, we move more data than necessary from
47897c478bd9Sstevel@tonic-gate * cylinder group 0. The lookup/allocate/move code can be
47907c478bd9Sstevel@tonic-gate * better stressed without having to create HUGE file systems.
47917c478bd9Sstevel@tonic-gate */
47927c478bd9Sstevel@tonic-gate if (localtest)
47937c478bd9Sstevel@tonic-gate for (i = newfrag; i < grow_sifrag; ++i) {
47947c478bd9Sstevel@tonic-gate if (frags >= testfrags)
47957c478bd9Sstevel@tonic-gate break;
47967c478bd9Sstevel@tonic-gate frags++;
47977c478bd9Sstevel@tonic-gate addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
47987c478bd9Sstevel@tonic-gate }
47997c478bd9Sstevel@tonic-gate
48007c478bd9Sstevel@tonic-gate /*
48017c478bd9Sstevel@tonic-gate * move frags to free or inode lists, depending on owner
48027c478bd9Sstevel@tonic-gate */
48037c478bd9Sstevel@tonic-gate findcsfragfree();
48047c478bd9Sstevel@tonic-gate findcsfragino();
48057c478bd9Sstevel@tonic-gate
48067c478bd9Sstevel@tonic-gate /*
48077c478bd9Sstevel@tonic-gate * if not all frags can be located, file system must be inconsistent
48087c478bd9Sstevel@tonic-gate */
48097c478bd9Sstevel@tonic-gate if (csfrag) {
48107c478bd9Sstevel@tonic-gate isbad = 1; /* should already be set, but make sure */
48117c478bd9Sstevel@tonic-gate lockexit(32);
48127c478bd9Sstevel@tonic-gate }
48137c478bd9Sstevel@tonic-gate
48147c478bd9Sstevel@tonic-gate /*
48157c478bd9Sstevel@tonic-gate * allocate the free frags. Note that the free frags must be allocated
48167c478bd9Sstevel@tonic-gate * first otherwise they could be grabbed by alloccsfragino() for data
48177c478bd9Sstevel@tonic-gate * frags.
48187c478bd9Sstevel@tonic-gate */
48197c478bd9Sstevel@tonic-gate alloccsfragfree();
48207c478bd9Sstevel@tonic-gate /*
48217c478bd9Sstevel@tonic-gate * allocate extra space for inode frags
48227c478bd9Sstevel@tonic-gate */
48237c478bd9Sstevel@tonic-gate alloccsfragino();
48247c478bd9Sstevel@tonic-gate
48257c478bd9Sstevel@tonic-gate /*
48267c478bd9Sstevel@tonic-gate * not enough space
48277c478bd9Sstevel@tonic-gate */
48287c478bd9Sstevel@tonic-gate if (notenoughspace()) {
48297c478bd9Sstevel@tonic-gate unalloccsfragfree();
48307c478bd9Sstevel@tonic-gate unalloccsfragino();
48317c478bd9Sstevel@tonic-gate if (localtest && !testforce) {
48327c478bd9Sstevel@tonic-gate localtest = 0;
48337c478bd9Sstevel@tonic-gate goto again;
48347c478bd9Sstevel@tonic-gate }
48357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Not enough free space\n"));
48367c478bd9Sstevel@tonic-gate lockexit(NOTENOUGHSPACE);
48377c478bd9Sstevel@tonic-gate }
48387c478bd9Sstevel@tonic-gate
48397c478bd9Sstevel@tonic-gate /*
48407c478bd9Sstevel@tonic-gate * copy the data from old frags to new frags
48417c478bd9Sstevel@tonic-gate */
48427c478bd9Sstevel@tonic-gate copycsfragino();
48437c478bd9Sstevel@tonic-gate
48447c478bd9Sstevel@tonic-gate /*
48457c478bd9Sstevel@tonic-gate * fix the inodes to point to the new frags
48467c478bd9Sstevel@tonic-gate */
48477c478bd9Sstevel@tonic-gate fixcsfragino();
48487c478bd9Sstevel@tonic-gate
48497c478bd9Sstevel@tonic-gate /*
48507c478bd9Sstevel@tonic-gate * We may have moved more frags than we needed. Free them.
48517c478bd9Sstevel@tonic-gate */
48527c478bd9Sstevel@tonic-gate rdcg((long)0);
48537c478bd9Sstevel@tonic-gate for (i = newfrag; i <= maxcsfrag; ++i)
48547c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&acg), i-cgbase(&sblock, 0));
48557c478bd9Sstevel@tonic-gate wtcg();
48567c478bd9Sstevel@tonic-gate
48577c478bd9Sstevel@tonic-gate flcg();
48587c478bd9Sstevel@tonic-gate }
48597c478bd9Sstevel@tonic-gate
48607c478bd9Sstevel@tonic-gate /*
48617c478bd9Sstevel@tonic-gate * Check if all fragments in the `csfragino' list were reallocated.
48627c478bd9Sstevel@tonic-gate */
48637c478bd9Sstevel@tonic-gate int
notenoughspace()48647c478bd9Sstevel@tonic-gate notenoughspace()
48657c478bd9Sstevel@tonic-gate {
48667c478bd9Sstevel@tonic-gate struct csfrag *cfp;
48677c478bd9Sstevel@tonic-gate
48687c478bd9Sstevel@tonic-gate /*
48697c478bd9Sstevel@tonic-gate * If any element in the csfragino array has a "new frag location"
48707c478bd9Sstevel@tonic-gate * of 0, the allocfrags() function was unsuccessful in allocating
48717c478bd9Sstevel@tonic-gate * space for moving the frag represented by this array element.
48727c478bd9Sstevel@tonic-gate */
48737c478bd9Sstevel@tonic-gate for (cfp = csfragino; cfp; cfp = cfp->next)
48747c478bd9Sstevel@tonic-gate if (cfp->nfrag == 0)
48757c478bd9Sstevel@tonic-gate return (1);
48767c478bd9Sstevel@tonic-gate return (0);
48777c478bd9Sstevel@tonic-gate }
48787c478bd9Sstevel@tonic-gate
48797c478bd9Sstevel@tonic-gate void
unalloccsfragino()48807c478bd9Sstevel@tonic-gate unalloccsfragino()
48817c478bd9Sstevel@tonic-gate {
48827c478bd9Sstevel@tonic-gate struct csfrag *cfp;
48837c478bd9Sstevel@tonic-gate
48847c478bd9Sstevel@tonic-gate while ((cfp = csfragino) != NULL) {
48857c478bd9Sstevel@tonic-gate if (cfp->nfrag)
48867c478bd9Sstevel@tonic-gate freefrags(cfp->nfrag, cfp->frags, cfp->cylno);
48877c478bd9Sstevel@tonic-gate delcsfrag(cfp->ofrag, &csfragino);
48887c478bd9Sstevel@tonic-gate }
48897c478bd9Sstevel@tonic-gate }
48907c478bd9Sstevel@tonic-gate
48917c478bd9Sstevel@tonic-gate void
unalloccsfragfree()48927c478bd9Sstevel@tonic-gate unalloccsfragfree()
48937c478bd9Sstevel@tonic-gate {
48947c478bd9Sstevel@tonic-gate struct csfrag *cfp;
48957c478bd9Sstevel@tonic-gate
48967c478bd9Sstevel@tonic-gate while ((cfp = csfragfree) != NULL) {
48977c478bd9Sstevel@tonic-gate freefrags(cfp->ofrag, cfp->frags, cfp->cylno);
48987c478bd9Sstevel@tonic-gate delcsfrag(cfp->ofrag, &csfragfree);
48997c478bd9Sstevel@tonic-gate }
49007c478bd9Sstevel@tonic-gate }
49017c478bd9Sstevel@tonic-gate
49027c478bd9Sstevel@tonic-gate /*
49037c478bd9Sstevel@tonic-gate * For each frag in the "as-yet-unclassified" list (csfrag), see if
49047c478bd9Sstevel@tonic-gate * it's free (i.e., its bit is set in the free frag bit map). If so,
49057c478bd9Sstevel@tonic-gate * move it from the "as-yet-unclassified" list to the csfragfree list.
49067c478bd9Sstevel@tonic-gate */
49077c478bd9Sstevel@tonic-gate void
findcsfragfree()49087c478bd9Sstevel@tonic-gate findcsfragfree()
49097c478bd9Sstevel@tonic-gate {
49107c478bd9Sstevel@tonic-gate struct csfrag *cfp;
49117c478bd9Sstevel@tonic-gate struct csfrag *cfpnext;
49127c478bd9Sstevel@tonic-gate
49137c478bd9Sstevel@tonic-gate /*
49147c478bd9Sstevel@tonic-gate * move free frags onto the free-frag list
49157c478bd9Sstevel@tonic-gate */
49167c478bd9Sstevel@tonic-gate rdcg((long)0);
49177c478bd9Sstevel@tonic-gate for (cfp = csfrag; cfp; cfp = cfpnext) {
49187c478bd9Sstevel@tonic-gate cfpnext = cfp->next;
49197c478bd9Sstevel@tonic-gate if (isset(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0))) {
49207c478bd9Sstevel@tonic-gate addcsfrag(cfp->ino, cfp->ofrag, &csfragfree);
49217c478bd9Sstevel@tonic-gate delcsfrag(cfp->ofrag, &csfrag);
49227c478bd9Sstevel@tonic-gate }
49237c478bd9Sstevel@tonic-gate }
49247c478bd9Sstevel@tonic-gate }
49257c478bd9Sstevel@tonic-gate
49267c478bd9Sstevel@tonic-gate void
copycsfragino()49277c478bd9Sstevel@tonic-gate copycsfragino()
49287c478bd9Sstevel@tonic-gate {
49297c478bd9Sstevel@tonic-gate struct csfrag *cfp;
49307c478bd9Sstevel@tonic-gate char buf[MAXBSIZE];
49317c478bd9Sstevel@tonic-gate
49327c478bd9Sstevel@tonic-gate /*
49337c478bd9Sstevel@tonic-gate * copy data from old frags to newly allocated frags
49347c478bd9Sstevel@tonic-gate */
49357c478bd9Sstevel@tonic-gate for (cfp = csfragino; cfp; cfp = cfp->next) {
49367c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)cfp->ofrag), (int)cfp->size,
49377c478bd9Sstevel@tonic-gate buf);
49387c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)cfp->nfrag), (int)cfp->size,
49397c478bd9Sstevel@tonic-gate buf);
49407c478bd9Sstevel@tonic-gate }
49417c478bd9Sstevel@tonic-gate }
49427c478bd9Sstevel@tonic-gate
49437c478bd9Sstevel@tonic-gate long curcylno = -1;
49447c478bd9Sstevel@tonic-gate int cylnodirty = 0;
49457c478bd9Sstevel@tonic-gate
49467c478bd9Sstevel@tonic-gate void
rdcg(long cylno)49477c478bd9Sstevel@tonic-gate rdcg(long cylno)
49487c478bd9Sstevel@tonic-gate {
49497c478bd9Sstevel@tonic-gate if (cylno != curcylno) {
49507c478bd9Sstevel@tonic-gate flcg();
49517c478bd9Sstevel@tonic-gate curcylno = cylno;
49527c478bd9Sstevel@tonic-gate rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
49537c478bd9Sstevel@tonic-gate (int)sblock.fs_cgsize, (char *)&acg);
49547c478bd9Sstevel@tonic-gate }
49557c478bd9Sstevel@tonic-gate }
49567c478bd9Sstevel@tonic-gate
49577c478bd9Sstevel@tonic-gate void
flcg()49587c478bd9Sstevel@tonic-gate flcg()
49597c478bd9Sstevel@tonic-gate {
49607c478bd9Sstevel@tonic-gate if (cylnodirty) {
49617c478bd9Sstevel@tonic-gate if (debug && Pflag) {
49627c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
49637c478bd9Sstevel@tonic-gate "Assert: cylnodirty set in probe mode\n");
49647c478bd9Sstevel@tonic-gate return;
49657c478bd9Sstevel@tonic-gate }
49667c478bd9Sstevel@tonic-gate resetallocinfo();
49677c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
49687c478bd9Sstevel@tonic-gate (int)sblock.fs_cgsize, (char *)&acg);
49697c478bd9Sstevel@tonic-gate cylnodirty = 0;
49707c478bd9Sstevel@tonic-gate }
49717c478bd9Sstevel@tonic-gate curcylno = -1;
49727c478bd9Sstevel@tonic-gate }
49737c478bd9Sstevel@tonic-gate
49747c478bd9Sstevel@tonic-gate void
wtcg()49757c478bd9Sstevel@tonic-gate wtcg()
49767c478bd9Sstevel@tonic-gate {
49777c478bd9Sstevel@tonic-gate if (!Pflag) {
49787c478bd9Sstevel@tonic-gate /* probe mode should never write to disk */
49797c478bd9Sstevel@tonic-gate cylnodirty = 1;
49807c478bd9Sstevel@tonic-gate }
49817c478bd9Sstevel@tonic-gate }
49827c478bd9Sstevel@tonic-gate
49837c478bd9Sstevel@tonic-gate void
allocfrags(long frags,daddr32_t * fragp,long * cylnop)49847c478bd9Sstevel@tonic-gate allocfrags(long frags, daddr32_t *fragp, long *cylnop)
49857c478bd9Sstevel@tonic-gate {
49867c478bd9Sstevel@tonic-gate int i;
49877c478bd9Sstevel@tonic-gate int j;
49887c478bd9Sstevel@tonic-gate long bits;
49897c478bd9Sstevel@tonic-gate long bit;
49907c478bd9Sstevel@tonic-gate
49917c478bd9Sstevel@tonic-gate /*
49927c478bd9Sstevel@tonic-gate * Allocate a free-frag range in an old cylinder group
49937c478bd9Sstevel@tonic-gate */
49947c478bd9Sstevel@tonic-gate for (i = 0, *fragp = 0; i < grow_fs_ncg; ++i) {
49957c478bd9Sstevel@tonic-gate if (((fscs+i)->cs_nffree < frags) && ((fscs+i)->cs_nbfree == 0))
49967c478bd9Sstevel@tonic-gate continue;
49977c478bd9Sstevel@tonic-gate rdcg((long)i);
49987c478bd9Sstevel@tonic-gate bit = bits = 0;
49997c478bd9Sstevel@tonic-gate while (findfreerange(&bit, &bits)) {
50007c478bd9Sstevel@tonic-gate if (frags <= bits) {
50017c478bd9Sstevel@tonic-gate for (j = 0; j < frags; ++j)
50027c478bd9Sstevel@tonic-gate clrbit(cg_blksfree(&acg), bit+j);
50037c478bd9Sstevel@tonic-gate wtcg();
50047c478bd9Sstevel@tonic-gate *cylnop = i;
50057c478bd9Sstevel@tonic-gate *fragp = bit + cgbase(&sblock, i);
50067c478bd9Sstevel@tonic-gate return;
50077c478bd9Sstevel@tonic-gate }
50087c478bd9Sstevel@tonic-gate bit += bits;
50097c478bd9Sstevel@tonic-gate }
50107c478bd9Sstevel@tonic-gate }
50117c478bd9Sstevel@tonic-gate }
50127c478bd9Sstevel@tonic-gate
50137c478bd9Sstevel@tonic-gate /*
50147c478bd9Sstevel@tonic-gate * Allocate space for frags that need to be moved in order to free up space for
50157c478bd9Sstevel@tonic-gate * expanding the cylinder summary info.
50167c478bd9Sstevel@tonic-gate * For each frag that needs to be moved (each frag or range of frags in
50177c478bd9Sstevel@tonic-gate * the csfragino list), allocate a new location and store the frag number
50187c478bd9Sstevel@tonic-gate * of that new location in the nfrag field of the csfrag struct.
50197c478bd9Sstevel@tonic-gate * If a new frag can't be allocated for any element in the csfragino list,
50207c478bd9Sstevel@tonic-gate * set the new frag number for that element to 0 and return immediately.
50217c478bd9Sstevel@tonic-gate * The notenoughspace() function will detect this condition.
50227c478bd9Sstevel@tonic-gate */
50237c478bd9Sstevel@tonic-gate void
alloccsfragino()50247c478bd9Sstevel@tonic-gate alloccsfragino()
50257c478bd9Sstevel@tonic-gate {
50267c478bd9Sstevel@tonic-gate struct csfrag *cfp;
50277c478bd9Sstevel@tonic-gate
50287c478bd9Sstevel@tonic-gate /*
50297c478bd9Sstevel@tonic-gate * allocate space for inode frag ranges
50307c478bd9Sstevel@tonic-gate */
50317c478bd9Sstevel@tonic-gate for (cfp = csfragino; cfp; cfp = cfp->next) {
50327c478bd9Sstevel@tonic-gate allocfrags(cfp->frags, &cfp->nfrag, &cfp->cylno);
50337c478bd9Sstevel@tonic-gate if (cfp->nfrag == 0)
50347c478bd9Sstevel@tonic-gate break;
50357c478bd9Sstevel@tonic-gate }
50367c478bd9Sstevel@tonic-gate }
50377c478bd9Sstevel@tonic-gate
50387c478bd9Sstevel@tonic-gate void
alloccsfragfree()50397c478bd9Sstevel@tonic-gate alloccsfragfree()
50407c478bd9Sstevel@tonic-gate {
50417c478bd9Sstevel@tonic-gate struct csfrag *cfp;
50427c478bd9Sstevel@tonic-gate
50437c478bd9Sstevel@tonic-gate /*
50447c478bd9Sstevel@tonic-gate * allocate the free frags needed for extended summary info
50457c478bd9Sstevel@tonic-gate */
50467c478bd9Sstevel@tonic-gate rdcg((long)0);
50477c478bd9Sstevel@tonic-gate
50487c478bd9Sstevel@tonic-gate for (cfp = csfragfree; cfp; cfp = cfp->next)
50497c478bd9Sstevel@tonic-gate clrbit(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0));
50507c478bd9Sstevel@tonic-gate
50517c478bd9Sstevel@tonic-gate wtcg();
50527c478bd9Sstevel@tonic-gate }
50537c478bd9Sstevel@tonic-gate
50547c478bd9Sstevel@tonic-gate void
freefrags(daddr32_t frag,long frags,long cylno)50557c478bd9Sstevel@tonic-gate freefrags(daddr32_t frag, long frags, long cylno)
50567c478bd9Sstevel@tonic-gate {
50577c478bd9Sstevel@tonic-gate int i;
50587c478bd9Sstevel@tonic-gate
50597c478bd9Sstevel@tonic-gate /*
50607c478bd9Sstevel@tonic-gate * free frags
50617c478bd9Sstevel@tonic-gate */
50627c478bd9Sstevel@tonic-gate rdcg(cylno);
50637c478bd9Sstevel@tonic-gate for (i = 0; i < frags; ++i) {
50647c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&acg), (frag+i) - cgbase(&sblock, cylno));
50657c478bd9Sstevel@tonic-gate }
50667c478bd9Sstevel@tonic-gate wtcg();
50677c478bd9Sstevel@tonic-gate }
50687c478bd9Sstevel@tonic-gate
50697c478bd9Sstevel@tonic-gate int
findfreerange(long * bitp,long * bitsp)50707c478bd9Sstevel@tonic-gate findfreerange(long *bitp, long *bitsp)
50717c478bd9Sstevel@tonic-gate {
50727c478bd9Sstevel@tonic-gate long bit;
50737c478bd9Sstevel@tonic-gate
50747c478bd9Sstevel@tonic-gate /*
50757c478bd9Sstevel@tonic-gate * find a range of free bits in a cylinder group bit map
50767c478bd9Sstevel@tonic-gate */
50777c478bd9Sstevel@tonic-gate for (bit = *bitp, *bitsp = 0; bit < acg.cg_ndblk; ++bit)
50787c478bd9Sstevel@tonic-gate if (isset(cg_blksfree(&acg), bit))
50797c478bd9Sstevel@tonic-gate break;
50807c478bd9Sstevel@tonic-gate
50817c478bd9Sstevel@tonic-gate if (bit >= acg.cg_ndblk)
50827c478bd9Sstevel@tonic-gate return (0);
50837c478bd9Sstevel@tonic-gate
50847c478bd9Sstevel@tonic-gate *bitp = bit;
50857c478bd9Sstevel@tonic-gate *bitsp = 1;
50867c478bd9Sstevel@tonic-gate for (++bit; bit < acg.cg_ndblk; ++bit, ++(*bitsp)) {
50877c478bd9Sstevel@tonic-gate if ((bit % sblock.fs_frag) == 0)
50887c478bd9Sstevel@tonic-gate break;
50897c478bd9Sstevel@tonic-gate if (isclr(cg_blksfree(&acg), bit))
50907c478bd9Sstevel@tonic-gate break;
50917c478bd9Sstevel@tonic-gate }
50927c478bd9Sstevel@tonic-gate return (1);
50937c478bd9Sstevel@tonic-gate }
50947c478bd9Sstevel@tonic-gate
50957c478bd9Sstevel@tonic-gate void
resetallocinfo()50967c478bd9Sstevel@tonic-gate resetallocinfo()
50977c478bd9Sstevel@tonic-gate {
50987c478bd9Sstevel@tonic-gate long cno;
50997c478bd9Sstevel@tonic-gate long bit;
51007c478bd9Sstevel@tonic-gate long bits;
51017c478bd9Sstevel@tonic-gate
51027c478bd9Sstevel@tonic-gate /*
51037c478bd9Sstevel@tonic-gate * Compute the free blocks/frags info and update the appropriate
51047c478bd9Sstevel@tonic-gate * inmemory superblock, summary info, and cylinder group fields
51057c478bd9Sstevel@tonic-gate */
51067c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nffree -= acg.cg_cs.cs_nffree;
51077c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nbfree -= acg.cg_cs.cs_nbfree;
51087c478bd9Sstevel@tonic-gate
51097c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nffree = 0;
51107c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nbfree = 0;
51117c478bd9Sstevel@tonic-gate
51127c478bd9Sstevel@tonic-gate bzero((caddr_t)acg.cg_frsum, sizeof (acg.cg_frsum));
51137c478bd9Sstevel@tonic-gate bzero((caddr_t)cg_blktot(&acg), (int)(acg.cg_iusedoff-acg.cg_btotoff));
51147c478bd9Sstevel@tonic-gate
51157c478bd9Sstevel@tonic-gate bit = bits = 0;
51167c478bd9Sstevel@tonic-gate while (findfreerange(&bit, &bits)) {
51177c478bd9Sstevel@tonic-gate if (bits == sblock.fs_frag) {
51187c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nbfree++;
51197c478bd9Sstevel@tonic-gate cno = cbtocylno(&sblock, bit);
51207c478bd9Sstevel@tonic-gate cg_blktot(&acg)[cno]++;
51217c478bd9Sstevel@tonic-gate cg_blks(&sblock, &acg, cno)[cbtorpos(&sblock, bit)]++;
51227c478bd9Sstevel@tonic-gate } else {
51237c478bd9Sstevel@tonic-gate acg.cg_cs.cs_nffree += bits;
51247c478bd9Sstevel@tonic-gate acg.cg_frsum[bits]++;
51257c478bd9Sstevel@tonic-gate }
51267c478bd9Sstevel@tonic-gate bit += bits;
51277c478bd9Sstevel@tonic-gate }
51287c478bd9Sstevel@tonic-gate
51297c478bd9Sstevel@tonic-gate *(fscs + acg.cg_cgx) = acg.cg_cs;
51307c478bd9Sstevel@tonic-gate
51317c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
51327c478bd9Sstevel@tonic-gate sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
51337c478bd9Sstevel@tonic-gate }
51347c478bd9Sstevel@tonic-gate
51357c478bd9Sstevel@tonic-gate void
extendcg(long cylno)51367c478bd9Sstevel@tonic-gate extendcg(long cylno)
51377c478bd9Sstevel@tonic-gate {
51387c478bd9Sstevel@tonic-gate int i;
51397c478bd9Sstevel@tonic-gate diskaddr_t dupper;
51407c478bd9Sstevel@tonic-gate diskaddr_t cbase;
51417c478bd9Sstevel@tonic-gate diskaddr_t dmax;
51427c478bd9Sstevel@tonic-gate
51437c478bd9Sstevel@tonic-gate /*
51447c478bd9Sstevel@tonic-gate * extend the cylinder group at the end of the old file system
51457c478bd9Sstevel@tonic-gate * if it was partially allocated becase of lack of space
51467c478bd9Sstevel@tonic-gate */
51477c478bd9Sstevel@tonic-gate flcg();
51487c478bd9Sstevel@tonic-gate rdcg(cylno);
51497c478bd9Sstevel@tonic-gate
51507c478bd9Sstevel@tonic-gate dupper = acg.cg_ndblk;
51517c478bd9Sstevel@tonic-gate if (cylno == sblock.fs_ncg - 1)
5152355d6bb5Sswilcox acg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
51537c478bd9Sstevel@tonic-gate else
51547c478bd9Sstevel@tonic-gate acg.cg_ncyl = sblock.fs_cpg;
51557c478bd9Sstevel@tonic-gate cbase = cgbase(&sblock, cylno);
51567c478bd9Sstevel@tonic-gate dmax = cbase + sblock.fs_fpg;
51577c478bd9Sstevel@tonic-gate if (dmax > sblock.fs_size)
51587c478bd9Sstevel@tonic-gate dmax = sblock.fs_size;
51597c478bd9Sstevel@tonic-gate acg.cg_ndblk = dmax - cbase;
51607c478bd9Sstevel@tonic-gate
51617c478bd9Sstevel@tonic-gate for (i = dupper; i < acg.cg_ndblk; ++i)
51627c478bd9Sstevel@tonic-gate setbit(cg_blksfree(&acg), i);
51637c478bd9Sstevel@tonic-gate
51647c478bd9Sstevel@tonic-gate sblock.fs_dsize += (acg.cg_ndblk - dupper);
51657c478bd9Sstevel@tonic-gate
51667c478bd9Sstevel@tonic-gate wtcg();
51677c478bd9Sstevel@tonic-gate flcg();
51687c478bd9Sstevel@tonic-gate }
51697c478bd9Sstevel@tonic-gate
51707c478bd9Sstevel@tonic-gate struct lockfs lockfs;
51717c478bd9Sstevel@tonic-gate int lockfd;
51727c478bd9Sstevel@tonic-gate int islocked;
51737c478bd9Sstevel@tonic-gate int lockfskey;
51747c478bd9Sstevel@tonic-gate char lockfscomment[128];
51757c478bd9Sstevel@tonic-gate
51767c478bd9Sstevel@tonic-gate void
ulockfs()51777c478bd9Sstevel@tonic-gate ulockfs()
51787c478bd9Sstevel@tonic-gate {
51797c478bd9Sstevel@tonic-gate /*
51807c478bd9Sstevel@tonic-gate * if the file system was locked, unlock it before exiting
51817c478bd9Sstevel@tonic-gate */
51827c478bd9Sstevel@tonic-gate if (islocked == 0)
51837c478bd9Sstevel@tonic-gate return;
51847c478bd9Sstevel@tonic-gate
51857c478bd9Sstevel@tonic-gate /*
51867c478bd9Sstevel@tonic-gate * first, check if the lock held
51877c478bd9Sstevel@tonic-gate */
51887c478bd9Sstevel@tonic-gate lockfs.lf_flags = LOCKFS_MOD;
51897c478bd9Sstevel@tonic-gate if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
51907c478bd9Sstevel@tonic-gate perror(directory);
51917c478bd9Sstevel@tonic-gate lockexit(32);
51927c478bd9Sstevel@tonic-gate }
51937c478bd9Sstevel@tonic-gate
51947c478bd9Sstevel@tonic-gate if (LOCKFS_IS_MOD(&lockfs)) {
51957c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
51967c478bd9Sstevel@tonic-gate gettext("FILE SYSTEM CHANGED DURING GROWFS!\n"));
51977c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
51987c478bd9Sstevel@tonic-gate gettext(" See lockfs(1), umount(1), and fsck(1)\n"));
51997c478bd9Sstevel@tonic-gate lockexit(32);
52007c478bd9Sstevel@tonic-gate }
52017c478bd9Sstevel@tonic-gate /*
52027c478bd9Sstevel@tonic-gate * unlock the file system
52037c478bd9Sstevel@tonic-gate */
52047c478bd9Sstevel@tonic-gate lockfs.lf_lock = LOCKFS_ULOCK;
52057c478bd9Sstevel@tonic-gate lockfs.lf_flags = 0;
52067c478bd9Sstevel@tonic-gate lockfs.lf_key = lockfskey;
52077c478bd9Sstevel@tonic-gate clockfs();
52087c478bd9Sstevel@tonic-gate if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
52097c478bd9Sstevel@tonic-gate perror(directory);
52107c478bd9Sstevel@tonic-gate lockexit(32);
52117c478bd9Sstevel@tonic-gate }
52127c478bd9Sstevel@tonic-gate }
52137c478bd9Sstevel@tonic-gate
52147c478bd9Sstevel@tonic-gate void
wlockfs()52157c478bd9Sstevel@tonic-gate wlockfs()
52167c478bd9Sstevel@tonic-gate {
52177c478bd9Sstevel@tonic-gate
52187c478bd9Sstevel@tonic-gate /*
52197c478bd9Sstevel@tonic-gate * if no-write (-N), don't bother
52207c478bd9Sstevel@tonic-gate */
52217c478bd9Sstevel@tonic-gate if (Nflag)
52227c478bd9Sstevel@tonic-gate return;
52237c478bd9Sstevel@tonic-gate /*
52247c478bd9Sstevel@tonic-gate * open the mountpoint, and write lock the file system
52257c478bd9Sstevel@tonic-gate */
52267c478bd9Sstevel@tonic-gate if ((lockfd = open64(directory, O_RDONLY)) == -1) {
52277c478bd9Sstevel@tonic-gate perror(directory);
52287c478bd9Sstevel@tonic-gate lockexit(32);
52297c478bd9Sstevel@tonic-gate }
52307c478bd9Sstevel@tonic-gate
52317c478bd9Sstevel@tonic-gate /*
52327c478bd9Sstevel@tonic-gate * check if it is already locked
52337c478bd9Sstevel@tonic-gate */
52347c478bd9Sstevel@tonic-gate if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
52357c478bd9Sstevel@tonic-gate perror(directory);
52367c478bd9Sstevel@tonic-gate lockexit(32);
52377c478bd9Sstevel@tonic-gate }
52387c478bd9Sstevel@tonic-gate
52397c478bd9Sstevel@tonic-gate if (lockfs.lf_lock != LOCKFS_WLOCK) {
52407c478bd9Sstevel@tonic-gate lockfs.lf_lock = LOCKFS_WLOCK;
52417c478bd9Sstevel@tonic-gate lockfs.lf_flags = 0;
52427c478bd9Sstevel@tonic-gate lockfs.lf_key = 0;
52437c478bd9Sstevel@tonic-gate clockfs();
52447c478bd9Sstevel@tonic-gate if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
52457c478bd9Sstevel@tonic-gate perror(directory);
52467c478bd9Sstevel@tonic-gate lockexit(32);
52477c478bd9Sstevel@tonic-gate }
52487c478bd9Sstevel@tonic-gate }
52497c478bd9Sstevel@tonic-gate islocked = 1;
52507c478bd9Sstevel@tonic-gate lockfskey = lockfs.lf_key;
52517c478bd9Sstevel@tonic-gate }
52527c478bd9Sstevel@tonic-gate
52537c478bd9Sstevel@tonic-gate void
clockfs()52547c478bd9Sstevel@tonic-gate clockfs()
52557c478bd9Sstevel@tonic-gate {
52567c478bd9Sstevel@tonic-gate time_t t;
52577c478bd9Sstevel@tonic-gate char *ct;
52587c478bd9Sstevel@tonic-gate
52597c478bd9Sstevel@tonic-gate (void) time(&t);
52607c478bd9Sstevel@tonic-gate ct = ctime(&t);
52617c478bd9Sstevel@tonic-gate ct[strlen(ct)-1] = '\0';
52627c478bd9Sstevel@tonic-gate
52637c478bd9Sstevel@tonic-gate (void) sprintf(lockfscomment, "%s -- mkfs pid %d", ct, getpid());
52647c478bd9Sstevel@tonic-gate lockfs.lf_comlen = strlen(lockfscomment)+1;
52657c478bd9Sstevel@tonic-gate lockfs.lf_comment = lockfscomment;
52667c478bd9Sstevel@tonic-gate }
52677c478bd9Sstevel@tonic-gate
52687c478bd9Sstevel@tonic-gate /*
52697c478bd9Sstevel@tonic-gate * Write the csum records and the superblock
52707c478bd9Sstevel@tonic-gate */
52717c478bd9Sstevel@tonic-gate void
wtsb()52727c478bd9Sstevel@tonic-gate wtsb()
52737c478bd9Sstevel@tonic-gate {
52747c478bd9Sstevel@tonic-gate long i;
52757c478bd9Sstevel@tonic-gate
52767c478bd9Sstevel@tonic-gate /*
52777c478bd9Sstevel@tonic-gate * write summary information
52787c478bd9Sstevel@tonic-gate */
52797c478bd9Sstevel@tonic-gate for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
52807c478bd9Sstevel@tonic-gate wtfs(fsbtodb(&sblock, (uint64_t)(sblock.fs_csaddr +
52817c478bd9Sstevel@tonic-gate numfrags(&sblock, i))),
52827c478bd9Sstevel@tonic-gate (int)(sblock.fs_cssize - i < sblock.fs_bsize ?
52837c478bd9Sstevel@tonic-gate sblock.fs_cssize - i : sblock.fs_bsize),
52847c478bd9Sstevel@tonic-gate ((char *)fscs) + i);
52857c478bd9Sstevel@tonic-gate
52867c478bd9Sstevel@tonic-gate /*
52877c478bd9Sstevel@tonic-gate * write superblock
52887c478bd9Sstevel@tonic-gate */
52897c478bd9Sstevel@tonic-gate sblock.fs_time = mkfstime;
52907c478bd9Sstevel@tonic-gate wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
52917c478bd9Sstevel@tonic-gate }
52927c478bd9Sstevel@tonic-gate
52937c478bd9Sstevel@tonic-gate /*
52947c478bd9Sstevel@tonic-gate * Verify that the optimization selection is reasonable, and advance
52957c478bd9Sstevel@tonic-gate * the global "string" appropriately.
52967c478bd9Sstevel@tonic-gate */
52977c478bd9Sstevel@tonic-gate static char
checkopt(char * optim)52987c478bd9Sstevel@tonic-gate checkopt(char *optim)
52997c478bd9Sstevel@tonic-gate {
53007c478bd9Sstevel@tonic-gate char opt;
53017c478bd9Sstevel@tonic-gate int limit = strcspn(optim, ",");
53027c478bd9Sstevel@tonic-gate
53037c478bd9Sstevel@tonic-gate switch (limit) {
53047c478bd9Sstevel@tonic-gate case 0: /* missing indicator (have comma or nul) */
53057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53067c478bd9Sstevel@tonic-gate "mkfs: missing optimization flag reset to `t' (time)\n"));
53077c478bd9Sstevel@tonic-gate opt = 't';
53087c478bd9Sstevel@tonic-gate break;
53097c478bd9Sstevel@tonic-gate
53107c478bd9Sstevel@tonic-gate case 1: /* single-character indicator */
53117c478bd9Sstevel@tonic-gate opt = *optim;
53127c478bd9Sstevel@tonic-gate if ((opt != 's') && (opt != 't')) {
53137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53147c478bd9Sstevel@tonic-gate "mkfs: bad optimization value `%c' reset to `t' (time)\n"),
53157c478bd9Sstevel@tonic-gate opt);
53167c478bd9Sstevel@tonic-gate opt = 't';
53177c478bd9Sstevel@tonic-gate }
53187c478bd9Sstevel@tonic-gate break;
53197c478bd9Sstevel@tonic-gate
53207c478bd9Sstevel@tonic-gate default: /* multi-character indicator */
53217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53227c478bd9Sstevel@tonic-gate "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"),
53237c478bd9Sstevel@tonic-gate limit, limit, optim);
53247c478bd9Sstevel@tonic-gate opt = 't';
53257c478bd9Sstevel@tonic-gate break;
53267c478bd9Sstevel@tonic-gate }
53277c478bd9Sstevel@tonic-gate
53287c478bd9Sstevel@tonic-gate string += limit;
53297c478bd9Sstevel@tonic-gate
53307c478bd9Sstevel@tonic-gate return (opt);
53317c478bd9Sstevel@tonic-gate }
53327c478bd9Sstevel@tonic-gate
53337c478bd9Sstevel@tonic-gate /*
53347c478bd9Sstevel@tonic-gate * Verify that the mtb selection is reasonable, and advance
53357c478bd9Sstevel@tonic-gate * the global "string" appropriately.
53367c478bd9Sstevel@tonic-gate */
53377c478bd9Sstevel@tonic-gate static char
checkmtb(char * mtbarg)53387c478bd9Sstevel@tonic-gate checkmtb(char *mtbarg)
53397c478bd9Sstevel@tonic-gate {
53407c478bd9Sstevel@tonic-gate char mtbc;
53417c478bd9Sstevel@tonic-gate int limit = strcspn(mtbarg, ",");
53427c478bd9Sstevel@tonic-gate
53437c478bd9Sstevel@tonic-gate switch (limit) {
53447c478bd9Sstevel@tonic-gate case 0: /* missing indicator (have comma or nul) */
53457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53467c478bd9Sstevel@tonic-gate "mkfs: missing mtb flag reset to `n' (no mtb support)\n"));
53477c478bd9Sstevel@tonic-gate mtbc = 'n';
53487c478bd9Sstevel@tonic-gate break;
53497c478bd9Sstevel@tonic-gate
53507c478bd9Sstevel@tonic-gate case 1: /* single-character indicator */
53517c478bd9Sstevel@tonic-gate mtbc = tolower(*mtbarg);
53527c478bd9Sstevel@tonic-gate if ((mtbc != 'y') && (mtbc != 'n')) {
53537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53547c478bd9Sstevel@tonic-gate "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"),
53557c478bd9Sstevel@tonic-gate mtbc);
53567c478bd9Sstevel@tonic-gate mtbc = 'n';
53577c478bd9Sstevel@tonic-gate }
53587c478bd9Sstevel@tonic-gate break;
53597c478bd9Sstevel@tonic-gate
53607c478bd9Sstevel@tonic-gate default: /* multi-character indicator */
53617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53627c478bd9Sstevel@tonic-gate "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"),
53637c478bd9Sstevel@tonic-gate limit, limit, mtbarg);
53647c478bd9Sstevel@tonic-gate opt = 'n';
53657c478bd9Sstevel@tonic-gate break;
53667c478bd9Sstevel@tonic-gate }
53677c478bd9Sstevel@tonic-gate
53687c478bd9Sstevel@tonic-gate string += limit;
53697c478bd9Sstevel@tonic-gate
53707c478bd9Sstevel@tonic-gate return (mtbc);
53717c478bd9Sstevel@tonic-gate }
53727c478bd9Sstevel@tonic-gate
53737c478bd9Sstevel@tonic-gate /*
53747c478bd9Sstevel@tonic-gate * Verify that a value is in a range. If it is not, resets it to
53757c478bd9Sstevel@tonic-gate * its default value if one is supplied, exits otherwise.
53767c478bd9Sstevel@tonic-gate *
53777c478bd9Sstevel@tonic-gate * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
53787c478bd9Sstevel@tonic-gate */
53797c478bd9Sstevel@tonic-gate static void
range_check(long * varp,char * name,long minimum,long maximum,long def_val,int user_supplied)53807c478bd9Sstevel@tonic-gate range_check(long *varp, char *name, long minimum, long maximum,
53817c478bd9Sstevel@tonic-gate long def_val, int user_supplied)
53827c478bd9Sstevel@tonic-gate {
53836451fdbcSvsakar dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n",
53846451fdbcSvsakar name, *varp, minimum, maximum, def_val));
53856451fdbcSvsakar
53867c478bd9Sstevel@tonic-gate if ((*varp < minimum) || (*varp > maximum)) {
53877c478bd9Sstevel@tonic-gate if (user_supplied != RC_DEFAULT) {
53887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
53897c478bd9Sstevel@tonic-gate "mkfs: bad value for %s: %ld must be between %ld and %ld\n"),
53907c478bd9Sstevel@tonic-gate name, *varp, minimum, maximum);
53917c478bd9Sstevel@tonic-gate }
53927c478bd9Sstevel@tonic-gate if (def_val != NO_DEFAULT) {
53937c478bd9Sstevel@tonic-gate if (user_supplied) {
53947c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
53957c478bd9Sstevel@tonic-gate gettext("mkfs: %s reset to default %ld\n"),
53967c478bd9Sstevel@tonic-gate name, def_val);
53977c478bd9Sstevel@tonic-gate }
53987c478bd9Sstevel@tonic-gate *varp = def_val;
53996451fdbcSvsakar dprintf(("DeBuG %s : %ld\n", name, *varp));
54007c478bd9Sstevel@tonic-gate return;
54017c478bd9Sstevel@tonic-gate }
54027c478bd9Sstevel@tonic-gate lockexit(2);
54037c478bd9Sstevel@tonic-gate /*NOTREACHED*/
54047c478bd9Sstevel@tonic-gate }
54057c478bd9Sstevel@tonic-gate }
54067c478bd9Sstevel@tonic-gate
54077c478bd9Sstevel@tonic-gate /*
54087c478bd9Sstevel@tonic-gate * Verify that a value is in a range. If it is not, resets it to
54097c478bd9Sstevel@tonic-gate * its default value if one is supplied, exits otherwise.
54107c478bd9Sstevel@tonic-gate *
54117c478bd9Sstevel@tonic-gate * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
54127c478bd9Sstevel@tonic-gate */
54137c478bd9Sstevel@tonic-gate static void
range_check_64(uint64_t * varp,char * name,uint64_t minimum,uint64_t maximum,uint64_t def_val,int user_supplied)54147c478bd9Sstevel@tonic-gate range_check_64(uint64_t *varp, char *name, uint64_t minimum, uint64_t maximum,
54157c478bd9Sstevel@tonic-gate uint64_t def_val, int user_supplied)
54167c478bd9Sstevel@tonic-gate {
54177c478bd9Sstevel@tonic-gate if ((*varp < minimum) || (*varp > maximum)) {
54187c478bd9Sstevel@tonic-gate if (user_supplied != RC_DEFAULT) {
54197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
54207c478bd9Sstevel@tonic-gate "mkfs: bad value for %s: %lld must be between %lld and %lld\n"),
54217c478bd9Sstevel@tonic-gate name, *varp, minimum, maximum);
54227c478bd9Sstevel@tonic-gate }
54237c478bd9Sstevel@tonic-gate if (def_val != NO_DEFAULT) {
54247c478bd9Sstevel@tonic-gate if (user_supplied) {
54257c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
54267c478bd9Sstevel@tonic-gate gettext("mkfs: %s reset to default %lld\n"),
54277c478bd9Sstevel@tonic-gate name, def_val);
54287c478bd9Sstevel@tonic-gate }
54297c478bd9Sstevel@tonic-gate *varp = def_val;
54307c478bd9Sstevel@tonic-gate return;
54317c478bd9Sstevel@tonic-gate }
54327c478bd9Sstevel@tonic-gate lockexit(2);
54337c478bd9Sstevel@tonic-gate /*NOTREACHED*/
54347c478bd9Sstevel@tonic-gate }
54357c478bd9Sstevel@tonic-gate }
54367c478bd9Sstevel@tonic-gate
54377c478bd9Sstevel@tonic-gate /*
54387c478bd9Sstevel@tonic-gate * Blocks SIGINT from delivery. Returns the previous mask in the
54397c478bd9Sstevel@tonic-gate * buffer provided, so that mask may be later restored.
54407c478bd9Sstevel@tonic-gate */
54417c478bd9Sstevel@tonic-gate static void
block_sigint(sigset_t * old_mask)54427c478bd9Sstevel@tonic-gate block_sigint(sigset_t *old_mask)
54437c478bd9Sstevel@tonic-gate {
54447c478bd9Sstevel@tonic-gate sigset_t block_mask;
54457c478bd9Sstevel@tonic-gate
54467c478bd9Sstevel@tonic-gate if (sigemptyset(&block_mask) < 0) {
54477c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Could not clear signal mask\n"));
54487c478bd9Sstevel@tonic-gate lockexit(3);
54497c478bd9Sstevel@tonic-gate }
54507c478bd9Sstevel@tonic-gate if (sigaddset(&block_mask, SIGINT) < 0) {
54517c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Could not set signal mask\n"));
54527c478bd9Sstevel@tonic-gate lockexit(3);
54537c478bd9Sstevel@tonic-gate }
54547c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_BLOCK, &block_mask, old_mask) < 0) {
54557c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Could not block SIGINT\n"));
54567c478bd9Sstevel@tonic-gate lockexit(3);
54577c478bd9Sstevel@tonic-gate }
54587c478bd9Sstevel@tonic-gate }
54597c478bd9Sstevel@tonic-gate
54607c478bd9Sstevel@tonic-gate /*
54617c478bd9Sstevel@tonic-gate * Restores the signal mask that was in force before a call
54627c478bd9Sstevel@tonic-gate * to block_sigint(). This may actually still have SIGINT blocked,
54637c478bd9Sstevel@tonic-gate * if we've been recursively invoked.
54647c478bd9Sstevel@tonic-gate */
54657c478bd9Sstevel@tonic-gate static void
unblock_sigint(sigset_t * old_mask)54667c478bd9Sstevel@tonic-gate unblock_sigint(sigset_t *old_mask)
54677c478bd9Sstevel@tonic-gate {
54687c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_UNBLOCK, old_mask, (sigset_t *)NULL) < 0) {
54697c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Could not restore signal mask\n"));
54707c478bd9Sstevel@tonic-gate lockexit(3);
54717c478bd9Sstevel@tonic-gate }
54727c478bd9Sstevel@tonic-gate }
54737c478bd9Sstevel@tonic-gate
54747c478bd9Sstevel@tonic-gate /*
54757c478bd9Sstevel@tonic-gate * Attempt to be somewhat graceful about being interrupted, rather than
54767c478bd9Sstevel@tonic-gate * just silently leaving the filesystem in an unusable state.
54777c478bd9Sstevel@tonic-gate *
54787c478bd9Sstevel@tonic-gate * The kernel has blocked SIGINT upon entry, so we don't have to worry
54797c478bd9Sstevel@tonic-gate * about recursion if the user starts pounding on the keyboard.
54807c478bd9Sstevel@tonic-gate */
54817c478bd9Sstevel@tonic-gate static void
recover_from_sigint(int signum)54827c478bd9Sstevel@tonic-gate recover_from_sigint(int signum)
54837c478bd9Sstevel@tonic-gate {
54847c478bd9Sstevel@tonic-gate if (fso > -1) {
54857c478bd9Sstevel@tonic-gate if ((Nflag != 0) || confirm_abort()) {
54867c478bd9Sstevel@tonic-gate lockexit(4);
54877c478bd9Sstevel@tonic-gate }
54887c478bd9Sstevel@tonic-gate }
54897c478bd9Sstevel@tonic-gate }
54907c478bd9Sstevel@tonic-gate
54917c478bd9Sstevel@tonic-gate static int
confirm_abort(void)54927c478bd9Sstevel@tonic-gate confirm_abort(void)
54937c478bd9Sstevel@tonic-gate {
54947c478bd9Sstevel@tonic-gate char line[80];
54957c478bd9Sstevel@tonic-gate
54967c478bd9Sstevel@tonic-gate printf(gettext("\n\nAborting at this point will leave the filesystem "
54977c478bd9Sstevel@tonic-gate "in an inconsistent\nstate. If you do choose to stop, "
54987c478bd9Sstevel@tonic-gate "you will be given instructions on how to\nrecover "
54997c478bd9Sstevel@tonic-gate "the filesystem. Do you wish to cancel the filesystem "
55007c478bd9Sstevel@tonic-gate "grow\noperation (y/n)?"));
550123a1cceaSRoger A. Faulkner if (getaline(stdin, line, sizeof (line)) == EOF)
55027c478bd9Sstevel@tonic-gate line[0] = 'y';
55037c478bd9Sstevel@tonic-gate
55047c478bd9Sstevel@tonic-gate printf("\n");
55057c478bd9Sstevel@tonic-gate if (line[0] == 'y' || line[0] == 'Y')
55067c478bd9Sstevel@tonic-gate return (1);
55077c478bd9Sstevel@tonic-gate else {
55087c478bd9Sstevel@tonic-gate return (0);
55097c478bd9Sstevel@tonic-gate }
55107c478bd9Sstevel@tonic-gate }
55117c478bd9Sstevel@tonic-gate
55127c478bd9Sstevel@tonic-gate static int
getaline(FILE * fp,char * loc,int maxlen)551323a1cceaSRoger A. Faulkner getaline(FILE *fp, char *loc, int maxlen)
55147c478bd9Sstevel@tonic-gate {
55157c478bd9Sstevel@tonic-gate int n;
55167c478bd9Sstevel@tonic-gate char *p, *lastloc;
55177c478bd9Sstevel@tonic-gate
55187c478bd9Sstevel@tonic-gate p = loc;
55197c478bd9Sstevel@tonic-gate lastloc = &p[maxlen-1];
55207c478bd9Sstevel@tonic-gate while ((n = getc(fp)) != '\n') {
55217c478bd9Sstevel@tonic-gate if (n == EOF)
55227c478bd9Sstevel@tonic-gate return (EOF);
55237c478bd9Sstevel@tonic-gate if (!isspace(n) && p < lastloc)
55247c478bd9Sstevel@tonic-gate *p++ = n;
55257c478bd9Sstevel@tonic-gate }
55267c478bd9Sstevel@tonic-gate *p = 0;
55277c478bd9Sstevel@tonic-gate return (p - loc);
55287c478bd9Sstevel@tonic-gate }
55297c478bd9Sstevel@tonic-gate
55307c478bd9Sstevel@tonic-gate /*
55317c478bd9Sstevel@tonic-gate * Calculate the maximum value of cylinders-per-group for a file
55327c478bd9Sstevel@tonic-gate * system with the characteristics:
55337c478bd9Sstevel@tonic-gate *
55347c478bd9Sstevel@tonic-gate * bsize - file system block size
55357c478bd9Sstevel@tonic-gate * fragsize - frag size
55367c478bd9Sstevel@tonic-gate * nbpi - number of bytes of disk space per inode
55377c478bd9Sstevel@tonic-gate * nrpos - number of rotational positions
55387c478bd9Sstevel@tonic-gate * spc - sectors per cylinder
55397c478bd9Sstevel@tonic-gate *
55407c478bd9Sstevel@tonic-gate * These five characteristic are not adjustable (by this function).
55417c478bd9Sstevel@tonic-gate * The only attribute of the file system which IS adjusted by this
55427c478bd9Sstevel@tonic-gate * function in order to maximize cylinders-per-group is the proportion
55437c478bd9Sstevel@tonic-gate * of the cylinder group overhead block used for the inode map. The
55447c478bd9Sstevel@tonic-gate * inode map cannot occupy more than one-third of the cylinder group
55457c478bd9Sstevel@tonic-gate * overhead block, but it's OK for it to occupy less than one-third
55467c478bd9Sstevel@tonic-gate * of the overhead block.
55477c478bd9Sstevel@tonic-gate *
55487c478bd9Sstevel@tonic-gate * The setting of nbpi determines one possible value for the maximum
55497c478bd9Sstevel@tonic-gate * size of a cylinder group. It does so because it determines the total
55507c478bd9Sstevel@tonic-gate * number of inodes in the file system (file system size is fixed, and
55517c478bd9Sstevel@tonic-gate * nbpi is fixed, so the total number of inodes is fixed too). The
55527c478bd9Sstevel@tonic-gate * cylinder group has to be small enough so that the number of inodes
55537c478bd9Sstevel@tonic-gate * in the cylinder group is less than or equal to the number of bits
55547c478bd9Sstevel@tonic-gate * in one-third (or whatever proportion is assumed) of a file system
55557c478bd9Sstevel@tonic-gate * block. The details of the calculation are:
55567c478bd9Sstevel@tonic-gate *
55577c478bd9Sstevel@tonic-gate * The macro MAXIpG_B(bsize, inode_divisor) determines the maximum
55587c478bd9Sstevel@tonic-gate * number of inodes that can be in a cylinder group, given the
55597c478bd9Sstevel@tonic-gate * proportion of the cylinder group overhead block used for the
55607c478bd9Sstevel@tonic-gate * inode bitmaps (an inode_divisor of 3 means that 1/3 of the
55617c478bd9Sstevel@tonic-gate * block is used for inode bitmaps; an inode_divisor of 12 means
55627c478bd9Sstevel@tonic-gate * that 1/12 of the block is used for inode bitmaps.)
55637c478bd9Sstevel@tonic-gate *
55647c478bd9Sstevel@tonic-gate * Once the number of inodes per cylinder group is known, the
55657c478bd9Sstevel@tonic-gate * maximum value of cylinders-per-group (determined by nbpi)
55667c478bd9Sstevel@tonic-gate * is calculated by the formula
55677c478bd9Sstevel@tonic-gate *
55687c478bd9Sstevel@tonic-gate * maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder)
55697c478bd9Sstevel@tonic-gate *
55707c478bd9Sstevel@tonic-gate * = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE)
55717c478bd9Sstevel@tonic-gate *
55727c478bd9Sstevel@tonic-gate * (Interestingly, the size of the file system never enters
55737c478bd9Sstevel@tonic-gate * into this calculation.)
55747c478bd9Sstevel@tonic-gate *
55757c478bd9Sstevel@tonic-gate * Another possible value for the maximum cylinder group size is determined
55767c478bd9Sstevel@tonic-gate * by frag_size and nrpos. The frags in the cylinder group must be
55777c478bd9Sstevel@tonic-gate * representable in the frag bitmaps in the cylinder overhead block and the
55787c478bd9Sstevel@tonic-gate * rotational positions for each cylinder must be represented in the
55797c478bd9Sstevel@tonic-gate * rotational position tables. The calculation of the maximum cpg
55807c478bd9Sstevel@tonic-gate * value, given the frag and nrpos vales, is:
55817c478bd9Sstevel@tonic-gate *
55827c478bd9Sstevel@tonic-gate * maxcpg_given_fragsize =
55837c478bd9Sstevel@tonic-gate * (available space in the overhead block) / (size of per-cylinder data)
55847c478bd9Sstevel@tonic-gate *
55857c478bd9Sstevel@tonic-gate * The available space in the overhead block =
55867c478bd9Sstevel@tonic-gate * bsize - sizeof (struct cg) - space_used_for_inode_bitmaps
55877c478bd9Sstevel@tonic-gate *
55887c478bd9Sstevel@tonic-gate * The size of the per-cylinder data is:
55897c478bd9Sstevel@tonic-gate * sizeof(long) # for the "blocks avail per cylinder" field
55907c478bd9Sstevel@tonic-gate * + nrpos * sizeof(short) # for the rotational position table entry
55917c478bd9Sstevel@tonic-gate * + frags-per-cylinder/NBBY # number of bytes to represent this
55927c478bd9Sstevel@tonic-gate * # cylinder in the frag bitmap
55937c478bd9Sstevel@tonic-gate *
55947c478bd9Sstevel@tonic-gate * The two calculated maximum values of cylinder-per-group will typically
55957c478bd9Sstevel@tonic-gate * turn out to be different, since they are derived from two different
55967c478bd9Sstevel@tonic-gate * constraints. Usually, maxcpg_given_nbpi is much bigger than
55977c478bd9Sstevel@tonic-gate * maxcpg_given_fragsize. But they can be brought together by
55987c478bd9Sstevel@tonic-gate * adjusting the proportion of the overhead block dedicated to
55997c478bd9Sstevel@tonic-gate * the inode bitmaps. Decreasing the proportion of the cylinder
56007c478bd9Sstevel@tonic-gate * group overhead block used for inode maps will decrease
56017c478bd9Sstevel@tonic-gate * maxcpg_given_nbpi and increase maxcpg_given_fragsize.
56027c478bd9Sstevel@tonic-gate *
56037c478bd9Sstevel@tonic-gate * This function calculates the initial values of maxcpg_given_nbpi
56047c478bd9Sstevel@tonic-gate * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead
56057c478bd9Sstevel@tonic-gate * block is used for inode bitmaps. Then it decreases the proportion
56067c478bd9Sstevel@tonic-gate * of the cg overhead block used for inode bitmaps (by increasing
56077c478bd9Sstevel@tonic-gate * the value of inode_divisor) until maxcpg_given_nbpi and
56087c478bd9Sstevel@tonic-gate * maxcpg_given_fragsize are the same, or stop changing, or
56097c478bd9Sstevel@tonic-gate * maxcpg_given_nbpi is less than maxcpg_given_fragsize.
56107c478bd9Sstevel@tonic-gate *
56117c478bd9Sstevel@tonic-gate * The loop terminates when any of the following occur:
56127c478bd9Sstevel@tonic-gate * * maxcpg_given_fragsize is greater than or equal to
56137c478bd9Sstevel@tonic-gate * maxcpg_given_nbpi
56147c478bd9Sstevel@tonic-gate * * neither maxcpg_given_fragsize nor maxcpg_given_nbpi
56157c478bd9Sstevel@tonic-gate * change in the expected direction
56167c478bd9Sstevel@tonic-gate *
56177c478bd9Sstevel@tonic-gate * The loop is guaranteed to terminate because it only continues
56187c478bd9Sstevel@tonic-gate * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching
56197c478bd9Sstevel@tonic-gate * each other. As soon they cross each other, or neither one changes
56207c478bd9Sstevel@tonic-gate * in the direction of the other, or one of them moves in the wrong
56217c478bd9Sstevel@tonic-gate * direction, the loop completes.
56227c478bd9Sstevel@tonic-gate */
56237c478bd9Sstevel@tonic-gate
56247c478bd9Sstevel@tonic-gate static long
compute_maxcpg(long bsize,long fragsize,long nbpi,long nrpos,long spc)56257c478bd9Sstevel@tonic-gate compute_maxcpg(long bsize, long fragsize, long nbpi, long nrpos, long spc)
56267c478bd9Sstevel@tonic-gate {
56277c478bd9Sstevel@tonic-gate int maxcpg_given_nbpi; /* in cylinders */
56287c478bd9Sstevel@tonic-gate int maxcpg_given_fragsize; /* in cylinders */
56297c478bd9Sstevel@tonic-gate int spf; /* sectors per frag */
56307c478bd9Sstevel@tonic-gate int inode_divisor;
56317c478bd9Sstevel@tonic-gate int old_max_given_frag = 0;
56327c478bd9Sstevel@tonic-gate int old_max_given_nbpi = INT_MAX;
56337c478bd9Sstevel@tonic-gate
56347c478bd9Sstevel@tonic-gate spf = fragsize / DEV_BSIZE;
56357c478bd9Sstevel@tonic-gate inode_divisor = 3;
56367c478bd9Sstevel@tonic-gate
56377c478bd9Sstevel@tonic-gate while (1) {
56387c478bd9Sstevel@tonic-gate maxcpg_given_nbpi =
56397c478bd9Sstevel@tonic-gate (((int64_t)(MAXIpG_B(bsize, inode_divisor))) * nbpi) /
56407c478bd9Sstevel@tonic-gate (DEV_BSIZE * ((int64_t)spc));
56417c478bd9Sstevel@tonic-gate maxcpg_given_fragsize =
56427c478bd9Sstevel@tonic-gate (bsize - (sizeof (struct cg)) - (bsize / inode_divisor)) /
56437c478bd9Sstevel@tonic-gate (sizeof (long) + nrpos * sizeof (short) +
56447c478bd9Sstevel@tonic-gate (spc / spf) / NBBY);
56457c478bd9Sstevel@tonic-gate
56467c478bd9Sstevel@tonic-gate if (maxcpg_given_fragsize >= maxcpg_given_nbpi)
56477c478bd9Sstevel@tonic-gate return (maxcpg_given_nbpi);
56487c478bd9Sstevel@tonic-gate
56497c478bd9Sstevel@tonic-gate /*
56507c478bd9Sstevel@tonic-gate * If neither value moves toward the other, return the
56517c478bd9Sstevel@tonic-gate * least of the old values (we use the old instead of the
56527c478bd9Sstevel@tonic-gate * new because: if the old is the same as the new, it
56537c478bd9Sstevel@tonic-gate * doesn't matter which ones we use. If one of the
56547c478bd9Sstevel@tonic-gate * values changed, but in the wrong direction, the
56557c478bd9Sstevel@tonic-gate * new values are suspect. Better use the old. This
56567c478bd9Sstevel@tonic-gate * shouldn't happen, but it's best to check.
56577c478bd9Sstevel@tonic-gate */
56587c478bd9Sstevel@tonic-gate
56597c478bd9Sstevel@tonic-gate if (!(maxcpg_given_nbpi < old_max_given_nbpi) &&
56607c478bd9Sstevel@tonic-gate !(maxcpg_given_fragsize > old_max_given_frag))
56617c478bd9Sstevel@tonic-gate return (MIN(old_max_given_nbpi, old_max_given_frag));
56627c478bd9Sstevel@tonic-gate
56637c478bd9Sstevel@tonic-gate /*
56647c478bd9Sstevel@tonic-gate * This is probably impossible, but if one of the maxcpg
56657c478bd9Sstevel@tonic-gate * values moved in the "right" direction and one moved
56667c478bd9Sstevel@tonic-gate * in the "wrong" direction (that is, the two values moved
56677c478bd9Sstevel@tonic-gate * in the same direction), the previous conditional won't
56687c478bd9Sstevel@tonic-gate * recognize that the values aren't converging (since at
56697c478bd9Sstevel@tonic-gate * least one value moved in the "right" direction, the
56707c478bd9Sstevel@tonic-gate * last conditional says "keep going").
56717c478bd9Sstevel@tonic-gate *
56727c478bd9Sstevel@tonic-gate * Just to make absolutely certain that the loop terminates,
56737c478bd9Sstevel@tonic-gate * check for one of the values moving in the "wrong" direction
56747c478bd9Sstevel@tonic-gate * and terminate the loop if it happens.
56757c478bd9Sstevel@tonic-gate */
56767c478bd9Sstevel@tonic-gate
56777c478bd9Sstevel@tonic-gate if (maxcpg_given_nbpi > old_max_given_nbpi ||
56787c478bd9Sstevel@tonic-gate maxcpg_given_fragsize < old_max_given_frag)
56797c478bd9Sstevel@tonic-gate return (MIN(old_max_given_nbpi, old_max_given_frag));
56807c478bd9Sstevel@tonic-gate
56817c478bd9Sstevel@tonic-gate old_max_given_nbpi = maxcpg_given_nbpi;
56827c478bd9Sstevel@tonic-gate old_max_given_frag = maxcpg_given_fragsize;
56837c478bd9Sstevel@tonic-gate
56847c478bd9Sstevel@tonic-gate inode_divisor++;
56857c478bd9Sstevel@tonic-gate }
56867c478bd9Sstevel@tonic-gate }
56877c478bd9Sstevel@tonic-gate
56887c478bd9Sstevel@tonic-gate static int
in_64bit_mode(void)56897c478bd9Sstevel@tonic-gate in_64bit_mode(void)
56907c478bd9Sstevel@tonic-gate {
56917c478bd9Sstevel@tonic-gate /* cmd must be an absolute path, for security */
56927c478bd9Sstevel@tonic-gate char *cmd = "/usr/bin/isainfo -b";
56937c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
56947c478bd9Sstevel@tonic-gate FILE *ptr;
56957c478bd9Sstevel@tonic-gate int retval = 0;
56967c478bd9Sstevel@tonic-gate
56977c478bd9Sstevel@tonic-gate putenv("IFS= \t");
56987c478bd9Sstevel@tonic-gate if ((ptr = popen(cmd, "r")) != NULL) {
56997c478bd9Sstevel@tonic-gate if (fgets(buf, BUFSIZ, ptr) != NULL &&
57007c478bd9Sstevel@tonic-gate strncmp(buf, "64", 2) == 0)
57017c478bd9Sstevel@tonic-gate retval = 1;
57027c478bd9Sstevel@tonic-gate (void) pclose(ptr);
57037c478bd9Sstevel@tonic-gate }
57047c478bd9Sstevel@tonic-gate return (retval);
57057c478bd9Sstevel@tonic-gate }
57067c478bd9Sstevel@tonic-gate
57077c478bd9Sstevel@tonic-gate /*
57087c478bd9Sstevel@tonic-gate * validate_size
57097c478bd9Sstevel@tonic-gate *
57107c478bd9Sstevel@tonic-gate * Return 1 if the device appears to be at least "size" sectors long.
57117c478bd9Sstevel@tonic-gate * Return 0 if it's shorter or we can't read it.
57127c478bd9Sstevel@tonic-gate */
57137c478bd9Sstevel@tonic-gate
57147c478bd9Sstevel@tonic-gate static int
validate_size(int fd,diskaddr_t size)57157c478bd9Sstevel@tonic-gate validate_size(int fd, diskaddr_t size)
57167c478bd9Sstevel@tonic-gate {
57177c478bd9Sstevel@tonic-gate char buf[DEV_BSIZE];
57187c478bd9Sstevel@tonic-gate int rc;
57197c478bd9Sstevel@tonic-gate
57207c478bd9Sstevel@tonic-gate if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) ||
57217c478bd9Sstevel@tonic-gate (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)
57227c478bd9Sstevel@tonic-gate rc = 0;
57237c478bd9Sstevel@tonic-gate else
57247c478bd9Sstevel@tonic-gate rc = 1;
57257c478bd9Sstevel@tonic-gate return (rc);
57267c478bd9Sstevel@tonic-gate }
5727355d6bb5Sswilcox
5728355d6bb5Sswilcox /*
5729355d6bb5Sswilcox * Print every field of the calculated superblock, along with
5730355d6bb5Sswilcox * its value. To make parsing easier on the caller, the value
5731355d6bb5Sswilcox * is printed first, then the name. Additionally, there's only
5732355d6bb5Sswilcox * one name/value pair per line. All values are reported in
5733355d6bb5Sswilcox * hexadecimal (with the traditional 0x prefix), as that's slightly
5734355d6bb5Sswilcox * easier for humans to read. Not that they're expected to, but
5735355d6bb5Sswilcox * debugging happens.
5736355d6bb5Sswilcox */
5737355d6bb5Sswilcox static void
dump_sblock(void)5738355d6bb5Sswilcox dump_sblock(void)
5739355d6bb5Sswilcox {
5740355d6bb5Sswilcox int row, column, pending, written;
5741355d6bb5Sswilcox caddr_t source;
5742355d6bb5Sswilcox
5743355d6bb5Sswilcox if (Rflag) {
5744355d6bb5Sswilcox pending = sizeof (sblock);
5745355d6bb5Sswilcox source = (caddr_t)&sblock;
5746355d6bb5Sswilcox do {
5747355d6bb5Sswilcox written = write(fileno(stdout), source, pending);
5748355d6bb5Sswilcox pending -= written;
5749355d6bb5Sswilcox source += written;
5750355d6bb5Sswilcox } while ((pending > 0) && (written > 0));
5751355d6bb5Sswilcox
5752355d6bb5Sswilcox if (written < 0) {
5753355d6bb5Sswilcox perror(gettext("Binary dump of superblock failed"));
5754355d6bb5Sswilcox lockexit(1);
5755355d6bb5Sswilcox }
5756355d6bb5Sswilcox return;
5757355d6bb5Sswilcox } else {
5758355d6bb5Sswilcox printf("0x%x sblock.fs_link\n", sblock.fs_link);
5759355d6bb5Sswilcox printf("0x%x sblock.fs_rolled\n", sblock.fs_rolled);
5760355d6bb5Sswilcox printf("0x%x sblock.fs_sblkno\n", sblock.fs_sblkno);
5761355d6bb5Sswilcox printf("0x%x sblock.fs_cblkno\n", sblock.fs_cblkno);
5762355d6bb5Sswilcox printf("0x%x sblock.fs_iblkno\n", sblock.fs_iblkno);
5763355d6bb5Sswilcox printf("0x%x sblock.fs_dblkno\n", sblock.fs_dblkno);
5764355d6bb5Sswilcox printf("0x%x sblock.fs_cgoffset\n", sblock.fs_cgoffset);
5765355d6bb5Sswilcox printf("0x%x sblock.fs_cgmask\n", sblock.fs_cgmask);
5766355d6bb5Sswilcox printf("0x%x sblock.fs_time\n", sblock.fs_time);
5767355d6bb5Sswilcox printf("0x%x sblock.fs_size\n", sblock.fs_size);
5768355d6bb5Sswilcox printf("0x%x sblock.fs_dsize\n", sblock.fs_dsize);
5769355d6bb5Sswilcox printf("0x%x sblock.fs_ncg\n", sblock.fs_ncg);
5770355d6bb5Sswilcox printf("0x%x sblock.fs_bsize\n", sblock.fs_bsize);
5771355d6bb5Sswilcox printf("0x%x sblock.fs_fsize\n", sblock.fs_fsize);
5772355d6bb5Sswilcox printf("0x%x sblock.fs_frag\n", sblock.fs_frag);
5773355d6bb5Sswilcox printf("0x%x sblock.fs_minfree\n", sblock.fs_minfree);
5774355d6bb5Sswilcox printf("0x%x sblock.fs_rotdelay\n", sblock.fs_rotdelay);
5775355d6bb5Sswilcox printf("0x%x sblock.fs_rps\n", sblock.fs_rps);
5776355d6bb5Sswilcox printf("0x%x sblock.fs_bmask\n", sblock.fs_bmask);
5777355d6bb5Sswilcox printf("0x%x sblock.fs_fmask\n", sblock.fs_fmask);
5778355d6bb5Sswilcox printf("0x%x sblock.fs_bshift\n", sblock.fs_bshift);
5779355d6bb5Sswilcox printf("0x%x sblock.fs_fshift\n", sblock.fs_fshift);
5780355d6bb5Sswilcox printf("0x%x sblock.fs_maxcontig\n", sblock.fs_maxcontig);
5781355d6bb5Sswilcox printf("0x%x sblock.fs_maxbpg\n", sblock.fs_maxbpg);
5782355d6bb5Sswilcox printf("0x%x sblock.fs_fragshift\n", sblock.fs_fragshift);
5783355d6bb5Sswilcox printf("0x%x sblock.fs_fsbtodb\n", sblock.fs_fsbtodb);
5784355d6bb5Sswilcox printf("0x%x sblock.fs_sbsize\n", sblock.fs_sbsize);
5785355d6bb5Sswilcox printf("0x%x sblock.fs_csmask\n", sblock.fs_csmask);
5786355d6bb5Sswilcox printf("0x%x sblock.fs_csshift\n", sblock.fs_csshift);
5787355d6bb5Sswilcox printf("0x%x sblock.fs_nindir\n", sblock.fs_nindir);
5788355d6bb5Sswilcox printf("0x%x sblock.fs_inopb\n", sblock.fs_inopb);
5789355d6bb5Sswilcox printf("0x%x sblock.fs_nspf\n", sblock.fs_nspf);
5790355d6bb5Sswilcox printf("0x%x sblock.fs_optim\n", sblock.fs_optim);
5791355d6bb5Sswilcox #ifdef _LITTLE_ENDIAN
5792355d6bb5Sswilcox printf("0x%x sblock.fs_state\n", sblock.fs_state);
5793355d6bb5Sswilcox #else
5794355d6bb5Sswilcox printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5795355d6bb5Sswilcox #endif
5796355d6bb5Sswilcox printf("0x%x sblock.fs_si\n", sblock.fs_si);
5797355d6bb5Sswilcox printf("0x%x sblock.fs_trackskew\n", sblock.fs_trackskew);
5798355d6bb5Sswilcox printf("0x%x sblock.fs_id[0]\n", sblock.fs_id[0]);
5799355d6bb5Sswilcox printf("0x%x sblock.fs_id[1]\n", sblock.fs_id[1]);
5800355d6bb5Sswilcox printf("0x%x sblock.fs_csaddr\n", sblock.fs_csaddr);
5801355d6bb5Sswilcox printf("0x%x sblock.fs_cssize\n", sblock.fs_cssize);
5802355d6bb5Sswilcox printf("0x%x sblock.fs_cgsize\n", sblock.fs_cgsize);
5803355d6bb5Sswilcox printf("0x%x sblock.fs_ntrak\n", sblock.fs_ntrak);
5804355d6bb5Sswilcox printf("0x%x sblock.fs_nsect\n", sblock.fs_nsect);
5805355d6bb5Sswilcox printf("0x%x sblock.fs_spc\n", sblock.fs_spc);
5806355d6bb5Sswilcox printf("0x%x sblock.fs_ncyl\n", sblock.fs_ncyl);
5807355d6bb5Sswilcox printf("0x%x sblock.fs_cpg\n", sblock.fs_cpg);
5808355d6bb5Sswilcox printf("0x%x sblock.fs_ipg\n", sblock.fs_ipg);
5809355d6bb5Sswilcox printf("0x%x sblock.fs_fpg\n", sblock.fs_fpg);
5810355d6bb5Sswilcox printf("0x%x sblock.fs_cstotal\n", sblock.fs_cstotal);
5811355d6bb5Sswilcox printf("0x%x sblock.fs_fmod\n", sblock.fs_fmod);
5812355d6bb5Sswilcox printf("0x%x sblock.fs_clean\n", sblock.fs_clean);
5813355d6bb5Sswilcox printf("0x%x sblock.fs_ronly\n", sblock.fs_ronly);
5814355d6bb5Sswilcox printf("0x%x sblock.fs_flags\n", sblock.fs_flags);
5815355d6bb5Sswilcox printf("0x%x sblock.fs_fsmnt\n", sblock.fs_fsmnt);
5816355d6bb5Sswilcox printf("0x%x sblock.fs_cgrotor\n", sblock.fs_cgrotor);
5817355d6bb5Sswilcox printf("0x%x sblock.fs_u.fs_csp\n", sblock.fs_u.fs_csp);
5818355d6bb5Sswilcox printf("0x%x sblock.fs_cpc\n", sblock.fs_cpc);
5819355d6bb5Sswilcox
5820355d6bb5Sswilcox /*
5821355d6bb5Sswilcox * No macros are defined for the dimensions of the
5822355d6bb5Sswilcox * opostbl array.
5823355d6bb5Sswilcox */
5824355d6bb5Sswilcox for (row = 0; row < 16; row++) {
5825355d6bb5Sswilcox for (column = 0; column < 8; column++) {
5826355d6bb5Sswilcox printf("0x%x sblock.fs_opostbl[%d][%d]\n",
5827355d6bb5Sswilcox sblock.fs_opostbl[row][column],
5828355d6bb5Sswilcox row, column);
5829355d6bb5Sswilcox }
5830355d6bb5Sswilcox }
5831355d6bb5Sswilcox
5832355d6bb5Sswilcox /*
5833355d6bb5Sswilcox * Ditto the size of sparecon.
5834355d6bb5Sswilcox */
5835355d6bb5Sswilcox for (row = 0; row < 51; row++) {
5836355d6bb5Sswilcox printf("0x%x sblock.fs_sparecon[%d]\n",
5837355d6bb5Sswilcox sblock.fs_sparecon[row], row);
5838355d6bb5Sswilcox }
5839355d6bb5Sswilcox
5840355d6bb5Sswilcox printf("0x%x sblock.fs_version\n", sblock.fs_version);
5841355d6bb5Sswilcox printf("0x%x sblock.fs_logbno\n", sblock.fs_logbno);
5842355d6bb5Sswilcox printf("0x%x sblock.fs_reclaim\n", sblock.fs_reclaim);
5843355d6bb5Sswilcox printf("0x%x sblock.fs_sparecon2\n", sblock.fs_sparecon2);
5844355d6bb5Sswilcox #ifdef _LITTLE_ENDIAN
5845355d6bb5Sswilcox printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5846355d6bb5Sswilcox #else
5847355d6bb5Sswilcox printf("0x%x sblock.fs_state\n", sblock.fs_state);
5848355d6bb5Sswilcox #endif
5849355d6bb5Sswilcox printf("0x%llx sblock.fs_qbmask\n", sblock.fs_qbmask);
5850355d6bb5Sswilcox printf("0x%llx sblock.fs_qfmask\n", sblock.fs_qfmask);
5851355d6bb5Sswilcox printf("0x%x sblock.fs_postblformat\n", sblock.fs_postblformat);
5852355d6bb5Sswilcox printf("0x%x sblock.fs_nrpos\n", sblock.fs_nrpos);
5853355d6bb5Sswilcox printf("0x%x sblock.fs_postbloff\n", sblock.fs_postbloff);
5854355d6bb5Sswilcox printf("0x%x sblock.fs_rotbloff\n", sblock.fs_rotbloff);
5855355d6bb5Sswilcox printf("0x%x sblock.fs_magic\n", sblock.fs_magic);
5856355d6bb5Sswilcox
5857355d6bb5Sswilcox /*
5858355d6bb5Sswilcox * fs_space isn't of much use in this context, so we'll
5859355d6bb5Sswilcox * just ignore it for now.
5860355d6bb5Sswilcox */
5861355d6bb5Sswilcox }
5862355d6bb5Sswilcox }
5863