4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
40 * The maximum supported file system size (in sectors) is the
41 * number of frags that can be represented in an int32_t field
42 * (INT_MAX) times the maximum number of sectors per frag. Since
43 * the maximum frag size is MAXBSIZE, the maximum number of sectors
44 * per frag is MAXBSIZE/DEV_BSIZE.
46 #define FS_MAX (((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
49 * make file system for cylinder-group style file systems
53 * mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
54 * [-o specific_options] special size
55 * [nsect ntrack bsize fsize cpg minfree rps nbpi opt apc rotdelay
56 * 2 3 4 5 6 7 8 9 10 11 12
57 * nrpos maxcontig mtb]
60 * where specific_options are:
62 * nsect - The number of sectors per track
63 * ntrack - The number of tracks per cylinder
65 * fragsize - fragment size
66 * cgsize - The number of disk cylinders per cylinder group.
67 * free - minimum free space
68 * rps - rotational speed (rev/sec).
69 * nbpi - number of data bytes per allocated inode
70 * opt - optimization (space, time)
71 * apc - number of alternates
73 * nrpos - number of rotational positions
74 * maxcontig - maximum number of logical blocks that will be
75 * allocated contiguously before inserting rotational delay
76 * mtb - if "y", set up file system for eventual growth to over a
78 * -P Do not grow the file system, but print on stdout the maximal
79 * size in sectors to which the file system can be increased. The calculated
80 * size is limited by the value provided by the operand size.
82 * Note that -P is a project-private interface and together with -G intended
83 * to be used only by the growfs script. It is therefore purposely not
84 * documented in the man page.
85 * The -P option is covered by PSARC case 2003/422.
89 * The following constants set the defaults used for the number
90 * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
97 * However the defaults will be different for disks larger than CHSLIMIT.
104 * The following default sectors and tracks values are used for
105 * non-efi disks that are larger than the CHS addressing limit. The
106 * existing default cpg of 16 (DESCPG) holds good for larger disks too.
108 #define DEF_SECTORS_EFI 128
109 #define DEF_TRACKS_EFI 48
112 * The maximum number of cylinders in a group depends upon how much
113 * information can be stored on a single cylinder. The default is to
114 * use 16 cylinders per group. This is effectively tradition - it was
115 * the largest value acceptable under SunOs 4.1
117 #define DESCPG 16 /* desired fs_cpg */
120 * The following two constants set the default block and fragment sizes.
121 * Both constants must be a power of 2 and meet the following constraints:
122 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
123 * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
124 * DESBLKSIZE / DESFRAGSIZE <= 8
126 #define DESBLKSIZE 8192
127 #define DESFRAGSIZE 1024
130 * MINFREE gives the minimum acceptable percentage of file system
131 * blocks which may be free. If the freelist drops below this level
132 * only the superuser may continue to allocate blocks. This may
133 * be set to 0 if no reserve of free blocks is deemed necessary,
134 * however throughput drops by fifty percent if the file system
135 * is run at between 90% and 100% full; thus the default value of
136 * fs_minfree is 10%. With 10% free space, fragmentation is not a
137 * problem, so we choose to optimize for time.
140 #define DEFAULTOPT FS_OPTTIME
143 * ROTDELAY gives the minimum number of milliseconds to initiate
144 * another disk transfer on the same cylinder. It is no longer used
145 * and will always default to 0.
150 * MAXBLKPG determines the maximum number of data blocks which are
151 * placed in a single cylinder group. The default is one indirect
152 * block worth of data blocks.
154 #define MAXBLKPG(bsize) ((bsize) / sizeof (daddr32_t))
157 * Each file system has a number of inodes statically allocated.
158 * We allocate one inode slot per NBPI bytes, expecting this
159 * to be far more than we will ever need.
161 #define NBPI 2048 /* Number Bytes Per Inode */
162 #define MTB_NBPI (MB) /* Number Bytes Per Inode for multi-terabyte */
165 * Disks are assumed to rotate at 60HZ, unless otherwise specified.
170 * Cylinder group related limits.
172 * For each cylinder we keep track of the availability of blocks at different
173 * rotational positions, so that we can lay out the data to be picked
174 * up with minimum rotational latency. NRPOS is the number of rotational
175 * positions which we distinguish. With NRPOS 8 the resolution of our
176 * summary information is 2ms for a typical 3600 rpm drive.
178 #define NRPOS 8 /* number distinct rotational positions */
181 #define dprintf(x) printf x
187 * For the -N option, when calculating the backup superblocks, do not print
188 * them if we are not really sure. We may have to try an alternate method of
189 * arriving at the superblocks. So defer printing till a handful of superblocks
192 #define tprintf(x) if (Nflag && retry) \
193 (void) strncat(tmpbuf, x, strlen(x)); \
195 (void) fprintf(stderr, x);
197 #define ALTSB 32 /* Location of first backup superblock */
200 * range_check "user_supplied" flag values.
204 #define RC_POSITIONAL 2
213 #include <sys/mnttab.h>
223 #include <sys/param.h>
225 #include <sys/types.h>
226 #include <sys/sysmacros.h>
227 #include <sys/vnode.h>
228 #include <sys/fs/ufs_fsdir.h>
229 #include <sys/fs/ufs_inode.h>
230 #include <sys/fs/ufs_fs.h>
231 #include <sys/fs/ufs_log.h>
232 #include <sys/mntent.h>
233 #include <sys/filio.h>
235 #include <sys/int_const.h>
237 #include <sys/efi_partition.h>
238 #include "roll_log.h"
240 #define bcopy(f, t, n) (void) memcpy(t, f, n)
241 #define bzero(s, n) (void) memset(s, 0, n)
242 #define bcmp(s, d, n) memcmp(s, d, n)
244 #define index(s, r) strchr(s, r)
245 #define rindex(s, r) strrchr(s, r)
247 #include <sys/stat.h>
248 #include <sys/statvfs.h>
251 #include <sys/isa_defs.h> /* for ENDIAN defines */
252 #include <sys/vtoc.h>
254 #include <sys/dkio.h>
255 #include <sys/asynch.h>
257 extern offset_t
llseek();
258 extern char *getfullblkname();
259 extern long lrand48();
266 * The size of a cylinder group is calculated by CGSIZE. The maximum size
267 * is limited by the fact that cylinder groups are at most one block.
268 * Its size is derived from the size of the maps maintained in the
269 * cylinder group and the (struct cg) size.
272 /* base cg */ (sizeof (struct cg) + \
273 /* blktot size */ (fs)->fs_cpg * sizeof (long) + \
274 /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
275 /* inode map */ howmany((fs)->fs_ipg, NBBY) + \
276 /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
279 * We limit the size of the inode map to be no more than a
280 * third of the cylinder group space, since we must leave at
281 * least an equal amount of space for the block map.
283 * N.B.: MAXIpG must be a multiple of INOPB(fs).
285 #define MAXIpG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
288 * Same as MAXIpG, but parameterized by the block size (b) and the
289 * cylinder group divisor (d), which is the reciprocal of the fraction of the
290 * cylinder group overhead block that is used for the inode map. So for
291 * example, if d = 5, the macro's computation assumes that 1/5 of the
292 * cylinder group overhead block can be dedicated to the inode map.
294 #define MAXIpG_B(b, d) roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
297 #define MAXINOPB (MAXBSIZE / sizeof (struct dinode))
298 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
299 #define MB (1024*1024)
300 #define BETWEEN(x, l, h) ((x) >= (l) && (x) <= (h))
303 * Used to set the inode generation number. Since both inodes and dinodes
304 * are dealt with, we really need a pointer to an icommon here.
306 #define IRANDOMIZE(icp) (icp)->ic_gen = lrand48();
311 #define ALLOW_PERCENT 0x01 /* allow trailing `%' on number */
312 #define ALLOW_MS1 0x02 /* allow trailing `ms', state 1 */
313 #define ALLOW_MS2 0x04 /* allow trailing `ms', state 2 */
314 #define ALLOW_END_ONLY 0x08 /* must be at end of number & suffixes */
316 #define MAXAIO 1000 /* maximum number of outstanding I/O's we'll manage */
317 #define BLOCK 1 /* block in aiowait */
318 #define NOBLOCK 0 /* don't block in aiowait */
320 #define RELEASE 1 /* free an aio buffer after use */
321 #define SAVE 0 /* don't free the buffer */
323 typedef struct aio_trans
{
324 aio_result_t resultbuf
;
329 struct aio_trans
*next
;
332 typedef struct aio_results
{
343 * Allow up to MAXBUF aio requests that each have a unique buffer.
344 * More aio's might be done, but not using memory through the getbuf()
345 * interface. This can be raised, but you run into the potential of
346 * using more memory than is physically available on the machine,
347 * and if you start swapping, you can forget about performance.
348 * To prevent this, we also limit the total memory used for a given
349 * type of buffer to MAXBUFMEM.
351 * Tests indicate a cylinder group's worth of inodes takes:
353 * NBPI Size of Inode Buffer
357 * initcg() stores all the inodes for a cylinder group in one buffer,
358 * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
361 #define MAXBUFMEM (8 * 1024 * 1024)
364 * header information for buffers managed by getbuf() and freebuf()
366 typedef struct bufhdr
{
373 bufhdr inodebuf
= { NULL
, NULL
};
374 bufhdr cgsumbuf
= { NULL
, NULL
};
376 #define SECTORS_PER_TERABYTE (1LL << 31)
378 * The following constant specifies an upper limit for file system size
379 * that is actually a lot bigger than we expect to support with UFS. (Since
380 * it's specified in sectors, the file system size would be 2**44 * 512,
381 * which is 2**53, which is 8192 Terabytes.) However, it's useful
382 * for checking the basic sanity of a size value that is input on the
385 #define FS_SIZE_UPPER_LIMIT 0x100000000000LL
388 * Forward declarations
390 static char *getbuf(bufhdr
*bufhead
, int size
);
391 static void freebuf(char *buf
);
392 static void freetrans(aio_trans
*transp
);
393 static aio_trans
*get_aiop();
394 static aio_trans
*wait_for_write(int block
);
395 static void initcg(int cylno
);
396 static void fsinit();
397 static int makedir(struct direct
*protodir
, int entries
);
398 static void iput(struct inode
*ip
);
399 static void rdfs(diskaddr_t bno
, int size
, char *bf
);
400 static void wtfs(diskaddr_t bno
, int size
, char *bf
);
401 static void awtfs(diskaddr_t bno
, int size
, char *bf
, int release
);
402 static void wtfs_breakup(diskaddr_t bno
, int size
, char *bf
);
403 static int isblock(struct fs
*fs
, unsigned char *cp
, int h
);
404 static void clrblock(struct fs
*fs
, unsigned char *cp
, int h
);
405 static void setblock(struct fs
*fs
, unsigned char *cp
, int h
);
407 static void dump_fscmd(char *fsys
, int fsi
);
408 static uint64_t number(uint64_t d_value
, char *param
, int flags
);
409 static int match(char *s
);
410 static char checkopt(char *optim
);
411 static char checkmtb(char *mtbarg
);
412 static void range_check(long *varp
, char *name
, long minimum
,
413 long maximum
, long def_val
, int user_supplied
);
414 static void range_check_64(uint64_t *varp
, char *name
, uint64_t minimum
,
415 uint64_t maximum
, uint64_t def_val
, int user_supplied
);
416 static daddr32_t
alloc(int size
, int mode
);
417 static diskaddr_t
get_max_size(int fd
);
418 static long get_max_track_size(int fd
);
419 static void block_sigint(sigset_t
*old_mask
);
420 static void unblock_sigint(sigset_t
*old_mask
);
421 static void recover_from_sigint(int signum
);
422 static int confirm_abort(void);
423 static int getaline(FILE *fp
, char *loc
, int maxlen
);
424 static void flush_writes(void);
425 static long compute_maxcpg(long, long, long, long, long);
426 static int in_64bit_mode(void);
427 static int validate_size(int fd
, diskaddr_t size
);
428 static void dump_sblock(void);
431 * Workaround for mkfs to function properly on disks attached to XMIT 2.X
432 * controller. If the address is not aligned at 8 byte boundary, mkfs on
433 * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
435 #define XMIT_2_X_ALIGN 8
436 #pragma align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
442 #define sblock fsun.fs
443 #define altsblock altfsun.fs
454 * Size of screen in cols in which to fit output
458 struct dinode zino
[MAXBSIZE
/ sizeof (struct dinode
)];
461 * file descriptors used for rdfs(fsi) and wtfs(fso).
462 * Initialized to an illegal file descriptor number.
468 * The BIG parameter is machine dependent. It should be a longlong integer
469 * constant that can be used by the number parser to check the validity
470 * of numeric parameters.
473 #define BIG 0x7fffffffffffffffLL
475 /* Used to indicate to number() that a bogus value should cause us to exit */
476 #define NO_DEFAULT LONG_MIN
479 * INVALIDSBLIMIT is the number of bad backup superblocks that will be
480 * tolerated before we decide to try arriving at a different set of them
481 * using a different logic. This is applicable for non-EFI disks only.
483 #define INVALIDSBLIMIT 10
486 * The *_flag variables are used to indicate that the user specified
487 * the values, rather than that we made them up ourselves. We can
488 * complain about the user giving us bogus values.
492 long sectorsize
= DEV_BSIZE
; /* bytes/sector from param.h */
493 long bbsize
= BBSIZE
; /* boot block size */
494 long sbsize
= SBSIZE
; /* superblock size */
497 diskaddr_t fssize_db
; /* file system size in disk blocks */
498 diskaddr_t fssize_frag
; /* file system size in frags */
499 long cpg
; /* cylinders/cylinder group */
500 int cpg_flag
= RC_DEFAULT
;
501 long rotdelay
= -1; /* rotational delay between blocks */
502 int rotdelay_flag
= RC_DEFAULT
;
503 long maxcontig
; /* max contiguous blocks to allocate */
504 int maxcontig_flag
= RC_DEFAULT
;
505 long nsect
= DFLNSECT
; /* sectors per track */
506 int nsect_flag
= RC_DEFAULT
;
507 long ntrack
= DFLNTRAK
; /* tracks per cylinder group */
508 int ntrack_flag
= RC_DEFAULT
;
509 long bsize
= DESBLKSIZE
; /* filesystem block size */
510 int bsize_flag
= RC_DEFAULT
;
511 long fragsize
= DESFRAGSIZE
; /* filesystem fragment size */
512 int fragsize_flag
= RC_DEFAULT
;
513 long minfree
= MINFREE
; /* fs_minfree */
514 int minfree_flag
= RC_DEFAULT
;
515 long rps
= DEFHZ
; /* revolutions/second of drive */
516 int rps_flag
= RC_DEFAULT
;
517 long nbpi
= NBPI
; /* number of bytes per inode */
518 int nbpi_flag
= RC_DEFAULT
;
519 long nrpos
= NRPOS
; /* number of rotational positions */
520 int nrpos_flag
= RC_DEFAULT
;
521 long apc
= 0; /* alternate sectors per cylinder */
522 int apc_flag
= RC_DEFAULT
;
523 char opt
= 't'; /* optimization style, `t' or `s' */
524 char mtb
= 'n'; /* multi-terabyte format, 'y' or 'n' */
525 #define DEFAULT_SECT_TRAK_CPG (nsect_flag == RC_DEFAULT && \
526 ntrack_flag == RC_DEFAULT && \
527 cpg_flag == RC_DEFAULT)
529 long debug
= 0; /* enable debugging output */
531 int spc_flag
= 0; /* alternate sectors specified or */
535 int Nflag
; /* do not write to disk */
536 int mflag
; /* return the command line used to create this FS */
537 int rflag
; /* report the superblock in an easily-parsed form */
538 int Rflag
; /* dump the superblock in binary */
547 int islog
; /* true if ufs logging is enabled */
548 int islogok
; /* true if ufs log state is good */
549 int waslog
; /* true when ufs logging disabled during grow */
552 * growfs defines, globals, and forward references
554 #define NOTENOUGHSPACE 33
556 #define GROW_WITH_DEFAULT_TRAK (grow && ntrack_flag == RC_DEFAULT)
558 static int Pflag
; /* probe to which size the fs can be grown */
561 diskaddr_t grow_fssize
;
564 diskaddr_t grow_fs_csaddr
;
567 struct csum
*grow_fscs
;
568 diskaddr_t grow_sifrag
;
571 diskaddr_t testfrags
;
576 void randomgeneration(void);
577 void checksummarysize(void);
578 int checksblock(struct fs
, int);
579 void growinit(char *);
580 void checkdev(char *, char *);
581 void checkmount(struct mnttab
*, char *);
582 struct dinode
*gdinode(ino_t
);
583 int csfraginrange(daddr32_t
);
584 struct csfrag
*findcsfrag(daddr32_t
, struct csfrag
**);
585 void checkindirect(ino_t
, daddr32_t
*, daddr32_t
, int);
586 void addcsfrag(ino_t
, daddr32_t
, struct csfrag
**);
587 void delcsfrag(daddr32_t
, struct csfrag
**);
588 void checkdirect(ino_t
, daddr32_t
*, daddr32_t
*, int);
589 void findcsfragino(void);
590 void fixindirect(daddr32_t
, int);
591 void fixdirect(caddr_t
, daddr32_t
, daddr32_t
*, int);
592 void fixcsfragino(void);
593 void extendsummaryinfo(void);
594 int notenoughspace(void);
595 void unalloccsfragino(void);
596 void unalloccsfragfree(void);
597 void findcsfragfree(void);
598 void copycsfragino(void);
602 void allocfrags(long, daddr32_t
*, long *);
603 void alloccsfragino(void);
604 void alloccsfragfree(void);
605 void freefrags(daddr32_t
, long, long);
606 int findfreerange(long *, long *);
607 void resetallocinfo(void);
613 static int64_t checkfragallocated(daddr32_t
);
614 static struct csum
*read_summaryinfo(struct fs
*);
615 static diskaddr_t
probe_summaryinfo();
618 main(int argc
, char *argv
[])
620 long i
, mincpc
, mincpg
, ibpcl
;
621 long cylno
, rpos
, blk
, j
, warn
= 0;
622 long mincpgcnt
, maxcpg
;
623 uint64_t used
, bpcg
, inospercg
;
624 long mapcramped
, inodecramped
;
625 long postblsize
, rotblsize
, totalsbsize
;
631 struct dk_minfo dkminfo
;
632 char pbuf
[sizeof (uint64_t) * 3 + 1];
637 diskaddr_t max_fssize
;
638 long tmpmaxcontig
= -1;
639 struct sigaction sigact
;
643 int use_efi_dflts
= 0, retry
= 0, isremovable
= 0, ishotpluggable
= 0;
644 int invalid_sb_cnt
, ret
, skip_this_sb
, cg_too_small
;
645 int geom_nsect
, geom_ntrack
, geom_cpg
;
647 (void) setlocale(LC_ALL
, "");
649 #if !defined(TEXT_DOMAIN)
650 #define TEXT_DOMAIN "SYS_TEST"
652 (void) textdomain(TEXT_DOMAIN
);
654 while ((c
= getopt(argc
, argv
, "F:bmo:VPGM:T:t:")) != EOF
) {
659 if (strcmp(string
, "ufs") != 0)
663 case 'm': /* return command line used to create this FS */
669 * ufs specific options.
672 while (*string
!= '\0') {
673 if (match("nsect=")) {
674 nsect
= number(DFLNSECT
, "nsect", 0);
675 nsect_flag
= RC_KEYWORD
;
676 } else if (match("ntrack=")) {
677 ntrack
= number(DFLNTRAK
, "ntrack", 0);
678 ntrack_flag
= RC_KEYWORD
;
679 } else if (match("bsize=")) {
680 bsize
= number(DESBLKSIZE
, "bsize", 0);
681 bsize_flag
= RC_KEYWORD
;
682 } else if (match("fragsize=")) {
683 fragsize
= number(DESFRAGSIZE
,
685 fragsize_flag
= RC_KEYWORD
;
686 } else if (match("cgsize=")) {
687 cpg
= number(DESCPG
, "cgsize", 0);
688 cpg_flag
= RC_KEYWORD
;
689 } else if (match("free=")) {
690 minfree
= number(MINFREE
, "free",
692 minfree_flag
= RC_KEYWORD
;
693 } else if (match("maxcontig=")) {
695 number(-1, "maxcontig", 0);
696 maxcontig_flag
= RC_KEYWORD
;
697 } else if (match("nrpos=")) {
698 nrpos
= number(NRPOS
, "nrpos", 0);
699 nrpos_flag
= RC_KEYWORD
;
700 } else if (match("rps=")) {
701 rps
= number(DEFHZ
, "rps", 0);
702 rps_flag
= RC_KEYWORD
;
703 } else if (match("nbpi=")) {
704 nbpi
= number(NBPI
, "nbpi", 0);
705 nbpi_flag
= RC_KEYWORD
;
706 } else if (match("opt=")) {
707 opt
= checkopt(string
);
708 } else if (match("mtb=")) {
709 mtb
= checkmtb(string
);
710 } else if (match("apc=")) {
711 apc
= number(0, "apc", 0);
712 apc_flag
= RC_KEYWORD
;
713 } else if (match("gap=")) {
714 (void) number(0, "gap", ALLOW_MS1
);
716 rotdelay_flag
= RC_DEFAULT
;
717 } else if (match("debug=")) {
718 debug
= number(0, "debug", 0);
719 } else if (match("N")) {
721 } else if (match("calcsb")) {
724 } else if (match("calcbinsb")) {
728 } else if (*string
== '\0') {
731 (void) fprintf(stderr
, gettext(
732 "illegal option: %s\n"), string
);
736 if (*string
== ',') string
++;
737 if (*string
== ' ') string
++;
746 (void) fprintf(stdout
, gettext("mkfs -F ufs "));
747 for (opt_count
= 1; opt_count
< argc
;
749 opt_text
= argv
[opt_count
];
751 (void) fprintf(stdout
, " %s ",
754 (void) fprintf(stdout
, "\n");
758 case 'b': /* do nothing for this */
761 case 'M': /* grow the mounted file system */
765 case 'G': /* grow the file system */
768 case 'P': /* probe the file system growing size */
770 grow
= 1; /* probe mode implies fs growing */
772 case 'T': /* For testing */
779 testfrags
= number(NO_DEFAULT
, "testfrags", 0);
789 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
790 * that can be reproduced by setting the time to 0 and seeding
791 * the random number generator to a constant.
793 mkfstime
= 0; /* reproducible results */
795 (void) time(&mkfstime
);
798 if (optind
>= (argc
- 1)) {
799 if (optind
> (argc
- 1)) {
800 (void) fprintf(stderr
,
801 gettext("special not specified\n"));
803 } else if (mflag
== 0) {
804 (void) fprintf(stderr
,
805 gettext("size not specified\n"));
810 argv
= &argv
[optind
];
813 fsi
= open64(fsys
, O_RDONLY
);
815 (void) fprintf(stderr
, gettext("%s: cannot open\n"), fsys
);
820 dump_fscmd(fsys
, fsi
);
825 * The task of setting all of the configuration parameters for a
826 * UFS file system is basically a matter of solving n equations
827 * in m variables. Typically, m is greater than n, so there is
828 * usually more than one valid solution. Since this is usually
829 * an under-constrained problem, it's not always obvious what the
830 * "best" configuration is.
832 * In general, the approach is to
833 * 1. Determine the values for the file system parameters
834 * that are externally contrained and therefore not adjustable
835 * by mkfs (such as the device's size and maxtransfer size).
836 * 2. Acquire the user's requested setting for all configuration
837 * values that can be set on the command line.
838 * 3. Determine the final value of all configuration values, by
839 * the following approach:
840 * - set the file system block size (fs_bsize). Although
841 * this could be regarded as an adjustable parameter, in
842 * fact, it's pretty much a constant. At this time, it's
843 * generally set to 8k (with older hardware, it can
844 * sometimes make sense to set it to 4k, but those
845 * situations are pretty rare now).
846 * - re-adjust the maximum file system size based on the
847 * value of the file system block size. Since the
848 * frag size can't be any larger than a file system
849 * block, and the number of frags in the file system
850 * has to fit into 31 bits, the file system block size
851 * affects the maximum file system size.
852 * - now that the real maximum file system is known, set the
853 * actual size of the file system to be created to
854 * MIN(requested size, maximum file system size).
855 * - now validate, and if necessary, adjust the following
867 * - calculate maxcpg (the maximum value of the cylinders-per-
868 * cylinder-group configuration parameters). There are two
869 * algorithms for calculating maxcpg: an old one, which is
870 * used for file systems of less than 1 terabyte, and a
871 * new one, implemented in the function compute_maxcpg(),
872 * which is used for file systems of greater than 1 TB.
873 * The difference between them is that compute_maxcpg()
874 * really tries to maximize the cpg value. The old
875 * algorithm fails to take advantage of smaller frags and
876 * lower inode density when determining the maximum cpg,
877 * and thus comes up with much lower numbers in some
878 * configurations. At some point, we might use the
879 * new algorithm for determining maxcpg for all file
880 * systems, but at this time, the changes implemented for
881 * multi-terabyte UFS are NOT being automatically applied
882 * to UFS file systems of less than a terabyte (in the
883 * interest of not changing existing UFS policy too much
884 * until the ramifications of the changes are well-understood
885 * and have been evaluated for their effects on performance.)
886 * - check the current values of the configuration parameters
887 * against the various constraints imposed by UFS. These
889 * * There must be at least one inode in each
891 * * The cylinder group overhead block, which
892 * contains the inode and frag bigmaps, must fit
893 * within one file system block.
894 * * The space required for inode maps should
895 * occupy no more than a third of the cylinder
896 * group overhead block.
897 * * The rotational position tables have to fit
898 * within the available space in the super block.
899 * Adjust the configuration values that can be adjusted
900 * so that these constraints are satisfied. The
901 * configuration values that are adjustable are:
903 * * cylinders per group
904 * * inode density (can be increased)
905 * * number of rotational positions (the rotational
906 * position tables are eliminated altogether if
907 * there isn't enough room for them.)
908 * 4. Set the values for all the dependent configuration
909 * values (those that aren't settable on the command
910 * line and which are completely dependent on the
911 * adjustable parameters). This include cpc (cycles
912 * per cylinder, spc (sectors-per-cylinder), and many others.
916 * Figure out the partition size and initialize the label_type.
918 max_fssize
= get_max_size(fsi
);
921 * Get and check positional arguments, if any.
928 mtb
= checkmtb(argv
[15]);
932 tmpmaxcontig
= number(-1, "maxcontig", 0);
933 maxcontig_flag
= RC_POSITIONAL
;
937 nrpos
= number(NRPOS
, "nrpos", 0);
938 nrpos_flag
= RC_POSITIONAL
;
943 rotdelay_flag
= RC_DEFAULT
;
947 apc
= number(0, "apc", 0);
948 apc_flag
= RC_POSITIONAL
;
951 opt
= checkopt(argv
[10]);
955 nbpi
= number(NBPI
, "nbpi", 0);
956 nbpi_flag
= RC_POSITIONAL
;
960 rps
= number(DEFHZ
, "rps", 0);
961 rps_flag
= RC_POSITIONAL
;
965 minfree
= number(MINFREE
, "free", ALLOW_PERCENT
);
966 minfree_flag
= RC_POSITIONAL
;
970 cpg
= number(DESCPG
, "cgsize", 0);
971 cpg_flag
= RC_POSITIONAL
;
975 fragsize
= number(DESFRAGSIZE
, "fragsize", 0);
976 fragsize_flag
= RC_POSITIONAL
;
980 bsize
= number(DESBLKSIZE
, "bsize", 0);
981 bsize_flag
= RC_POSITIONAL
;
985 ntrack
= number(DFLNTRAK
, "ntrack", 0);
986 ntrack_flag
= RC_POSITIONAL
;
990 nsect
= number(DFLNSECT
, "nsect", 0);
991 nsect_flag
= RC_POSITIONAL
;
995 fssize_db
= number(max_fssize
, "size", 0);
999 * Initialize the parameters in the same way as newfs so that
1000 * newfs and mkfs would result in the same file system layout
1001 * for EFI labelled disks. Do this only in the absence of user
1002 * specified values for these parameters.
1004 if (label_type
== LABEL_TYPE_EFI
) {
1005 if (apc_flag
== RC_DEFAULT
) apc
= 0;
1006 if (nrpos_flag
== RC_DEFAULT
) nrpos
= 1;
1007 if (ntrack_flag
== RC_DEFAULT
) ntrack
= DEF_TRACKS_EFI
;
1008 if (rps_flag
== RC_DEFAULT
) rps
= DEFHZ
;
1009 if (nsect_flag
== RC_DEFAULT
) nsect
= DEF_SECTORS_EFI
;
1012 if ((maxcontig_flag
== RC_DEFAULT
) || (tmpmaxcontig
== -1) ||
1013 (maxcontig
== -1)) {
1014 long maxtrax
= get_max_track_size(fsi
);
1015 maxcontig
= maxtrax
/ bsize
;
1018 maxcontig
= tmpmaxcontig
;
1020 dprintf(("DeBuG maxcontig : %ld\n", maxcontig
));
1022 if (rotdelay
== -1) { /* default by newfs and mkfs */
1023 rotdelay
= ROTDELAY
;
1026 if (cpg_flag
== RC_DEFAULT
) { /* If not explicity set, use default */
1029 dprintf(("DeBuG cpg : %ld\n", cpg
));
1032 * Now that we have the semi-sane args, either positional, via -o,
1033 * or by defaulting, handle inter-dependencies and range checks.
1037 * Settle the file system block size first, since it's a fixed
1038 * parameter once set and so many other parameters, including
1039 * max_fssize, depend on it.
1041 range_check(&bsize
, "bsize", MINBSIZE
, MAXBSIZE
, DESBLKSIZE
,
1044 if (!POWEROF2(bsize
)) {
1045 (void) fprintf(stderr
,
1046 gettext("block size must be a power of 2, not %ld\n"),
1049 (void) fprintf(stderr
,
1050 gettext("mkfs: bsize reset to default %ld\n"),
1054 if (fssize_db
> max_fssize
&& validate_size(fsi
, fssize_db
)) {
1055 (void) fprintf(stderr
, gettext(
1056 "Warning: the requested size of this file system\n"
1057 "(%lld sectors) is greater than the size of the\n"
1058 "device reported by the driver (%lld sectors).\n"
1059 "However, a read of the device at the requested size\n"
1060 "does succeed, so the requested size will be used.\n"),
1061 fssize_db
, max_fssize
);
1062 max_fssize
= fssize_db
;
1065 * Since the maximum allocatable unit (the frag) must be less than
1066 * or equal to bsize, and the number of frags must be less than or
1067 * equal to INT_MAX, the total size of the file system (in
1068 * bytes) must be less than or equal to bsize * INT_MAX.
1071 if (max_fssize
> ((diskaddr_t
)bsize
/DEV_BSIZE
) * INT_MAX
)
1072 max_fssize
= ((diskaddr_t
)bsize
/DEV_BSIZE
) * INT_MAX
;
1074 range_check_64(&fssize_db
, "size", 1024LL, max_fssize
, max_fssize
, 1);
1076 if (fssize_db
>= SECTORS_PER_TERABYTE
) {
1078 if (!in_64bit_mode()) {
1079 (void) fprintf(stderr
, gettext(
1080 "mkfs: Warning: Creating a file system greater than 1 terabyte on a\n"
1081 " system running a 32-bit kernel. This file system will not be\n"
1082 " accessible until the system is rebooted with a 64-bit kernel.\n"));
1085 dprintf(("DeBuG mtb : %c\n", mtb
));
1088 * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M)
1089 * commands had problems in correctly handling the "native" geometries
1090 * for various storage devices.
1092 * To handle the new age disks, mkfs_ufs(1M) will use the EFI style
1093 * for non-EFI disks that are larger than the CHS addressing limit
1094 * ( > 8GB approx ) and ignore the disk geometry information for
1095 * these drives. This is what is currently done for multi-terrabyte
1096 * filesystems on EFI disks.
1098 * However if the user asked for a specific layout by supplying values
1099 * for even one of the three parameters (nsect, ntrack, cpg), honour
1100 * the user supplied parameters.
1102 * Choosing EFI style or native geometry style can make a lot of
1103 * difference, because the size of a cylinder group is dependent on
1104 * this choice. This in turn means that the position of alternate
1105 * superblocks varies depending on the style chosen. It is not
1106 * necessary that all disks of size > CHSLIMIT have EFI style layout.
1107 * There can be disks which are > CHSLIMIT size, but have native
1108 * geometry style layout, thereby warranting the need for alternate
1109 * logic in superblock detection.
1111 if (mtb
!= 'y' && (ntrack
== -1 || GROW_WITH_DEFAULT_TRAK
||
1112 DEFAULT_SECT_TRAK_CPG
)) {
1114 * "-1" indicates that we were called from newfs and ntracks
1115 * was not specified in newfs command line. Calculate nsect
1116 * and ntrack in the same manner as newfs.
1118 * This is required because, the defaults for nsect and ntrack
1119 * is hardcoded in mkfs, whereas to generate the alternate
1120 * superblock locations for the -N option, there is a need for
1121 * the geometry based values that newfs would have arrived at.
1122 * Newfs would have arrived at these values as below.
1124 if (label_type
== LABEL_TYPE_EFI
||
1125 label_type
== LABEL_TYPE_OTHER
) {
1128 } else if (ioctl(fsi
, DKIOCGGEOM
, &dkg
)) {
1129 dprintf(("%s: Unable to read Disk geometry", fsys
));
1130 perror(gettext("Unable to read Disk geometry"));
1133 nsect
= dkg
.dkg_nsect
;
1134 ntrack
= dkg
.dkg_nhead
;
1135 #ifdef i386 /* Bug 1170182 */
1136 if (ntrack
> 32 && (ntrack
% 16) != 0) {
1137 ntrack
-= (ntrack
% 16);
1140 if (ioctl(fsi
, DKIOCREMOVABLE
, &isremovable
)) {
1141 dprintf(("DeBuG Unable to determine if %s is"
1142 " Removable Media. Proceeding with system"
1143 " determined parameters.\n", fsys
));
1146 if (ioctl(fsi
, DKIOCHOTPLUGGABLE
, &ishotpluggable
)) {
1147 dprintf(("DeBuG Unable to determine if %s is"
1148 " Hotpluggable Media. Proceeding with "
1149 "system determined parameters.\n", fsys
));
1152 if ((((diskaddr_t
)dkg
.dkg_ncyl
* dkg
.dkg_nhead
*
1153 dkg
.dkg_nsect
) > CHSLIMIT
) || isremovable
||
1160 dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT
,
1161 (diskaddr_t
)dkg
.dkg_ncyl
* dkg
.dkg_nhead
* dkg
.dkg_nsect
));
1162 dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d "
1163 "use_efi_dflts = %d\n", label_type
, isremovable
, ishotpluggable
,
1167 * For the newfs -N case, even if the disksize is > CHSLIMIT, do not
1168 * blindly follow EFI style. If the fs_version indicates a geometry
1169 * based layout, try that one first. If it fails we can always try the
1172 * If we were called from growfs, we will have a problem if we mix
1173 * and match the filesystem creation and growth styles. For example,
1174 * if we create using EFI style, we have to also grow using EFI
1175 * style. So follow the style indicated by the fs_version.
1177 * Read and verify the primary superblock. If it looks sane, use the
1178 * fs_version from the superblock. If the primary superblock does
1179 * not look good, read and verify the first alternate superblock at
1180 * ALTSB. Use the fs_version to decide whether to use the
1181 * EFI style logic or the old geometry based logic to calculate
1182 * the alternate superblock locations.
1184 if ((Nflag
&& use_efi_dflts
) || (grow
)) {
1185 if (grow
&& ntrack_flag
!= RC_DEFAULT
)
1186 goto start_fs_creation
;
1187 rdfs((diskaddr_t
)(SBOFF
/ sectorsize
), (int)sbsize
,
1188 (char *)&altsblock
);
1189 ret
= checksblock(altsblock
, 1);
1192 if (altsblock
.fs_magic
== MTB_UFS_MAGIC
) {
1194 goto start_fs_creation
;
1196 use_efi_dflts
= (altsblock
.fs_version
==
1197 UFS_EFISTYLE4NONEFI_VERSION_2
) ? 1 : 0;
1200 * The primary superblock didn't help in determining
1201 * the fs_version. Try the first alternate superblock.
1203 dprintf(("DeBuG checksblock() failed - error : %d"
1204 " for sb : %d\n", ret
, SBOFF
/sectorsize
));
1205 rdfs((diskaddr_t
)ALTSB
, (int)sbsize
,
1206 (char *)&altsblock
);
1207 ret
= checksblock(altsblock
, 1);
1210 if (altsblock
.fs_magic
== MTB_UFS_MAGIC
) {
1212 goto start_fs_creation
;
1214 use_efi_dflts
= (altsblock
.fs_version
==
1215 UFS_EFISTYLE4NONEFI_VERSION_2
) ? 1 : 0;
1217 dprintf(("DeBuG checksblock() returned : %d"
1218 " for sb : %d\n", ret
, ALTSB
));
1223 geom_ntrack
= ntrack
;
1225 dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n",
1226 geom_nsect
, geom_ntrack
, geom_cpg
));
1229 retry_alternate_logic
:
1232 if (use_efi_dflts
) {
1233 nsect
= DEF_SECTORS_EFI
;
1234 ntrack
= DEF_TRACKS_EFI
;
1236 dprintf(("\nDeBuG Using EFI defaults\n"));
1239 ntrack
= geom_ntrack
;
1241 dprintf(("\nDeBuG Using Geometry\n"));
1243 * 32K based on max block size of 64K, and rotational layout
1244 * test of nsect <= (256 * sectors/block). Current block size
1245 * limit is not 64K, but it's growing soon.
1247 range_check(&nsect
, "nsect", 1, 32768, DFLNSECT
, nsect_flag
);
1249 * ntrack is the number of tracks per cylinder.
1250 * The ntrack value must be between 1 and the total number of
1251 * sectors in the file system.
1253 range_check(&ntrack
, "ntrack", 1,
1254 fssize_db
> INT_MAX
? INT_MAX
: (uint32_t)fssize_db
,
1255 DFLNTRAK
, ntrack_flag
);
1258 range_check(&apc
, "apc", 0, nsect
- 1, 0, apc_flag
);
1263 range_check(&fragsize
, "fragsize", sectorsize
, bsize
,
1264 MAX(bsize
/ MAXFRAG
, MIN(DESFRAGSIZE
, bsize
)), fragsize_flag
);
1266 if ((bsize
/ MAXFRAG
) > fragsize
) {
1267 (void) fprintf(stderr
, gettext(
1268 "fragment size %ld is too small, minimum with block size %ld is %ld\n"),
1269 fragsize
, bsize
, bsize
/ MAXFRAG
);
1270 (void) fprintf(stderr
,
1271 gettext("mkfs: fragsize reset to minimum %ld\n"),
1273 fragsize
= bsize
/ MAXFRAG
;
1276 if (!POWEROF2(fragsize
)) {
1277 (void) fprintf(stderr
,
1278 gettext("fragment size must be a power of 2, not %ld\n"),
1280 fragsize
= MAX(bsize
/ MAXFRAG
, MIN(DESFRAGSIZE
, bsize
));
1281 (void) fprintf(stderr
,
1282 gettext("mkfs: fragsize reset to %ld\n"),
1286 /* At this point, bsize must be >= fragsize, so no need to check it */
1288 if (bsize
< PAGESIZE
) {
1289 (void) fprintf(stderr
, gettext(
1290 "WARNING: filesystem block size (%ld) is smaller than "
1291 "memory page size (%ld).\nResulting filesystem can not be "
1292 "mounted on this system.\n\n"),
1293 bsize
, (long)PAGESIZE
);
1296 range_check(&rps
, "rps", 1, 1000, DEFHZ
, rps_flag
);
1297 range_check(&minfree
, "free", 0, 99, MINFREE
, minfree_flag
);
1298 range_check(&nrpos
, "nrpos", 1, nsect
, MIN(nsect
, NRPOS
), nrpos_flag
);
1301 * nbpi is variable, but 2MB seems a reasonable upper limit,
1302 * as 4MB tends to cause problems (using otherwise-default
1303 * parameters). The true limit is where we end up with one
1304 * inode per cylinder group. If this file system is being
1305 * configured for multi-terabyte access, nbpi must be at least 1MB.
1307 if (mtb
== 'y' && nbpi
< MTB_NBPI
) {
1308 if (nbpi_flag
!= RC_DEFAULT
)
1309 (void) fprintf(stderr
, gettext("mkfs: bad value for "
1310 "nbpi: must be at least 1048576 for multi-terabyte,"
1311 " nbpi reset to default 1048576\n"));
1316 range_check(&nbpi
, "nbpi", MTB_NBPI
, 2 * MB
, MTB_NBPI
,
1319 range_check(&nbpi
, "nbpi", DEV_BSIZE
, 2 * MB
, NBPI
, nbpi_flag
);
1322 * maxcpg is another variably-limited parameter. Calculate
1323 * the limit based on what we've got for its dependent
1324 * variables. Effectively, it's how much space is left in the
1325 * superblock after all the other bits are accounted for. We
1326 * only fill in sblock fields so we can use MAXIpG.
1328 * If the calculation of maxcpg below (for the mtb == 'n'
1329 * case) is changed, update newfs as well.
1331 * For old-style, non-MTB format file systems, use the old
1332 * algorithm for calculating the maximum cylinder group size,
1333 * even though it limits the cylinder group more than necessary.
1334 * Since layout can affect performance, we don't want to change
1335 * the default layout for non-MTB file systems at this time.
1336 * However, for MTB file systems, use the new maxcpg calculation,
1337 * which really maxes out the cylinder group size.
1340 sblock
.fs_bsize
= bsize
;
1341 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof (struct dinode
);
1344 maxcpg
= (bsize
- sizeof (struct cg
) -
1345 howmany(MAXIpG(&sblock
), NBBY
)) /
1346 (sizeof (long) + nrpos
* sizeof (short) +
1347 nsect
/ (MAXFRAG
* NBBY
));
1349 maxcpg
= compute_maxcpg(bsize
, fragsize
, nbpi
, nrpos
,
1353 dprintf(("DeBuG cpg : %ld\n", cpg
));
1355 * Increase the cpg to maxcpg if either newfs was invoked
1356 * with -T option or if mkfs wants to create a mtb file system
1357 * and if the user has not specified the cpg.
1359 if (cpg
== -1 || (mtb
== 'y' && cpg_flag
== RC_DEFAULT
))
1361 dprintf(("DeBuG cpg : %ld\n", cpg
));
1364 * mincpg is variable in complex ways, so we really can't
1365 * do a sane lower-end limit check at this point.
1367 range_check(&cpg
, "cgsize", 1, maxcpg
, MIN(maxcpg
, DESCPG
), cpg_flag
);
1370 * get the controller info
1377 * Do not grow the file system, but print on stdout the maximum
1378 * size in sectors to which the file system can be increased.
1379 * The calculated size is limited by fssize_db.
1380 * Note that we don't lock the filesystem and therefore under rare
1381 * conditions (the filesystem is mounted, the free block count is
1382 * almost zero, and the superuser is still changing it) the calculated
1383 * size can be imprecise.
1386 (void) printf("%llu\n", probe_summaryinfo());
1391 * If we're growing an existing filesystem, then we're about
1392 * to start doing things that can require recovery efforts if
1393 * we get interrupted, so make sure we get a chance to do so.
1396 sigact
.sa_handler
= recover_from_sigint
;
1397 sigemptyset(&sigact
.sa_mask
);
1398 sigact
.sa_flags
= SA_RESTART
;
1400 if (sigaction(SIGINT
, &sigact
, NULL
) < 0) {
1401 perror(gettext("Could not register SIGINT handler"));
1408 * Check if MNTTAB is trustable
1410 if (statvfs64(MNTTAB
, &fs
) < 0) {
1411 (void) fprintf(stderr
, gettext("can't statvfs %s\n"),
1416 if (strcmp(MNTTYPE_MNTFS
, fs
.f_basetype
) != 0) {
1417 (void) fprintf(stderr
, gettext(
1418 "%s file system type is not %s, can't mkfs\n"),
1419 MNTTAB
, MNTTYPE_MNTFS
);
1423 special
= getfullblkname(fsys
);
1424 checkdev(fsys
, special
);
1427 * If we found the block device name,
1428 * then check the mount table.
1429 * if mounted, and growing write lock the file system
1432 if ((special
!= NULL
) && (*special
!= '\0')) {
1433 if ((mnttab
= fopen(MNTTAB
, "r")) == NULL
) {
1434 (void) fprintf(stderr
, gettext(
1435 "can't open %s\n"), MNTTAB
);
1438 while ((getmntent(mnttab
, &mntp
)) == 0) {
1440 checkmount(&mntp
, special
);
1443 if (strcmp(special
, mntp
.mnt_special
) == 0) {
1444 (void) fprintf(stderr
, gettext(
1445 "%s is mounted, can't mkfs\n"),
1450 (void) fclose(mnttab
);
1453 if (directory
&& (ismounted
== 0)) {
1454 (void) fprintf(stderr
, gettext("%s is not mounted\n"),
1459 fso
= (grow
) ? open64(fsys
, O_WRONLY
) : creat64(fsys
, 0666);
1462 (void) fprintf(stderr
,
1463 gettext("%s: cannot create: %s\n"),
1464 fsys
, strerror(saverr
));
1471 * For the -N case, a file descriptor is needed for the llseek()
1472 * in wtfs(). See the comment in wtfs() for more information.
1474 * Get a file descriptor that's read-only so that this code
1475 * doesn't accidentally write to the file.
1477 fso
= open64(fsys
, O_RDONLY
);
1480 (void) fprintf(stderr
, gettext("%s: cannot open: %s\n"),
1481 fsys
, strerror(saverr
));
1487 * Check the media sector size
1489 if (ioctl(fso
, DKIOCGMEDIAINFO
, &dkminfo
) != -1) {
1490 if (dkminfo
.dki_lbsize
!= 0 &&
1491 POWEROF2(dkminfo
.dki_lbsize
/ DEV_BSIZE
) &&
1492 dkminfo
.dki_lbsize
!= DEV_BSIZE
) {
1494 gettext("The device sector size %u is not "
1495 "supported by ufs!\n"), dkminfo
.dki_lbsize
);
1502 * seed random # generator (for ic_generation)
1505 srand48(12962); /* reproducible results */
1507 srand48((long)(time(NULL
) + getpid()));
1516 * Validate the given file system size.
1517 * Verify that its last block can actually be accessed.
1519 * Note: it's ok to use sblock as a buffer because it is immediately
1520 * overwritten by the rdfs() of the superblock in the next line.
1522 * ToDo: Because the size checking is done in rdfs()/wtfs(), the
1523 * error message for specifying an illegal size is very unfriendly.
1524 * In the future, one could replace the rdfs()/wtfs() calls
1525 * below with in-line calls to read() or write(). This allows better
1526 * error messages to be put in place.
1528 rdfs(fssize_db
- 1, (int)sectorsize
, (char *)&sblock
);
1531 * make the fs unmountable
1533 rdfs((diskaddr_t
)(SBOFF
/ sectorsize
), (int)sbsize
, (char *)&sblock
);
1534 sblock
.fs_magic
= -1;
1535 sblock
.fs_clean
= FSBAD
;
1536 sblock
.fs_state
= FSOKAY
- sblock
.fs_time
;
1537 wtfs((diskaddr_t
)(SBOFF
/ sectorsize
), (int)sbsize
, (char *)&sblock
);
1538 bzero(&sblock
, (size_t)sbsize
);
1540 sblock
.fs_nsect
= nsect
;
1541 sblock
.fs_ntrak
= ntrack
;
1544 * Validate specified/determined spc
1545 * and calculate minimum cylinders per group.
1549 * sectors/cyl = tracks/cyl * sectors/track
1551 sblock
.fs_spc
= sblock
.fs_ntrak
* sblock
.fs_nsect
;
1555 sblock
.fs_spc
-= apc
;
1558 * Have to test for this separately from apc_flag, due to
1559 * the growfs case....
1561 if (sblock
.fs_spc
!= sblock
.fs_ntrak
* sblock
.fs_nsect
) {
1567 sblock
.fs_nrpos
= nrpos
;
1568 sblock
.fs_bsize
= bsize
;
1569 sblock
.fs_fsize
= fragsize
;
1570 sblock
.fs_minfree
= minfree
;
1573 if (nbpi
< sblock
.fs_fsize
) {
1574 (void) fprintf(stderr
, gettext(
1575 "warning: wasteful data byte allocation / inode (nbpi):\n"));
1576 (void) fprintf(stderr
, gettext(
1577 "%ld smaller than allocatable fragment size of %d\n"),
1578 nbpi
, sblock
.fs_fsize
);
1584 sblock
.fs_optim
= FS_OPTSPACE
;
1586 sblock
.fs_optim
= FS_OPTTIME
;
1588 sblock
.fs_bmask
= ~(sblock
.fs_bsize
- 1);
1589 sblock
.fs_fmask
= ~(sblock
.fs_fsize
- 1);
1591 * Planning now for future expansion.
1593 #if defined(_BIG_ENDIAN)
1594 sblock
.fs_qbmask
.val
[0] = 0;
1595 sblock
.fs_qbmask
.val
[1] = ~sblock
.fs_bmask
;
1596 sblock
.fs_qfmask
.val
[0] = 0;
1597 sblock
.fs_qfmask
.val
[1] = ~sblock
.fs_fmask
;
1599 #if defined(_LITTLE_ENDIAN)
1600 sblock
.fs_qbmask
.val
[0] = ~sblock
.fs_bmask
;
1601 sblock
.fs_qbmask
.val
[1] = 0;
1602 sblock
.fs_qfmask
.val
[0] = ~sblock
.fs_fmask
;
1603 sblock
.fs_qfmask
.val
[1] = 0;
1605 for (sblock
.fs_bshift
= 0, i
= sblock
.fs_bsize
; i
> 1; i
>>= 1)
1607 for (sblock
.fs_fshift
= 0, i
= sblock
.fs_fsize
; i
> 1; i
>>= 1)
1609 sblock
.fs_frag
= numfrags(&sblock
, sblock
.fs_bsize
);
1610 for (sblock
.fs_fragshift
= 0, i
= sblock
.fs_frag
; i
> 1; i
>>= 1)
1611 sblock
.fs_fragshift
++;
1612 if (sblock
.fs_frag
> MAXFRAG
) {
1613 (void) fprintf(stderr
, gettext(
1614 "fragment size %d is too small, minimum with block size %d is %d\n"),
1615 sblock
.fs_fsize
, sblock
.fs_bsize
,
1616 sblock
.fs_bsize
/ MAXFRAG
);
1619 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof (daddr32_t
);
1620 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof (struct dinode
);
1621 sblock
.fs_nspf
= sblock
.fs_fsize
/ sectorsize
;
1622 for (sblock
.fs_fsbtodb
= 0, i
= NSPF(&sblock
); i
> 1; i
>>= 1)
1623 sblock
.fs_fsbtodb
++;
1626 * Compute the super-block, cylinder group, and inode blocks.
1627 * Note that these "blkno" are really fragment addresses.
1628 * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16,
1629 * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so
1630 * important: only 1 FS block is allocated for the cg struct (fragment
1631 * numbers 24 through 31).
1634 roundup(howmany(bbsize
+ sbsize
, sblock
.fs_fsize
), sblock
.fs_frag
);
1635 sblock
.fs_cblkno
= (daddr32_t
)(sblock
.fs_sblkno
+
1636 roundup(howmany(sbsize
, sblock
.fs_fsize
), sblock
.fs_frag
));
1637 sblock
.fs_iblkno
= sblock
.fs_cblkno
+ sblock
.fs_frag
;
1639 sblock
.fs_cgoffset
= roundup(
1640 howmany(sblock
.fs_nsect
, NSPF(&sblock
)), sblock
.fs_frag
);
1641 for (sblock
.fs_cgmask
= -1, i
= sblock
.fs_ntrak
; i
> 1; i
>>= 1)
1642 sblock
.fs_cgmask
<<= 1;
1643 if (!POWEROF2(sblock
.fs_ntrak
))
1644 sblock
.fs_cgmask
<<= 1;
1646 * Validate specified/determined spc
1647 * and calculate minimum cylinders per group.
1650 for (sblock
.fs_cpc
= NSPB(&sblock
), i
= sblock
.fs_spc
;
1651 sblock
.fs_cpc
> 1 && (i
& 1) == 0;
1652 sblock
.fs_cpc
>>= 1, i
>>= 1)
1654 mincpc
= sblock
.fs_cpc
;
1656 /* if these calculations are changed, check dump_fscmd also */
1657 bpcg
= (uint64_t)sblock
.fs_spc
* sectorsize
;
1658 inospercg
= (uint64_t)roundup(bpcg
/ sizeof (struct dinode
),
1660 if (inospercg
> MAXIpG(&sblock
))
1661 inospercg
= MAXIpG(&sblock
);
1662 used
= (uint64_t)(sblock
.fs_iblkno
+ inospercg
/
1663 INOPF(&sblock
)) * NSPF(&sblock
);
1664 mincpgcnt
= (long)howmany((uint64_t)sblock
.fs_cgoffset
*
1665 (~sblock
.fs_cgmask
) + used
, sblock
.fs_spc
);
1666 mincpg
= roundup(mincpgcnt
, mincpc
);
1668 * Insure that cylinder group with mincpg has enough space
1671 sblock
.fs_cpg
= mincpg
;
1672 sblock
.fs_ipg
= (int32_t)inospercg
;
1676 * Make sure the cg struct fits within the file system block.
1677 * Use larger block sizes until it fits
1679 while (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
1681 if (sblock
.fs_bsize
< MAXBSIZE
) {
1682 sblock
.fs_bsize
<<= 1;
1686 sblock
.fs_cpc
<<= 1;
1688 mincpg
= roundup(mincpgcnt
, mincpc
);
1689 sblock
.fs_cpg
= mincpg
;
1691 sblock
.fs_frag
<<= 1;
1692 sblock
.fs_fragshift
+= 1;
1693 if (sblock
.fs_frag
<= MAXFRAG
)
1698 * Looped far enough. The fragment is now as large as the
1701 if (sblock
.fs_fsize
== sblock
.fs_bsize
) {
1702 (void) fprintf(stderr
, gettext(
1703 "There is no block size that can support this disk\n"));
1708 * Try a larger fragment. Double the fragment size.
1710 sblock
.fs_frag
>>= 1;
1711 sblock
.fs_fragshift
-= 1;
1712 sblock
.fs_fsize
<<= 1;
1713 sblock
.fs_nspf
<<= 1;
1716 * Insure that cylinder group with mincpg has enough space for inodes
1720 nbytes64
= (uint64_t)mincpg
* bpcg
- used
;
1721 inospercg
= (uint64_t)roundup((nbytes64
/ nbpi
), INOPB(&sblock
));
1722 sblock
.fs_ipg
= (int32_t)inospercg
;
1723 while (inospercg
> MAXIpG(&sblock
)) {
1725 if (mincpc
== 1 || sblock
.fs_frag
== 1 ||
1726 sblock
.fs_bsize
== MINBSIZE
)
1728 nbytes64
= (uint64_t)mincpg
* bpcg
- used
;
1729 (void) fprintf(stderr
,
1730 gettext("With a block size of %d %s %lu\n"),
1731 sblock
.fs_bsize
, gettext("minimum bytes per inode is"),
1732 (uint32_t)(nbytes64
/ MAXIpG(&sblock
) + 1));
1733 sblock
.fs_bsize
>>= 1;
1734 sblock
.fs_frag
>>= 1;
1735 sblock
.fs_fragshift
-= 1;
1737 sblock
.fs_cpg
= roundup(mincpgcnt
, mincpc
);
1738 if (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
1739 sblock
.fs_bsize
<<= 1;
1742 mincpg
= sblock
.fs_cpg
;
1743 nbytes64
= (uint64_t)mincpg
* bpcg
- used
;
1744 inospercg
= (uint64_t)roundup((nbytes64
/ nbpi
),
1746 sblock
.fs_ipg
= (int32_t)inospercg
;
1749 if (inospercg
> MAXIpG(&sblock
)) {
1750 nbytes64
= (uint64_t)mincpg
* bpcg
- used
;
1751 (void) fprintf(stderr
, gettext(
1752 "Minimum bytes per inode is %d\n"),
1753 (uint32_t)(nbytes64
/ MAXIpG(&sblock
) + 1));
1754 } else if (!mapcramped
) {
1755 (void) fprintf(stderr
, gettext(
1756 "With %ld bytes per inode, minimum cylinders per group is %ld\n"),
1761 (void) fprintf(stderr
, gettext(
1762 "With %d sectors per cylinder, minimum cylinders "
1763 "per group is %ld\n"),
1764 sblock
.fs_spc
, mincpg
);
1766 if (inodecramped
|| mapcramped
) {
1768 * To make this at least somewhat comprehensible in
1769 * the world of i18n, figure out what we're going to
1770 * say and then say it all at one time. The days of
1771 * needing to scrimp on string space are behind us....
1773 if ((sblock
.fs_bsize
!= bsize
) &&
1774 (sblock
.fs_fsize
!= fragsize
)) {
1775 (void) fprintf(stderr
, gettext(
1776 "This requires the block size to be changed from %ld to %d\n"
1777 "and the fragment size to be changed from %ld to %d\n"),
1778 bsize
, sblock
.fs_bsize
,
1779 fragsize
, sblock
.fs_fsize
);
1780 } else if (sblock
.fs_bsize
!= bsize
) {
1781 (void) fprintf(stderr
, gettext(
1782 "This requires the block size to be changed from %ld to %d\n"),
1783 bsize
, sblock
.fs_bsize
);
1784 } else if (sblock
.fs_fsize
!= fragsize
) {
1785 (void) fprintf(stderr
, gettext(
1786 "This requires the fragment size to be changed from %ld to %d\n"),
1787 fragsize
, sblock
.fs_fsize
);
1789 (void) fprintf(stderr
, gettext(
1790 "Unable to make filesystem fit with the given constraints\n"));
1792 (void) fprintf(stderr
, gettext(
1793 "Please re-run mkfs with corrected parameters\n"));
1797 * Calculate the number of cylinders per group
1799 sblock
.fs_cpg
= cpg
;
1800 if (sblock
.fs_cpg
% mincpc
!= 0) {
1801 (void) fprintf(stderr
, gettext(
1802 "Warning: cylinder groups must have a multiple "
1803 "of %ld cylinders with the given\n parameters\n"),
1805 sblock
.fs_cpg
= roundup(sblock
.fs_cpg
, mincpc
);
1806 (void) fprintf(stderr
, gettext("Rounded cgsize up to %d\n"),
1810 * Must insure there is enough space for inodes
1812 /* if these calculations are changed, check dump_fscmd also */
1813 nbytes64
= (uint64_t)sblock
.fs_cpg
* bpcg
- used
;
1814 sblock
.fs_ipg
= roundup((uint32_t)(nbytes64
/ nbpi
), INOPB(&sblock
));
1817 * Slim down cylinders per group, until the inodes can fit.
1819 while (sblock
.fs_ipg
> MAXIpG(&sblock
)) {
1821 sblock
.fs_cpg
-= mincpc
;
1822 nbytes64
= (uint64_t)sblock
.fs_cpg
* bpcg
- used
;
1823 sblock
.fs_ipg
= roundup((uint32_t)(nbytes64
/ nbpi
),
1827 * Must insure there is enough space to hold block map.
1828 * Cut down on cylinders per group, until the cg struct fits in a
1831 while (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
1833 sblock
.fs_cpg
-= mincpc
;
1834 nbytes64
= (uint64_t)sblock
.fs_cpg
* bpcg
- used
;
1835 sblock
.fs_ipg
= roundup((uint32_t)(nbytes64
/ nbpi
),
1838 sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) / NSPF(&sblock
);
1839 if ((sblock
.fs_cpg
* sblock
.fs_spc
) % NSPB(&sblock
) != 0) {
1840 (void) fprintf(stderr
,
1841 gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n"));
1844 if (sblock
.fs_cpg
< mincpg
) {
1845 (void) fprintf(stderr
, gettext(
1846 "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"),
1850 sblock
.fs_cgsize
= fragroundup(&sblock
, CGSIZE(&sblock
));
1853 * Now have size for file system and nsect and ntrak.
1854 * Determine number of cylinders and blocks in the file system.
1856 fssize_frag
= (int64_t)dbtofsb(&sblock
, fssize_db
);
1857 if (fssize_frag
> INT_MAX
) {
1858 (void) fprintf(stderr
, gettext(
1859 "There are too many fragments in the system, increase fragment size\n"),
1863 sblock
.fs_size
= (int32_t)fssize_frag
;
1864 sblock
.fs_ncyl
= (int32_t)(fssize_frag
* NSPF(&sblock
) / sblock
.fs_spc
);
1865 if (fssize_frag
* NSPF(&sblock
) >
1866 (uint64_t)sblock
.fs_ncyl
* sblock
.fs_spc
) {
1870 if (sblock
.fs_ncyl
< 1) {
1871 (void) fprintf(stderr
, gettext(
1872 "file systems must have at least one cylinder\n"));
1878 * Determine feasability/values of rotational layout tables.
1880 * The size of the rotational layout tables is limited by the size
1881 * of the file system block, fs_bsize. The amount of space
1882 * available for tables is calculated as (fs_bsize - sizeof (struct
1883 * fs)). The size of these tables is inversely proportional to the
1884 * block size of the file system. The size increases if sectors per
1885 * track are not powers of two, because more cylinders must be
1886 * described by the tables before the rotational pattern repeats
1889 sblock
.fs_postblformat
= FS_DYNAMICPOSTBLFMT
;
1890 sblock
.fs_sbsize
= fragroundup(&sblock
, sizeof (struct fs
));
1891 sblock
.fs_npsect
= sblock
.fs_nsect
;
1892 if (sblock
.fs_ntrak
== 1) {
1896 postblsize
= sblock
.fs_nrpos
* sblock
.fs_cpc
* sizeof (short);
1897 rotblsize
= sblock
.fs_cpc
* sblock
.fs_spc
/ NSPB(&sblock
);
1898 totalsbsize
= sizeof (struct fs
) + rotblsize
;
1900 /* do static allocation if nrpos == 8 and fs_cpc == 16 */
1901 if (sblock
.fs_nrpos
== 8 && sblock
.fs_cpc
<= 16) {
1902 /* use old static table space */
1903 sblock
.fs_postbloff
= (char *)(&sblock
.fs_opostbl
[0][0]) -
1904 (char *)(&sblock
.fs_link
);
1905 sblock
.fs_rotbloff
= &sblock
.fs_space
[0] -
1906 (uchar_t
*)(&sblock
.fs_link
);
1908 /* use 4.3 dynamic table space */
1909 sblock
.fs_postbloff
= &sblock
.fs_space
[0] -
1910 (uchar_t
*)(&sblock
.fs_link
);
1911 sblock
.fs_rotbloff
= sblock
.fs_postbloff
+ postblsize
;
1912 totalsbsize
+= postblsize
;
1914 if (totalsbsize
> sblock
.fs_bsize
||
1915 sblock
.fs_nsect
> (1 << NBBY
) * NSPB(&sblock
)) {
1916 (void) fprintf(stderr
, gettext(
1917 "Warning: insufficient space in super block for\n"
1918 "rotational layout tables with nsect %d, ntrack %d, "
1919 "and nrpos %d.\nOmitting tables - file system "
1920 "performance may be impaired.\n"),
1921 sblock
.fs_nsect
, sblock
.fs_ntrak
, sblock
.fs_nrpos
);
1924 * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to
1925 * ignore the positional layout table and rotational
1931 sblock
.fs_sbsize
= fragroundup(&sblock
, totalsbsize
);
1935 * calculate the available blocks for each rotational position
1937 for (cylno
= 0; cylno
< sblock
.fs_cpc
; cylno
++)
1938 for (rpos
= 0; rpos
< sblock
.fs_nrpos
; rpos
++)
1939 fs_postbl(&sblock
, cylno
)[rpos
] = -1;
1940 for (i
= (rotblsize
- 1) * sblock
.fs_frag
;
1941 i
>= 0; i
-= sblock
.fs_frag
) {
1942 cylno
= cbtocylno(&sblock
, i
);
1943 rpos
= cbtorpos(&sblock
, i
);
1944 blk
= fragstoblks(&sblock
, i
);
1945 if (fs_postbl(&sblock
, cylno
)[rpos
] == -1)
1946 fs_rotbl(&sblock
)[blk
] = 0;
1948 fs_rotbl(&sblock
)[blk
] =
1949 fs_postbl(&sblock
, cylno
)[rpos
] - blk
;
1950 fs_postbl(&sblock
, cylno
)[rpos
] = blk
;
1955 * Compute/validate number of cylinder groups.
1956 * Note that if an excessively large filesystem is specified
1957 * (e.g., more than 16384 cylinders for an 8K filesystem block), it
1958 * does not get detected until checksummarysize()
1960 sblock
.fs_ncg
= sblock
.fs_ncyl
/ sblock
.fs_cpg
;
1961 if (sblock
.fs_ncyl
% sblock
.fs_cpg
)
1963 sblock
.fs_dblkno
= sblock
.fs_iblkno
+ sblock
.fs_ipg
/ INOPF(&sblock
);
1964 i
= MIN(~sblock
.fs_cgmask
, sblock
.fs_ncg
- 1);
1965 ibpcl
= cgdmin(&sblock
, i
) - cgbase(&sblock
, i
);
1966 if (ibpcl
>= sblock
.fs_fpg
) {
1967 (void) fprintf(stderr
, gettext(
1968 "inode blocks/cyl group (%d) >= data blocks (%d)\n"),
1969 cgdmin(&sblock
, i
) - cgbase(&sblock
, i
) / sblock
.fs_frag
,
1970 sblock
.fs_fpg
/ sblock
.fs_frag
);
1971 if ((ibpcl
< 0) || (sblock
.fs_fpg
< 0)) {
1972 (void) fprintf(stderr
, gettext(
1973 "number of cylinders per cylinder group (%d) must be decreased.\n"),
1976 (void) fprintf(stderr
, gettext(
1977 "number of cylinders per cylinder group (%d) must be increased.\n"),
1980 (void) fprintf(stderr
, gettext(
1981 "Note that cgsize may have been adjusted to allow struct cg to fit.\n"));
1984 j
= sblock
.fs_ncg
- 1;
1985 if ((i
= fssize_frag
- j
* sblock
.fs_fpg
) < sblock
.fs_fpg
&&
1986 cgdmin(&sblock
, j
) - cgbase(&sblock
, j
) > i
) {
1987 (void) fprintf(stderr
, gettext(
1988 "Warning: inode blocks/cyl group (%d) >= data "
1989 "blocks (%ld) in last\n cylinder group. This "
1990 "implies %ld sector(s) cannot be allocated.\n"),
1991 (cgdmin(&sblock
, j
) - cgbase(&sblock
, j
)) / sblock
.fs_frag
,
1992 i
/ sblock
.fs_frag
, i
* NSPF(&sblock
));
1994 * If there is only one cylinder group and that is not even
1995 * big enough to hold the inodes, exit.
1997 if (sblock
.fs_ncg
== 1)
2000 sblock
.fs_ncyl
= sblock
.fs_ncg
* sblock
.fs_cpg
;
2001 sblock
.fs_size
= fssize_frag
=
2002 (int64_t)sblock
.fs_ncyl
* (int64_t)sblock
.fs_spc
/
2003 (int64_t)NSPF(&sblock
);
2006 if (warn
&& !spc_flag
) {
2007 (void) fprintf(stderr
, gettext(
2008 "Warning: %d sector(s) in last cylinder unallocated\n"),
2009 sblock
.fs_spc
- (uint32_t)(fssize_frag
* NSPF(&sblock
) -
2010 (uint64_t)(sblock
.fs_ncyl
- 1) * sblock
.fs_spc
));
2013 * fill in remaining fields of the super block
2017 * The csum records are stored in cylinder group 0, starting at
2018 * cgdmin, the first data block.
2020 sblock
.fs_csaddr
= cgdmin(&sblock
, 0);
2022 fragroundup(&sblock
, sblock
.fs_ncg
* sizeof (struct csum
));
2023 i
= sblock
.fs_bsize
/ sizeof (struct csum
);
2024 sblock
.fs_csmask
= ~(i
- 1);
2025 for (sblock
.fs_csshift
= 0; i
> 1; i
>>= 1)
2026 sblock
.fs_csshift
++;
2027 fscs
= (struct csum
*)calloc(1, sblock
.fs_cssize
);
2031 sblock
.fs_magic
= MTB_UFS_MAGIC
;
2032 sblock
.fs_version
= MTB_UFS_VERSION_1
;
2034 sblock
.fs_magic
= FS_MAGIC
;
2036 sblock
.fs_version
= UFS_EFISTYLE4NONEFI_VERSION_2
;
2038 sblock
.fs_version
= UFS_VERSION_MIN
;
2042 bcopy((caddr_t
)grow_fscs
, (caddr_t
)fscs
, (int)grow_fs_cssize
);
2043 extendsummaryinfo();
2046 sblock
.fs_rotdelay
= rotdelay
;
2047 sblock
.fs_maxcontig
= maxcontig
;
2048 sblock
.fs_maxbpg
= MAXBLKPG(sblock
.fs_bsize
);
2050 sblock
.fs_rps
= rps
;
2051 sblock
.fs_cgrotor
= 0;
2052 sblock
.fs_cstotal
.cs_ndir
= 0;
2053 sblock
.fs_cstotal
.cs_nbfree
= 0;
2054 sblock
.fs_cstotal
.cs_nifree
= 0;
2055 sblock
.fs_cstotal
.cs_nffree
= 0;
2057 sblock
.fs_ronly
= 0;
2058 sblock
.fs_time
= mkfstime
;
2059 sblock
.fs_state
= FSOKAY
- sblock
.fs_time
;
2060 sblock
.fs_clean
= FSCLEAN
;
2064 * If all that's needed is a dump of the superblock we
2065 * would use by default, we've got it now. So, splat it
2073 * Dump out summary information about file system.
2075 (void) fprintf(stderr
, gettext(
2076 "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"),
2077 fsys
, (uint64_t)sblock
.fs_size
* NSPF(&sblock
), sblock
.fs_ncyl
,
2078 sblock
.fs_ntrak
, sblock
.fs_nsect
);
2079 (void) fprintf(stderr
, gettext(
2080 "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"),
2081 (float)sblock
.fs_size
* sblock
.fs_fsize
/ MB
, sblock
.fs_ncg
,
2082 sblock
.fs_cpg
, (float)sblock
.fs_fpg
* sblock
.fs_fsize
/ MB
,
2085 tmpbuf
= calloc(sblock
.fs_ncg
/ 50 + 500, 1);
2086 if (tmpbuf
== NULL
) {
2091 (void) fprintf(stderr
, gettext("File system creation failed. "
2092 "There is only one cylinder group and\nthat is "
2093 "not even big enough to hold the inodes.\n"));
2097 * Now build the cylinders group blocks and
2098 * then print out indices of cylinder groups.
2101 "super-block backups (for fsck -F ufs -o b=#) at:\n"));
2102 for (width
= cylno
= 0; cylno
< sblock
.fs_ncg
&& cylno
< 10; cylno
++) {
2103 if ((grow
== 0) || (cylno
>= grow_fs_ncg
))
2105 num
= fsbtodb(&sblock
, (uint64_t)cgsblock(&sblock
, cylno
));
2107 * If Nflag and if the disk is larger than the CHSLIMIT,
2108 * then sanity test the superblocks before reporting. If there
2109 * are too many superblocks which look insane, we have
2110 * to retry with alternate logic. If both methods have
2111 * failed, then our efforts to arrive at alternate
2112 * superblocks failed, so complain and exit.
2114 if (Nflag
&& retry
) {
2116 rdfs((diskaddr_t
)num
, sbsize
, (char *)&altsblock
);
2117 ret
= checksblock(altsblock
, 1);
2121 dprintf(("DeBuG checksblock() failed - error :"
2122 " %d for sb : %llu invalid_sb_cnt : %d\n",
2123 ret
, num
, invalid_sb_cnt
));
2126 * Though the superblock looks sane, verify if
2127 * the fs_version in the superblock and the
2128 * logic that we are using to arrive at the
2129 * superblocks match.
2131 if (use_efi_dflts
&& altsblock
.fs_version
2132 != UFS_EFISTYLE4NONEFI_VERSION_2
) {
2137 if (invalid_sb_cnt
>= INVALIDSBLIMIT
) {
2139 (void) fprintf(stderr
, gettext(
2140 "Error determining alternate "
2141 "superblock locations\n"));
2146 use_efi_dflts
= !use_efi_dflts
;
2148 goto retry_alternate_logic
;
2153 (void) sprintf(pbuf
, " %llu,", num
);
2154 plen
= strlen(pbuf
);
2155 if ((width
+ plen
) > (WIDTH
- 1)) {
2162 (void) strncat(tmpbuf
, pbuf
, strlen(pbuf
));
2164 (void) fprintf(stderr
, "%s", pbuf
);
2168 remaining_cg
= sblock
.fs_ncg
- cylno
;
2171 * If there are more than 300 cylinder groups still to be
2172 * initialized, print a "." for every 50 cylinder groups.
2174 if (remaining_cg
> 300) {
2175 tprintf(gettext("Initializing cylinder groups:\n"));
2180 * Now initialize all cylinder groups between the first ten
2183 * If the number of cylinder groups was less than 10, all of the
2184 * cylinder group offsets would have printed in the last loop
2185 * and cylno will already be equal to sblock.fs_ncg and so this
2186 * loop will not be entered. If there are less than 20 cylinder
2187 * groups, cylno is already less than fs_ncg - 10, so this loop
2188 * won't be entered in that case either.
2192 for (; cylno
< sblock
.fs_ncg
- 10; cylno
++) {
2193 if ((grow
== 0) || (cylno
>= grow_fs_ncg
))
2195 if (do_dot
&& cylno
% 50 == 0) {
2198 if (i
== WIDTH
- 1) {
2206 * Now print the cylinder group offsets for the last 10
2207 * cylinder groups, if any are left.
2212 "\nsuper-block backups for last 10 cylinder groups at:\n"));
2214 for (width
= 0; cylno
< sblock
.fs_ncg
; cylno
++) {
2215 if ((grow
== 0) || (cylno
>= grow_fs_ncg
))
2217 num
= fsbtodb(&sblock
, (uint64_t)cgsblock(&sblock
, cylno
));
2218 if (Nflag
&& retry
) {
2220 rdfs((diskaddr_t
)num
, sbsize
, (char *)&altsblock
);
2221 ret
= checksblock(altsblock
, 1);
2225 dprintf(("DeBuG checksblock() failed - error :"
2226 " %d for sb : %llu invalid_sb_cnt : %d\n",
2227 ret
, num
, invalid_sb_cnt
));
2230 * Though the superblock looks sane, verify if
2231 * the fs_version in the superblock and the
2232 * logic that we are using to arrive at the
2233 * superblocks match.
2235 if (use_efi_dflts
&& altsblock
.fs_version
2236 != UFS_EFISTYLE4NONEFI_VERSION_2
) {
2241 if (invalid_sb_cnt
>= INVALIDSBLIMIT
) {
2243 (void) fprintf(stderr
, gettext(
2244 "Error determining alternate "
2245 "superblock locations\n"));
2250 use_efi_dflts
= !use_efi_dflts
;
2252 goto retry_alternate_logic
;
2257 /* Don't print ',' for the last superblock */
2258 if (cylno
== sblock
.fs_ncg
-1)
2259 (void) sprintf(pbuf
, " %llu", num
);
2261 (void) sprintf(pbuf
, " %llu,", num
);
2262 plen
= strlen(pbuf
);
2263 if ((width
+ plen
) > (WIDTH
- 1)) {
2270 (void) strncat(tmpbuf
, pbuf
, strlen(pbuf
));
2272 (void) fprintf(stderr
, "%s", pbuf
);
2277 (void) fprintf(stderr
, "%s", tmpbuf
);
2287 * Now construct the initial file system,
2288 * then write out the super-block.
2293 * write the superblock and csum information
2298 * extend the last cylinder group in the original file system
2301 extendcg(grow_fs_ncg
-1);
2306 * Write out the duplicate super blocks to the first 10
2307 * cylinder groups (or fewer, if there are fewer than 10
2310 for (cylno
= 0; cylno
< sblock
.fs_ncg
&& cylno
< 10; cylno
++)
2311 awtfs(fsbtodb(&sblock
, (uint64_t)cgsblock(&sblock
, cylno
)),
2312 (int)sbsize
, (char *)&sblock
, SAVE
);
2315 * Now write out duplicate super blocks to the remaining
2316 * cylinder groups. In the case of multi-terabyte file
2317 * systems, just write out the super block to the last ten
2318 * cylinder groups (or however many are left).
2321 if (sblock
.fs_ncg
<= 10)
2322 cylno
= sblock
.fs_ncg
;
2323 else if (sblock
.fs_ncg
<= 20)
2326 cylno
= sblock
.fs_ncg
- 10;
2329 for (; cylno
< sblock
.fs_ncg
; cylno
++)
2330 awtfs(fsbtodb(&sblock
, (uint64_t)cgsblock(&sblock
, cylno
)),
2331 (int)sbsize
, (char *)&sblock
, SAVE
);
2334 * Flush out all the AIO writes we've done. It's not
2335 * necessary to do this explicitly, but it's the only
2336 * way to report any errors from those writes.
2344 sblock
.fs_clean
= grow_fs_clean
;
2346 sblock
.fs_clean
= FSCLEAN
;
2347 sblock
.fs_time
= mkfstime
;
2348 sblock
.fs_state
= FSOKAY
- sblock
.fs_time
;
2349 wtfs((diskaddr_t
)(SBOFF
/ sectorsize
), sbsize
, (char *)&sblock
);
2352 if (fsync(fso
) == -1) {
2354 (void) fprintf(stderr
,
2355 gettext("mkfs: fsync failed on write disk: %s\n"),
2357 /* we're just cleaning up, so keep going */
2359 if (close(fsi
) == -1) {
2361 (void) fprintf(stderr
,
2362 gettext("mkfs: close failed on read disk: %s\n"),
2364 /* we're just cleaning up, so keep going */
2366 if (close(fso
) == -1) {
2368 (void) fprintf(stderr
,
2369 gettext("mkfs: close failed on write disk: %s\n"),
2371 /* we're just cleaning up, so keep going */
2383 * Figure out how big the partition we're dealing with is.
2384 * The value returned is in disk blocks (sectors);
2387 get_max_size(int fd
)
2389 struct extvtoc vtoc
;
2391 diskaddr_t slicesize
;
2393 int index
= read_extvtoc(fd
, &vtoc
);
2396 label_type
= LABEL_TYPE_VTOC
;
2398 if (index
== VT_ENOTSUP
|| index
== VT_ERROR
) {
2399 /* it might be an EFI label */
2400 index
= efi_alloc_and_read(fd
, &efi_vtoc
);
2401 label_type
= LABEL_TYPE_EFI
;
2415 perror(gettext("Can not determine partition size"));
2419 if (label_type
== LABEL_TYPE_EFI
) {
2420 slicesize
= efi_vtoc
->efi_parts
[index
].p_size
;
2424 * In the vtoc struct, p_size is a 32-bit signed quantity.
2425 * In the dk_gpt struct (efi's version of the vtoc), p_size
2426 * is an unsigned 64-bit quantity. By casting the vtoc's
2427 * psize to an unsigned 32-bit quantity, it will be copied
2428 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without
2432 slicesize
= (uint32_t)vtoc
.v_part
[index
].p_size
;
2435 dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n",
2436 index
, slicesize
, (slicesize
> FS_MAX
)));
2439 * The next line limits a UFS file system to the maximum
2443 if (slicesize
> FS_MAX
)
2449 get_max_track_size(int fd
)
2452 long track_size
= -1;
2454 if (ioctl(fd
, DKIOCINFO
, &ci
) == 0) {
2455 track_size
= ci
.dki_maxtransfer
* DEV_BSIZE
;
2458 if ((track_size
< 0)) {
2463 gotit
= fsgetmaxphys(&maxphys
, &error
);
2465 track_size
= MIN(MB
, maxphys
);
2467 (void) fprintf(stderr
, gettext(
2468 "Warning: Could not get system value for maxphys. The value for\n"
2469 "maxcontig will default to 1MB.\n"));
2473 return (track_size
);
2477 * Initialize a cylinder group.
2482 diskaddr_t cbase
, d
;
2483 diskaddr_t dlower
; /* last data block before cg metadata */
2484 diskaddr_t dupper
; /* first data block after cg metadata */
2488 struct dinode
*inode_buffer
;
2492 * Variables used to store intermediate results as a part of
2493 * the internal implementation of the cbtocylno() macros.
2495 diskaddr_t bno
; /* UFS block number (not sector number) */
2496 int cbcylno
; /* current cylinder number */
2497 int cbcylno_sect
; /* sector offset within cylinder */
2498 int cbsect_incr
; /* amount to increment sector offset */
2501 * Variables used to store intermediate results as a part of
2502 * the internal implementation of the cbtorpos() macros.
2504 short *cgblks
; /* pointer to array of free blocks in cg */
2505 int trackrpos
; /* tmp variable for rotation position */
2506 int trackoff
; /* offset within a track */
2507 int trackoff_incr
; /* amount to increment trackoff */
2508 int rpos
; /* rotation position of current block */
2509 int rpos_incr
; /* amount to increment rpos per block */
2511 union cgun
*icgun
; /* local pointer to a cg summary block */
2512 #define icg (icgun->cg)
2514 icgun
= (union cgun
*)getbuf(&cgsumbuf
, sizeof (union cgun
));
2517 * Determine block bounds for cylinder group.
2518 * Allow space for super block summary information in first
2521 cbase
= cgbase(&sblock
, cylno
);
2522 dmax
= cbase
+ sblock
.fs_fpg
;
2523 if (dmax
> sblock
.fs_size
) /* last cg may be smaller than normal */
2524 dmax
= sblock
.fs_size
;
2525 dlower
= cgsblock(&sblock
, cylno
) - cbase
;
2526 dupper
= cgdmin(&sblock
, cylno
) - cbase
;
2528 dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
2530 icg
.cg_time
= mkfstime
;
2531 icg
.cg_magic
= CG_MAGIC
;
2533 /* last one gets whatever's left */
2534 if (cylno
== sblock
.fs_ncg
- 1)
2535 icg
.cg_ncyl
= sblock
.fs_ncyl
- (sblock
.fs_cpg
* cylno
);
2537 icg
.cg_ncyl
= sblock
.fs_cpg
;
2538 icg
.cg_niblk
= sblock
.fs_ipg
;
2539 icg
.cg_ndblk
= dmax
- cbase
;
2540 icg
.cg_cs
.cs_ndir
= 0;
2541 icg
.cg_cs
.cs_nffree
= 0;
2542 icg
.cg_cs
.cs_nbfree
= 0;
2543 icg
.cg_cs
.cs_nifree
= 0;
2547 icg
.cg_btotoff
= &icg
.cg_space
[0] - (uchar_t
*)(&icg
.cg_link
);
2548 icg
.cg_boff
= icg
.cg_btotoff
+ sblock
.fs_cpg
* sizeof (long);
2549 icg
.cg_iusedoff
= icg
.cg_boff
+
2550 sblock
.fs_cpg
* sblock
.fs_nrpos
* sizeof (short);
2551 icg
.cg_freeoff
= icg
.cg_iusedoff
+ howmany(sblock
.fs_ipg
, NBBY
);
2552 icg
.cg_nextfreeoff
= icg
.cg_freeoff
+
2553 howmany(sblock
.fs_cpg
* sblock
.fs_spc
/ NSPF(&sblock
), NBBY
);
2554 for (i
= 0; i
< sblock
.fs_frag
; i
++) {
2555 icg
.cg_frsum
[i
] = 0;
2557 bzero((caddr_t
)cg_inosused(&icg
), icg
.cg_freeoff
- icg
.cg_iusedoff
);
2558 icg
.cg_cs
.cs_nifree
+= sblock
.fs_ipg
;
2560 for (i
= 0; i
< UFSROOTINO
; i
++) {
2561 setbit(cg_inosused(&icg
), i
);
2562 icg
.cg_cs
.cs_nifree
--;
2566 * Initialize all the inodes in the cylinder group using
2569 size
= sblock
.fs_ipg
* sizeof (struct dinode
);
2570 inode_buffer
= (struct dinode
*)getbuf(&inodebuf
, size
);
2572 for (i
= 0; i
< sblock
.fs_ipg
; i
++) {
2573 IRANDOMIZE(&(inode_buffer
[i
].di_ic
));
2577 * Write all inodes in a single write for performance.
2579 awtfs(fsbtodb(&sblock
, (uint64_t)cgimin(&sblock
, cylno
)), (int)size
,
2580 (char *)inode_buffer
, RELEASE
);
2582 bzero((caddr_t
)cg_blktot(&icg
), icg
.cg_boff
- icg
.cg_btotoff
);
2583 bzero((caddr_t
)cg_blks(&sblock
, &icg
, 0),
2584 icg
.cg_iusedoff
- icg
.cg_boff
);
2585 bzero((caddr_t
)cg_blksfree(&icg
), icg
.cg_nextfreeoff
- icg
.cg_freeoff
);
2588 for (d
= 0; d
< dlower
; d
+= sblock
.fs_frag
) {
2589 setblock(&sblock
, cg_blksfree(&icg
), d
/sblock
.fs_frag
);
2590 icg
.cg_cs
.cs_nbfree
++;
2591 cg_blktot(&icg
)[cbtocylno(&sblock
, d
)]++;
2592 cg_blks(&sblock
, &icg
, cbtocylno(&sblock
, d
))
2593 [cbtorpos(&sblock
, d
)]++;
2595 sblock
.fs_dsize
+= dlower
;
2597 sblock
.fs_dsize
+= icg
.cg_ndblk
- dupper
;
2598 if ((i
= dupper
% sblock
.fs_frag
) != 0) {
2599 icg
.cg_frsum
[sblock
.fs_frag
- i
]++;
2600 for (d
= dupper
+ sblock
.fs_frag
- i
; dupper
< d
; dupper
++) {
2601 setbit(cg_blksfree(&icg
), dupper
);
2602 icg
.cg_cs
.cs_nffree
++;
2607 * WARNING: The following code is somewhat confusing, but
2608 * results in a substantial performance improvement in mkfs.
2610 * Instead of using cbtocylno() and cbtorpos() macros, we
2611 * keep track of all the intermediate state of those macros
2612 * in some variables. This allows simple addition to be
2613 * done to calculate the results as we step through the
2614 * blocks in an orderly fashion instead of the slower
2615 * multiplication and division the macros are forced to
2616 * used so they can support random input. (Multiplication,
2617 * division, and remainder operations typically take about
2618 * 10x as many processor cycles as other operations.)
2620 * The basic idea is to take code:
2622 * for (x = starting_x; x < max; x++)
2625 * and rewrite it to take advantage of the fact that
2626 * the variable x is incrementing in an orderly way:
2628 * intermediate = starting_x * c
2629 * yval = intermediate / z
2630 * for (x = starting_x; x < max; x++) {
2633 * if (intermediate > z) {
2639 * Performance has improved as much as 4X using this code.
2643 * Initialize the starting points for all the cbtocylno()
2644 * macro variables and figure out the increments needed each
2645 * time through the loop.
2647 cbcylno_sect
= dupper
* NSPF(&sblock
);
2648 cbsect_incr
= sblock
.fs_frag
* NSPF(&sblock
);
2649 cbcylno
= cbcylno_sect
/ sblock
.fs_spc
;
2650 cbcylno_sect
%= sblock
.fs_spc
;
2651 cgblks
= cg_blks(&sblock
, &icg
, cbcylno
);
2652 bno
= dupper
/ sblock
.fs_frag
;
2655 * Initialize the starting points for all the cbtorpos()
2656 * macro variables and figure out the increments needed each
2657 * time through the loop.
2659 * It's harder to simplify the cbtorpos() macro if there were
2660 * alternate sectors specified (or if they previously existed
2661 * in the growfs case). Since this is rare, we just revert to
2662 * using the macros in this case and skip the variable setup.
2665 trackrpos
= (cbcylno_sect
% sblock
.fs_nsect
) * sblock
.fs_nrpos
;
2666 rpos
= trackrpos
/ sblock
.fs_nsect
;
2667 trackoff
= trackrpos
% sblock
.fs_nsect
;
2668 trackoff_incr
= cbsect_incr
* sblock
.fs_nrpos
;
2669 rpos_incr
= (trackoff_incr
/ sblock
.fs_nsect
) % sblock
.fs_nrpos
;
2670 trackoff_incr
= trackoff_incr
% sblock
.fs_nsect
;
2674 * Loop through all the blocks, marking them free and
2675 * updating totals kept in the superblock and cg summary.
2677 for (d
= dupper
; d
+ sblock
.fs_frag
<= dmax
- cbase
; ) {
2678 setblock(&sblock
, cg_blksfree(&icg
), bno
);
2679 icg
.cg_cs
.cs_nbfree
++;
2681 cg_blktot(&icg
)[cbcylno
]++;
2686 cg_blks(&sblock
, &icg
, cbtocylno(&sblock
, d
))
2687 [cbtorpos(&sblock
, d
)]++;
2689 d
+= sblock
.fs_frag
;
2693 * Increment the sector offset within the cylinder
2694 * for the cbtocylno() macro reimplementation. If
2695 * we're beyond the end of the cylinder, update the
2696 * cylinder number, calculate the offset in the
2697 * new cylinder, and update the cgblks pointer
2698 * to the next rotational position.
2700 cbcylno_sect
+= cbsect_incr
;
2701 if (cbcylno_sect
>= sblock
.fs_spc
) {
2703 cbcylno_sect
-= sblock
.fs_spc
;
2704 cgblks
+= sblock
.fs_nrpos
;
2708 * If there aren't alternate sectors, increment the
2709 * rotational position variables for the cbtorpos()
2710 * reimplementation. Note that we potentially
2711 * increment rpos twice. Once by rpos_incr, and one
2712 * more time when we wrap to a new track because
2713 * trackoff >= fs_nsect.
2716 trackoff
+= trackoff_incr
;
2718 if (trackoff
>= sblock
.fs_nsect
) {
2719 trackoff
-= sblock
.fs_nsect
;
2722 if (rpos
>= sblock
.fs_nrpos
)
2723 rpos
-= sblock
.fs_nrpos
;
2727 if (d
< dmax
- cbase
) {
2728 icg
.cg_frsum
[dmax
- cbase
- d
]++;
2729 for (; d
< dmax
- cbase
; d
++) {
2730 setbit(cg_blksfree(&icg
), d
);
2731 icg
.cg_cs
.cs_nffree
++;
2734 sblock
.fs_cstotal
.cs_ndir
+= icg
.cg_cs
.cs_ndir
;
2735 sblock
.fs_cstotal
.cs_nffree
+= icg
.cg_cs
.cs_nffree
;
2736 sblock
.fs_cstotal
.cs_nbfree
+= icg
.cg_cs
.cs_nbfree
;
2737 sblock
.fs_cstotal
.cs_nifree
+= icg
.cg_cs
.cs_nifree
;
2739 awtfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, cylno
)),
2740 sblock
.fs_bsize
, (char *)&icg
, RELEASE
);
2744 * initialize the file system
2755 struct direct root_dir
[] = {
2756 { UFSROOTINO
, sizeof (struct direct
), 1, "." },
2757 { UFSROOTINO
, sizeof (struct direct
), 2, ".." },
2759 { LOSTFOUNDINO
, sizeof (struct direct
), 10, "lost+found" },
2763 struct direct lost_found_dir
[] = {
2764 { LOSTFOUNDINO
, sizeof (struct direct
), 1, "." },
2765 { UFSROOTINO
, sizeof (struct direct
), 2, ".." },
2766 { 0, DIRBLKSIZ
, 0, 0 },
2778 * initialize the node
2780 node
.i_atime
= mkfstime
;
2781 node
.i_mtime
= mkfstime
;
2782 node
.i_ctime
= mkfstime
;
2785 * create the lost+found directory
2787 (void) makedir(lost_found_dir
, 2);
2788 for (i
= DIRBLKSIZ
; i
< sblock
.fs_bsize
; i
+= DIRBLKSIZ
) {
2789 bcopy(&lost_found_dir
[2], &buf
[i
], DIRSIZ(&lost_found_dir
[2]));
2791 node
.i_number
= LOSTFOUNDINO
;
2792 node
.i_smode
= IFDIR
| 0700;
2794 node
.i_size
= sblock
.fs_bsize
;
2795 node
.i_db
[0] = alloc((int)node
.i_size
, node
.i_mode
);
2796 node
.i_blocks
= btodb(fragroundup(&sblock
, (int)node
.i_size
));
2797 IRANDOMIZE(&node
.i_ic
);
2798 wtfs(fsbtodb(&sblock
, (uint64_t)node
.i_db
[0]), (int)node
.i_size
, buf
);
2802 * create the root directory
2804 node
.i_number
= UFSROOTINO
;
2805 node
.i_mode
= IFDIR
| UMASK
;
2806 node
.i_nlink
= PREDEFDIR
;
2807 node
.i_size
= makedir(root_dir
, PREDEFDIR
);
2808 node
.i_db
[0] = alloc(sblock
.fs_fsize
, node
.i_mode
);
2809 /* i_size < 2GB because we are initializing the file system */
2810 node
.i_blocks
= btodb(fragroundup(&sblock
, (int)node
.i_size
));
2811 IRANDOMIZE(&node
.i_ic
);
2812 wtfs(fsbtodb(&sblock
, (uint64_t)node
.i_db
[0]), sblock
.fs_fsize
, buf
);
2817 * construct a set of directory entries in "buf".
2818 * return size of directory.
2821 makedir(struct direct
*protodir
, int entries
)
2827 spcleft
= DIRBLKSIZ
;
2828 for (cp
= buf
, i
= 0; i
< entries
- 1; i
++) {
2829 protodir
[i
].d_reclen
= DIRSIZ(&protodir
[i
]);
2830 bcopy(&protodir
[i
], cp
, protodir
[i
].d_reclen
);
2831 cp
+= protodir
[i
].d_reclen
;
2832 spcleft
-= protodir
[i
].d_reclen
;
2834 protodir
[i
].d_reclen
= spcleft
;
2835 bcopy(&protodir
[i
], cp
, DIRSIZ(&protodir
[i
]));
2840 * allocate a block or frag
2843 alloc(int size
, int mode
)
2848 rdfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
2850 if (acg
.cg_magic
!= CG_MAGIC
) {
2851 (void) fprintf(stderr
, gettext("cg 0: bad magic number\n"));
2854 if (acg
.cg_cs
.cs_nbfree
== 0) {
2855 (void) fprintf(stderr
,
2856 gettext("first cylinder group ran out of space\n"));
2859 for (d
= 0; d
< acg
.cg_ndblk
; d
+= sblock
.fs_frag
)
2860 if (isblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
))
2862 (void) fprintf(stderr
,
2863 gettext("internal error: can't find block in cyl 0\n"));
2866 clrblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
);
2867 acg
.cg_cs
.cs_nbfree
--;
2868 sblock
.fs_cstotal
.cs_nbfree
--;
2869 fscs
[0].cs_nbfree
--;
2871 acg
.cg_cs
.cs_ndir
++;
2872 sblock
.fs_cstotal
.cs_ndir
++;
2875 cg_blktot(&acg
)[cbtocylno(&sblock
, d
)]--;
2876 cg_blks(&sblock
, &acg
, cbtocylno(&sblock
, d
))[cbtorpos(&sblock
, d
)]--;
2877 if (size
!= sblock
.fs_bsize
) {
2878 frag
= howmany(size
, sblock
.fs_fsize
);
2879 fscs
[0].cs_nffree
+= sblock
.fs_frag
- frag
;
2880 sblock
.fs_cstotal
.cs_nffree
+= sblock
.fs_frag
- frag
;
2881 acg
.cg_cs
.cs_nffree
+= sblock
.fs_frag
- frag
;
2882 acg
.cg_frsum
[sblock
.fs_frag
- frag
]++;
2883 for (i
= frag
; i
< sblock
.fs_frag
; i
++)
2884 setbit(cg_blksfree(&acg
), d
+ i
);
2886 wtfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
2892 * Allocate an inode on the disk
2895 iput(struct inode
*ip
)
2897 struct dinode buf
[MAXINOPB
];
2900 rdfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
2902 if (acg
.cg_magic
!= CG_MAGIC
) {
2903 (void) fprintf(stderr
, gettext("cg 0: bad magic number\n"));
2906 acg
.cg_cs
.cs_nifree
--;
2907 setbit(cg_inosused(&acg
), ip
->i_number
);
2908 wtfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
2910 sblock
.fs_cstotal
.cs_nifree
--;
2911 fscs
[0].cs_nifree
--;
2912 if ((int)ip
->i_number
>= sblock
.fs_ipg
* sblock
.fs_ncg
) {
2913 (void) fprintf(stderr
,
2914 gettext("fsinit: inode value out of range (%d).\n"),
2918 d
= fsbtodb(&sblock
, (uint64_t)itod(&sblock
, (int)ip
->i_number
));
2919 rdfs(d
, sblock
.fs_bsize
, (char *)buf
);
2920 buf
[itoo(&sblock
, (int)ip
->i_number
)].di_ic
= ip
->i_ic
;
2921 wtfs(d
, sblock
.fs_bsize
, (char *)buf
);
2925 * getbuf() -- Get a buffer for use in an AIO operation. Buffer
2926 * is zero'd the first time returned, left with whatever
2927 * was in memory after that. This function actually gets
2928 * enough memory the first time it's called to support
2929 * MAXBUF buffers like a slab allocator. When all the
2930 * buffers are in use, it waits for an aio to complete
2931 * and make a buffer available.
2933 * Never returns an error. Either succeeds or exits.
2936 getbuf(bufhdr
*bufhead
, int size
)
2941 int buf_size
, max_bufs
;
2944 * Initialize all the buffers
2946 if (bufhead
->head
== NULL
) {
2948 * round up the size of our buffer header to a
2949 * 16 byte boundary so the address we return to
2950 * the caller is "suitably aligned".
2952 bufhdrsize
= (sizeof (bufhdr
) + 15) & ~15;
2955 * Add in our header to the buffer and round it all up to
2956 * a 16 byte boundry so each member of the slab is aligned.
2958 buf_size
= (size
+ bufhdrsize
+ 15) & ~15;
2961 * Limit number of buffers to lesser of MAXBUFMEM's worth
2962 * or MAXBUF, whichever is less.
2964 max_bufs
= MAXBUFMEM
/ buf_size
;
2965 if (max_bufs
> MAXBUF
)
2968 pbuf
= (bufhdr
*)calloc(max_bufs
, buf_size
);
2974 bufhead
->head
= bufhead
;
2976 for (i
= 0; i
< max_bufs
; i
++) {
2977 pbuf
->head
= bufhead
;
2980 pbuf
= (bufhdr
*)((char *)pbuf
+ buf_size
);
2985 * Get an available buffer, waiting for I/O if necessary
2987 wait_for_write(NOBLOCK
);
2988 while (bufhead
->next
== NULL
)
2989 wait_for_write(BLOCK
);
2992 * Take the buffer off the list
2994 pbuf
= bufhead
->next
;
2995 bufhead
->next
= pbuf
->next
;
2999 * return the empty buffer space just past the header
3001 return ((char *)pbuf
+ bufhdrsize
);
3005 * freebuf() -- Free a buffer gotten previously through getbuf.
3006 * Puts the buffer back on the appropriate list for
3007 * later use. Never calls free().
3009 * Assumes that SIGINT is blocked.
3018 * get the header for this buffer
3020 pbuf
= (bufhdr
*)(buf
- bufhdrsize
);
3023 * Put it back on the list of available buffers
3025 bufhead
= pbuf
->head
;
3026 pbuf
->next
= bufhead
->next
;
3027 bufhead
->next
= pbuf
;
3031 * freetrans() -- Free a transaction gotten previously through getaiop.
3032 * Puts the transaction struct back on the appropriate list for
3033 * later use. Never calls free().
3035 * Assumes that SIGINT is blocked.
3038 freetrans(aio_trans
*transp
)
3041 * free the buffer associated with this AIO if needed
3043 if (transp
->release
== RELEASE
)
3044 freebuf(transp
->buffer
);
3047 * Put transaction on the free list
3049 transp
->next
= results
.trans
;
3050 results
.trans
= transp
;
3054 * wait_for_write() -- Wait for an aio write to complete. Return
3055 * the transaction structure for that write.
3057 * Blocks SIGINT if necessary.
3060 wait_for_write(int block
)
3063 aio_result_t
*resultp
;
3064 static struct timeval zero_wait
= { 0, 0 };
3068 * If we know there aren't any outstanding transactions, just return
3070 if (results
.outstanding
== 0)
3071 return ((aio_trans
*) 0);
3073 block_sigint(&old_mask
);
3075 resultp
= aiowait(block
? NULL
: &zero_wait
);
3076 if (resultp
== NULL
||
3077 (resultp
== (aio_result_t
*)-1 && errno
== EINVAL
)) {
3078 unblock_sigint(&old_mask
);
3079 return ((aio_trans
*) 0);
3082 results
.outstanding
--;
3083 transp
= (aio_trans
*)resultp
;
3085 if (resultp
->aio_return
!= transp
->size
) {
3086 if (resultp
->aio_return
== -1) {
3088 * The aiowrite() may have failed because the
3089 * kernel didn't have enough memory to do the job.
3090 * Flush all pending writes and try a normal
3091 * write(). wtfs_breakup() will call exit if it
3092 * fails, so we don't worry about errors here.
3095 wtfs_breakup(transp
->bno
, transp
->size
, transp
->buffer
);
3097 (void) fprintf(stderr
, gettext(
3098 "short write (%d of %d bytes) on sector %lld\n"),
3099 resultp
->aio_return
, transp
->size
,
3102 * Don't unblock SIGINT, to avoid potential
3103 * looping due to queued interrupts and
3110 resultp
->aio_return
= 0;
3112 unblock_sigint(&old_mask
);
3117 * flush_writes() -- flush all the outstanding aio writes.
3122 while (wait_for_write(BLOCK
))
3127 * get_aiop() -- find and return an aio_trans structure on which a new
3128 * aio can be done. Blocks on aiowait() if needed. Reaps
3129 * all outstanding completed aio's.
3131 * Assumes that SIGINT is blocked.
3141 * initialize aio stuff
3146 results
.maxpend
= 0;
3147 results
.outstanding
= 0;
3148 results
.max
= MAXAIO
;
3150 results
.trans
= (aio_trans
*)calloc(results
.max
,
3151 sizeof (aio_trans
));
3152 if (results
.trans
== NULL
) {
3158 * Initialize the linked list of aio transaction
3159 * structures. Note that the final "next" pointer
3160 * will be NULL since we got the buffer from calloc().
3162 prev
= results
.trans
;
3163 for (i
= 1; i
< results
.max
; i
++) {
3164 prev
->next
= &(results
.trans
[i
]);
3169 wait_for_write(NOBLOCK
);
3170 while (results
.trans
== NULL
)
3171 wait_for_write(BLOCK
);
3172 transp
= results
.trans
;
3173 results
.trans
= results
.trans
->next
;
3176 transp
->resultbuf
.aio_return
= AIO_INPROGRESS
;
3181 * read a block from the file system
3184 rdfs(diskaddr_t bno
, int size
, char *bf
)
3189 * In case we need any data that's pending in an aiowrite(),
3190 * we wait for them all to complete before doing a read.
3195 * Note: the llseek() can succeed, even if the offset is out of range.
3196 * It's not until the file i/o operation (the read()) that one knows
3197 * for sure if the raw device can handle the offset.
3199 if (llseek(fsi
, (offset_t
)bno
* sectorsize
, 0) < 0) {
3201 (void) fprintf(stderr
,
3202 gettext("seek error on sector %lld: %s\n"),
3203 bno
, strerror(saverr
));
3206 n
= read(fsi
, bf
, size
);
3210 (void) fprintf(stderr
,
3211 gettext("read error on sector %lld: %s\n"),
3212 bno
, strerror(saverr
));
3214 (void) fprintf(stderr
, gettext(
3215 "short read (%d of %d bytes) on sector %lld\n"),
3222 * write a block to the file system
3225 wtfs(diskaddr_t bno
, int size
, char *bf
)
3233 * Note: the llseek() can succeed, even if the offset is out of range.
3234 * It's not until the file i/o operation (the write()) that one knows
3235 * for sure if the raw device can handle the offset.
3237 if (llseek(fso
, (offset_t
)bno
* sectorsize
, 0) < 0) {
3239 (void) fprintf(stderr
,
3240 gettext("seek error on sector %lld: %s\n"),
3241 bno
, strerror(saverr
));
3246 n
= write(fso
, bf
, size
);
3250 (void) fprintf(stderr
,
3251 gettext("write error on sector %lld: %s\n"),
3252 bno
, strerror(saverr
));
3254 (void) fprintf(stderr
, gettext(
3255 "short write (%d of %d bytes) on sector %lld\n"),
3262 * write a block to the file system -- buffered with aio
3265 awtfs(diskaddr_t bno
, int size
, char *bf
, int release
)
3275 * We need to keep things consistent if we get interrupted,
3276 * so defer any expected interrupts for the time being.
3278 block_sigint(&old_mask
);
3281 if (release
== RELEASE
)
3284 transp
= get_aiop();
3286 transp
->buffer
= bf
;
3287 transp
->size
= size
;
3288 transp
->release
= release
;
3290 n
= aiowrite(fso
, bf
, size
, (off_t
)bno
* sectorsize
,
3291 SEEK_SET
, &transp
->resultbuf
);
3295 * The aiowrite() may have failed because the
3296 * kernel didn't have enough memory to do the job.
3297 * Flush all pending writes and try a normal
3298 * write(). wtfs_breakup() will call exit if it
3299 * fails, so we don't worry about errors here.
3302 wtfs_breakup(transp
->bno
, transp
->size
, transp
->buffer
);
3306 * Keep track of our pending writes.
3308 results
.outstanding
++;
3309 if (results
.outstanding
> results
.maxpend
)
3310 results
.maxpend
= results
.outstanding
;
3314 unblock_sigint(&old_mask
);
3319 * write a block to the file system, but break it up into sbsize
3320 * chunks to avoid forcing a large amount of memory to be locked down.
3321 * Only used as a fallback when an aio write has failed.
3324 wtfs_breakup(diskaddr_t bno
, int size
, char *bf
)
3328 int block_incr
= sbsize
/ sectorsize
;
3338 * Note: the llseek() can succeed, even if the offset is
3339 * out of range. It's not until the file i/o operation
3340 * (the write()) that one knows for sure if the raw device
3341 * can handle the offset.
3343 if (llseek(fso
, (offset_t
)bno
* sectorsize
, 0) < 0) {
3345 (void) fprintf(stderr
,
3346 gettext("seek error on sector %lld: %s\n"),
3347 bno
, strerror(saverr
));
3351 n
= write(fso
, bf
, wsize
);
3354 (void) fprintf(stderr
,
3355 gettext("write error on sector %lld: %s\n"),
3356 bno
, strerror(saverr
));
3361 (void) fprintf(stderr
, gettext(
3362 "short write (%d of %d bytes) on sector %lld\n"),
3377 * check if a block is available
3380 isblock(struct fs
*fs
, unsigned char *cp
, int h
)
3384 switch (fs
->fs_frag
) {
3386 return (cp
[h
] == 0xff);
3388 mask
= 0x0f << ((h
& 0x1) << 2);
3389 return ((cp
[h
>> 1] & mask
) == mask
);
3391 mask
= 0x03 << ((h
& 0x3) << 1);
3392 return ((cp
[h
>> 2] & mask
) == mask
);
3394 mask
= 0x01 << (h
& 0x7);
3395 return ((cp
[h
>> 3] & mask
) == mask
);
3397 (void) fprintf(stderr
, "isblock bad fs_frag %d\n", fs
->fs_frag
);
3403 * take a block out of the map
3406 clrblock(struct fs
*fs
, unsigned char *cp
, int h
)
3408 switch ((fs
)->fs_frag
) {
3413 cp
[h
>> 1] &= ~(0x0f << ((h
& 0x1) << 2));
3416 cp
[h
>> 2] &= ~(0x03 << ((h
& 0x3) << 1));
3419 cp
[h
>> 3] &= ~(0x01 << (h
& 0x7));
3422 (void) fprintf(stderr
,
3423 gettext("clrblock: bad fs_frag value %d\n"), fs
->fs_frag
);
3429 * put a block into the map
3432 setblock(struct fs
*fs
, unsigned char *cp
, int h
)
3434 switch (fs
->fs_frag
) {
3439 cp
[h
>> 1] |= (0x0f << ((h
& 0x1) << 2));
3442 cp
[h
>> 2] |= (0x03 << ((h
& 0x3) << 1));
3445 cp
[h
>> 3] |= (0x01 << (h
& 0x7));
3448 (void) fprintf(stderr
,
3449 gettext("setblock: bad fs_frag value %d\n"), fs
->fs_frag
);
3457 (void) fprintf(stderr
,
3458 gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] "
3459 "special " /* param 0 */
3460 "size(sectors) \\ \n")); /* param 1 */
3461 (void) fprintf(stderr
,
3462 "[nsect " /* param 2 */
3463 "ntrack " /* param 3 */
3464 "bsize " /* param 4 */
3465 "fragsize " /* param 5 */
3466 "cpg " /* param 6 */
3467 "free " /* param 7 */
3468 "rps " /* param 8 */
3469 "nbpi " /* param 9 */
3470 "opt " /* param 10 */
3471 "apc " /* param 11 */
3472 "gap " /* param 12 */
3473 "nrpos " /* param 13 */
3474 "maxcontig " /* param 14 */
3475 "mtb]\n"); /* param 15 */
3476 (void) fprintf(stderr
,
3477 gettext(" -m : dump fs cmd line used to make this partition\n"
3478 " -V :print this command line and return\n"
3479 " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n"
3480 " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n"
3481 " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n"
3482 " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n"
3483 "NOTE that all -o suboptions: must be separated only by commas so as to\n"
3484 "be parsed as a single argument\n"),
3485 nsect
, ntrack
, bsize
, fragsize
, cpg
, sblock
.fs_minfree
, rps
,
3486 nbpi
, opt
, apc
, (rotdelay
== -1) ? 0 : rotdelay
,
3487 sblock
.fs_nrpos
, maxcontig
, mtb
);
3493 dump_fscmd(char *fsys
, int fsi
)
3495 int64_t used
, bpcg
, inospercg
;
3499 bzero((char *)&sblock
, sizeof (sblock
));
3500 rdfs((diskaddr_t
)SBLOCK
, SBSIZE
, (char *)&sblock
);
3503 * ensure a valid file system and if not, exit with error or else
3504 * we will end up computing block numbers etc and dividing by zero
3505 * which will cause floating point errors in this routine.
3508 if ((sblock
.fs_magic
!= FS_MAGIC
) &&
3509 (sblock
.fs_magic
!= MTB_UFS_MAGIC
)) {
3510 (void) fprintf(stderr
, gettext(
3511 "[not currently a valid file system - bad superblock]\n"));
3515 if (sblock
.fs_magic
== FS_MAGIC
&&
3516 (sblock
.fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
3517 sblock
.fs_version
!= UFS_VERSION_MIN
)) {
3518 (void) fprintf(stderr
, gettext(
3519 "Unknown version of UFS format: %d\n"), sblock
.fs_version
);
3523 if (sblock
.fs_magic
== MTB_UFS_MAGIC
&&
3524 (sblock
.fs_version
> MTB_UFS_VERSION_1
||
3525 sblock
.fs_version
< MTB_UFS_VERSION_MIN
)) {
3526 (void) fprintf(stderr
, gettext(
3527 "Unknown version of UFS format: %d\n"), sblock
.fs_version
);
3532 * Compute a reasonable nbpi value.
3533 * The algorithm for "used" is copied from code
3534 * in main() verbatim.
3535 * The nbpi equation is taken from main where the
3536 * fs_ipg value is set for the last time. The INOPB(...) - 1
3537 * is used to account for the roundup.
3538 * The problem is that a range of nbpi values map to
3539 * the same file system layout. So it is not possible
3540 * to calculate the exact value specified when the file
3541 * system was created. So instead we determine the top
3542 * end of the range of values.
3544 bpcg
= sblock
.fs_spc
* sectorsize
;
3545 inospercg
= (int64_t)roundup(bpcg
/ sizeof (struct dinode
),
3547 if (inospercg
> MAXIpG(&sblock
))
3548 inospercg
= MAXIpG(&sblock
);
3550 (sblock
.fs_iblkno
+ inospercg
/ INOPF(&sblock
)) * NSPF(&sblock
);
3552 nbytes64
= (uint64_t)sblock
.fs_cpg
* bpcg
- used
;
3555 * The top end of the range of values for nbpi may not be
3556 * a valid command line value for mkfs. Report the bottom
3559 nbpi
= (int64_t)(nbytes64
/ (sblock
.fs_ipg
));
3561 (void) fprintf(stdout
, gettext("mkfs -F ufs -o "), fsys
);
3562 (void) fprintf(stdout
, "nsect=%d,ntrack=%d,",
3563 sblock
.fs_nsect
, sblock
.fs_ntrak
);
3564 (void) fprintf(stdout
, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,",
3565 sblock
.fs_bsize
, sblock
.fs_fsize
, sblock
.fs_cpg
, sblock
.fs_minfree
);
3566 (void) fprintf(stdout
, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,",
3567 sblock
.fs_rps
, nbpi
, (sblock
.fs_optim
== FS_OPTSPACE
) ? 's' : 't',
3568 (sblock
.fs_ntrak
* sblock
.fs_nsect
) - sblock
.fs_spc
,
3569 sblock
.fs_rotdelay
);
3570 (void) fprintf(stdout
, "nrpos=%d,maxcontig=%d,mtb=%c ",
3571 sblock
.fs_nrpos
, sblock
.fs_maxcontig
,
3572 ((sblock
.fs_magic
== MTB_UFS_MAGIC
) ? 'y' : 'n'));
3573 (void) fprintf(stdout
, "%s %lld\n", fsys
,
3574 fsbtodb(&sblock
, sblock
.fs_size
));
3576 bzero((char *)&sblock
, sizeof (sblock
));
3579 /* number ************************************************************* */
3581 /* Convert a numeric string arg to binary */
3583 /* Args: d_value - default value, if have parse error */
3584 /* param - the name of the argument, for error messages */
3585 /* flags - parser state and what's allowed in the arg */
3586 /* Global arg: string - pointer to command arg */
3588 /* Valid forms: 123 | 123k | 123*123 | 123x123 */
3590 /* Return: converted number */
3592 /* ******************************************************************** */
3595 number(uint64_t d_value
, char *param
, int flags
)
3599 uint64_t cut
= BIG
/ 10; /* limit to avoid overflow */
3607 if ((*cs
< '0') || (*cs
> '9')) {
3611 while ((*cs
>= '0') && (*cs
<= '9') && (n
<= cut
)) {
3612 n
= n
*10 + *cs
++ - '0';
3619 if (flags
& ALLOW_END_ONLY
)
3621 if (n
> (BIG
/ 1024))
3628 if (flags
& ALLOW_END_ONLY
)
3631 t
= number(d_value
, param
, flags
);
3635 cs
= string
+ 1; /* adjust for -- below */
3637 /* recursion has read rest of expression */
3647 if (flags
& ALLOW_END_ONLY
)
3649 if (flags
& ALLOW_PERCENT
) {
3650 flags
&= ~ALLOW_PERCENT
;
3651 flags
|= ALLOW_END_ONLY
;
3657 if (flags
& ALLOW_END_ONLY
)
3659 if (flags
& ALLOW_MS1
) {
3660 flags
&= ~ALLOW_MS1
;
3667 if (flags
& ALLOW_END_ONLY
)
3669 if (flags
& ALLOW_MS2
) {
3670 flags
&= ~ALLOW_MS2
;
3671 flags
|= ALLOW_END_ONLY
;
3676 case '0': case '1': case '2': case '3': case '4':
3677 case '5': case '6': case '7': case '8': case '9':
3679 (void) fprintf(stderr
,
3680 gettext("mkfs: value for %s overflowed\n"),
3682 while ((*cs
!= '\0') && (*cs
!= ','))
3689 (void) fprintf(stderr
, gettext(
3690 "mkfs: bad numeric arg for %s: \"%s\"\n"),
3692 while ((*cs
!= '\0') && (*cs
!= ','))
3695 if (d_value
!= NO_DEFAULT
) {
3696 (void) fprintf(stderr
,
3697 gettext("mkfs: %s reset to default %lld\n"),
3704 } /* never gets here */
3707 /* match ************************************************************** */
3709 /* Compare two text strings for equality */
3711 /* Arg: s - pointer to string to match with a command arg */
3712 /* Global arg: string - pointer to command arg */
3714 /* Return: 1 if match, 0 if no match */
3715 /* If match, also reset `string' to point to the text */
3716 /* that follows the matching text. */
3718 /* ******************************************************************** */
3726 while (*cs
++ == *s
) {
3747 lockexit(int exitstatus
)
3750 /* the probe mode neither changes nor locks the filesystem */
3755 * flush the dirty cylinder group
3757 if (inlockexit
== 0) {
3767 * make sure the file system is unlocked before exiting
3769 if ((inlockexit
== 1) && (!isbad
)) {
3773 * if logging was enabled, then re-enable it
3776 if (rl_log_control(fsys
, _FIOLOGENABLE
) != RL_SUCCESS
) {
3777 (void) fprintf(stderr
, gettext(
3778 "failed to re-enable logging\n"));
3783 (void) fprintf(stderr
, gettext(
3784 "Filesystem is currently inconsistent. It "
3785 "must be repaired with fsck(1M)\nbefore being "
3786 "used. Use the following command to "
3787 "do this:\n\n\tfsck %s\n\n"), fsys
);
3790 (void) fprintf(stderr
, gettext(
3791 "You will be told that the filesystem "
3792 "is already mounted, and asked if you\n"
3793 "wish to continue. Answer `yes' to "
3794 "this question.\n\n"));
3797 (void) fprintf(stderr
, gettext(
3798 "One problem should be reported, that the summary "
3799 "information is bad.\nYou will then be asked if it "
3800 "should be salvaged. Answer `yes' to\nthis "
3806 * In theory, there's no way to get here without
3807 * isbad also being set, but be robust in the
3808 * face of future code changes.
3810 (void) fprintf(stderr
, gettext(
3811 "The filesystem is currently mounted "
3812 "read-only and write-locked. "));
3814 (void) fprintf(stderr
, gettext(
3815 "After\nrunning fsck, unlock the "
3816 "filesystem and "));
3818 (void) fprintf(stderr
, gettext(
3819 "Unlock the filesystem\nand "));
3822 (void) fprintf(stderr
, gettext(
3823 "re-enable writing with\nthe following "
3824 "command:\n\n\tlockfs -u %s\n\n"), directory
);
3838 * always perform fsirand(1) function... newfs will notice that
3839 * the inodes have been randomized and will not call fsirand itself
3841 for (i
= 0, dp
= zino
; i
< sblock
.fs_inopb
; ++i
, ++dp
)
3842 IRANDOMIZE(&dp
->di_ic
);
3846 * Check the size of the summary information.
3847 * Fields in sblock are not changed in this function.
3849 * For an 8K filesystem block, the maximum number of cylinder groups is 16384.
3850 * MAXCSBUFS {32} * 8K {FS block size}
3851 * divided by (sizeof csum) {16}
3853 * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32,
3854 * this is the only place where it's referenced.
3866 uint64_t maxfs_blocks
; /* filesystem blocks for max filesystem size */
3869 * compute the maximum summary info size
3871 dmin
= cgdmin(&sblock
, 0);
3872 dmax
= cgbase(&sblock
, 0) + sblock
.fs_fpg
;
3873 fs_size
= (grow
) ? grow_fs_size
: sblock
.fs_size
;
3876 cg0frags
= dmax
- dmin
;
3877 cg0blocks
= cg0frags
/ sblock
.fs_frag
;
3878 cg0frags
= cg0blocks
* sblock
.fs_frag
;
3879 maxncg
= (longlong_t
)cg0blocks
*
3880 (longlong_t
)(sblock
.fs_bsize
/ sizeof (struct csum
));
3882 maxfs_blocks
= FS_MAX
;
3884 if (maxncg
> ((longlong_t
)maxfs_blocks
/ (longlong_t
)sblock
.fs_fpg
) + 1)
3885 maxncg
= ((longlong_t
)maxfs_blocks
/
3886 (longlong_t
)sblock
.fs_fpg
) + 1;
3888 maxfrags
= maxncg
* (longlong_t
)sblock
.fs_fpg
;
3890 if (maxfrags
> maxfs_blocks
)
3891 maxfrags
= maxfs_blocks
;
3895 * remember for later processing in extendsummaryinfo()
3898 grow_sifrag
= dmin
+ (cg0blocks
* sblock
.fs_frag
);
3900 testfrags
= cg0frags
;
3902 if (testfrags
> cg0frags
) {
3903 (void) fprintf(stderr
,
3904 gettext("Too many test frags (%lld); "
3905 "try %lld\n"), testfrags
, cg0frags
);
3910 * if summary info is too large (too many cg's) tell the user and exit
3912 if ((longlong_t
)sblock
.fs_size
> maxfrags
) {
3913 (void) fprintf(stderr
, gettext(
3914 "Too many cylinder groups with %llu sectors;\n try "
3915 "increasing cgsize, or decreasing fssize to %llu\n"),
3916 fsbtodb(&sblock
, (uint64_t)sblock
.fs_size
),
3917 fsbtodb(&sblock
, (uint64_t)maxfrags
));
3923 * checksblock() has two uses:
3924 * - One is to sanity test the superblock and is used when newfs(1M)
3925 * is invoked with the "-N" option. If any discrepancy was found,
3926 * just return whatever error was found and do not exit.
3927 * - the other use of it is in places where you expect the superblock
3928 * to be sane, and if it isn't, then we exit.
3929 * Which of the above two actions to take is indicated with the second argument.
3933 checksblock(struct fs sb
, int proceed
)
3938 if ((sb
.fs_magic
!= FS_MAGIC
) && (sb
.fs_magic
!= MTB_UFS_MAGIC
)) {
3940 errmsg
= gettext("Bad superblock; magic number wrong\n");
3941 } else if ((sb
.fs_magic
== FS_MAGIC
&&
3942 (sb
.fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
3943 sb
.fs_version
!= UFS_VERSION_MIN
)) ||
3944 (sb
.fs_magic
== MTB_UFS_MAGIC
&&
3945 (sb
.fs_version
> MTB_UFS_VERSION_1
||
3946 sb
.fs_version
< MTB_UFS_VERSION_MIN
))) {
3948 errmsg
= gettext("Unrecognized version of UFS\n");
3949 } else if (sb
.fs_ncg
< 1) {
3951 errmsg
= gettext("Bad superblock; ncg out of range\n");
3952 } else if (sb
.fs_cpg
< 1) {
3954 errmsg
= gettext("Bad superblock; cpg out of range\n");
3955 } else if (sb
.fs_ncg
* sb
.fs_cpg
< sb
.fs_ncyl
||
3956 (sb
.fs_ncg
- 1) * sb
.fs_cpg
>= sb
.fs_ncyl
) {
3958 errmsg
= gettext("Bad superblock; ncyl out of range\n");
3959 } else if (sb
.fs_sbsize
<= 0 || sb
.fs_sbsize
> sb
.fs_bsize
) {
3961 errmsg
= gettext("Bad superblock; superblock size out of "
3966 if (err
) dprintf(("%s", errmsg
));
3971 fprintf(stderr
, "%s", errmsg
);
3978 * Roll the embedded log, if any, and set up the global variables
3979 * islog and islogok.
3982 logsetup(char *devstr
)
3985 extent_block_t
*ebp
;
3990 * Does the superblock indicate that we are supposed to have a log ?
3992 if (sblock
.fs_logbno
== 0) {
3994 * No log present, nothing to do.
4001 * There's a log in a yet unknown state, attempt to roll it.
4006 * We failed to roll the log, bail out.
4008 if (rl_roll_log(devstr
) != RL_SUCCESS
)
4013 /* log is not okay; check the fs */
4014 if ((FSOKAY
!= (sblock
.fs_state
+ sblock
.fs_time
)) ||
4015 (sblock
.fs_clean
!= FSLOG
))
4018 /* get the log allocation block */
4019 buf
= (void *)malloc(DEV_BSIZE
);
4023 ud_buf
= (void *)malloc(DEV_BSIZE
);
4024 if (ud_buf
== NULL
) {
4029 rdfs((diskaddr_t
)logbtodb(&sblock
, sblock
.fs_logbno
),
4031 ebp
= (extent_block_t
*)buf
;
4033 /* log allocation block is not okay; check the fs */
4034 if (ebp
->type
!= LUFS_EXTENTS
) {
4040 /* get the log state block(s) */
4041 rdfs((diskaddr_t
)logbtodb(&sblock
, ebp
->extents
[0].pbno
),
4043 ud
= (ml_odunit_t
*)ud_buf
;
4044 ul
= (ml_unit_t
*)malloc(sizeof (*ul
));
4045 ul
->un_ondisk
= *ud
;
4047 /* log state is okay */
4048 if ((ul
->un_chksum
== ul
->un_head_ident
+ ul
->un_tail_ident
) &&
4049 (ul
->un_version
== LUFS_VERSION_LATEST
) &&
4050 (ul
->un_badlog
== 0))
4059 growinit(char *devstr
)
4062 char buf
[DEV_BSIZE
];
4065 * Read and verify the superblock
4067 rdfs((diskaddr_t
)(SBOFF
/ sectorsize
), (int)sbsize
, (char *)&sblock
);
4068 (void) checksblock(sblock
, 0);
4069 if (sblock
.fs_postblformat
!= FS_DYNAMICPOSTBLFMT
) {
4070 (void) fprintf(stderr
,
4071 gettext("old file system format; can't growfs\n"));
4076 * can't shrink a file system
4078 grow_fssize
= fsbtodb(&sblock
, (uint64_t)sblock
.fs_size
);
4079 if (fssize_db
< grow_fssize
) {
4080 (void) fprintf(stderr
,
4081 gettext("%lld sectors < current size of %lld sectors\n"),
4082 fssize_db
, grow_fssize
);
4087 * can't grow a system to over a terabyte unless it was set up
4088 * as an MTB UFS file system.
4090 if (mtb
== 'y' && sblock
.fs_magic
!= MTB_UFS_MAGIC
) {
4091 if (fssize_db
>= SECTORS_PER_TERABYTE
) {
4092 (void) fprintf(stderr
, gettext(
4093 "File system was not set up with the multi-terabyte format.\n"));
4094 (void) fprintf(stderr
, gettext(
4095 "Its size cannot be increased to a terabyte or more.\n"));
4097 (void) fprintf(stderr
, gettext(
4098 "Cannot convert file system to multi-terabyte format.\n"));
4106 * can't growfs when logging device has errors
4108 if ((islog
&& !islogok
) ||
4109 ((FSOKAY
== (sblock
.fs_state
+ sblock
.fs_time
)) &&
4110 (sblock
.fs_clean
== FSLOG
&& !islog
))) {
4111 (void) fprintf(stderr
,
4112 gettext("logging device has errors; can't growfs\n"));
4117 * disable ufs logging for growing
4120 if (rl_log_control(devstr
, _FIOLOGDISABLE
) != RL_SUCCESS
) {
4121 (void) fprintf(stderr
, gettext(
4122 "failed to disable logging\n"));
4130 * if mounted write lock the file system to be grown
4136 * refresh dynamic superblock state - disabling logging will have
4137 * changed the amount of free space available in the file system
4139 rdfs((diskaddr_t
)(SBOFF
/ sectorsize
), sbsize
, (char *)&sblock
);
4142 * make sure device is big enough
4144 rdfs((diskaddr_t
)fssize_db
- 1, DEV_BSIZE
, buf
);
4145 wtfs((diskaddr_t
)fssize_db
- 1, DEV_BSIZE
, buf
);
4148 * read current summary information
4150 grow_fscs
= read_summaryinfo(&sblock
);
4153 * save some current size related fields from the superblock
4154 * These are used in extendsummaryinfo()
4156 grow_fs_size
= sblock
.fs_size
;
4157 grow_fs_ncg
= sblock
.fs_ncg
;
4158 grow_fs_csaddr
= (diskaddr_t
)sblock
.fs_csaddr
;
4159 grow_fs_cssize
= sblock
.fs_cssize
;
4162 * save and reset the clean flag
4164 if (FSOKAY
== (sblock
.fs_state
+ sblock
.fs_time
))
4165 grow_fs_clean
= sblock
.fs_clean
;
4167 grow_fs_clean
= FSBAD
;
4168 sblock
.fs_clean
= FSBAD
;
4169 sblock
.fs_state
= FSOKAY
- sblock
.fs_time
;
4171 wtfs((diskaddr_t
)(SBOFF
/ sectorsize
), sbsize
, (char *)&sblock
);
4175 checkdev(char *rdev
, char *bdev
)
4177 struct stat64 statarea
;
4179 if (stat64(bdev
, &statarea
) < 0) {
4180 (void) fprintf(stderr
, gettext("can't check mount point; "));
4181 (void) fprintf(stderr
, gettext("can't stat %s\n"), bdev
);
4184 if ((statarea
.st_mode
& S_IFMT
) != S_IFBLK
) {
4185 (void) fprintf(stderr
, gettext(
4186 "can't check mount point; %s is not a block device\n"),
4190 if (stat64(rdev
, &statarea
) < 0) {
4191 (void) fprintf(stderr
, gettext("can't stat %s\n"), rdev
);
4194 if ((statarea
.st_mode
& S_IFMT
) != S_IFCHR
) {
4195 (void) fprintf(stderr
,
4196 gettext("%s is not a character device\n"), rdev
);
4202 checkmount(struct mnttab
*mntp
, char *bdevname
)
4204 struct stat64 statdir
;
4205 struct stat64 statdev
;
4207 if (strcmp(bdevname
, mntp
->mnt_special
) == 0) {
4208 if (stat64(mntp
->mnt_mountp
, &statdir
) == -1) {
4209 (void) fprintf(stderr
, gettext("can't stat %s\n"),
4213 if (stat64(mntp
->mnt_special
, &statdev
) == -1) {
4214 (void) fprintf(stderr
, gettext("can't stat %s\n"),
4218 if (statdir
.st_dev
!= statdev
.st_rdev
) {
4219 (void) fprintf(stderr
, gettext(
4220 "%s is not mounted on %s; mnttab(4) wrong\n"),
4221 mntp
->mnt_special
, mntp
->mnt_mountp
);
4226 if (strcmp(mntp
->mnt_mountp
, directory
) != 0) {
4227 (void) fprintf(stderr
,
4228 gettext("%s is mounted on %s, not %s\n"),
4229 bdevname
, mntp
->mnt_mountp
, directory
);
4234 (void) fprintf(stderr
, gettext(
4235 "%s is mounted on %s; can't growfs\n"),
4236 bdevname
, mntp
->mnt_mountp
);
4238 (void) fprintf(stderr
,
4239 gettext("%s is mounted, can't mkfs\n"),
4246 struct dinode
*dibuf
= 0;
4247 diskaddr_t difrag
= 0;
4253 * read the block of inodes containing inode number ino
4256 dibuf
= (struct dinode
*)malloc((unsigned)sblock
.fs_bsize
);
4257 if (itod(&sblock
, ino
) != difrag
) {
4258 difrag
= itod(&sblock
, ino
);
4259 rdfs(fsbtodb(&sblock
, (uint64_t)difrag
), (int)sblock
.fs_bsize
,
4262 return (dibuf
+ (ino
% INOPB(&sblock
)));
4266 * structure that manages the frags we need for extended summary info
4267 * These frags can be:
4273 struct csfrag
*next
; /* next entry */
4274 daddr32_t ofrag
; /* old frag */
4275 daddr32_t nfrag
; /* new frag */
4276 long cylno
; /* cylno of nfrag */
4277 long frags
; /* number of frags */
4278 long size
; /* size in bytes */
4279 ino_t ino
; /* inode number */
4280 long fixed
; /* Boolean - Already fixed? */
4282 struct csfrag
*csfrag
; /* state unknown */
4283 struct csfrag
*csfragino
; /* frags belonging to an inode */
4284 struct csfrag
*csfragfree
; /* frags that are free */
4286 daddr32_t maxcsfrag
= 0; /* maximum in range */
4287 daddr32_t mincsfrag
= 0x7fffffff; /* minimum in range */
4290 csfraginrange(daddr32_t frag
)
4292 return ((frag
>= mincsfrag
) && (frag
<= maxcsfrag
));
4296 findcsfrag(daddr32_t frag
, struct csfrag
**cfap
)
4300 if (!csfraginrange(frag
))
4303 for (cfp
= *cfap
; cfp
; cfp
= cfp
->next
)
4304 if (cfp
->ofrag
== frag
)
4310 checkindirect(ino_t ino
, daddr32_t
*fragsp
, daddr32_t frag
, int level
)
4313 int ne
= sblock
.fs_bsize
/ sizeof (daddr32_t
);
4314 daddr32_t fsb
[MAXBSIZE
/ sizeof (daddr32_t
)];
4319 rdfs(fsbtodb(&sblock
, frag
), (int)sblock
.fs_bsize
,
4322 checkdirect(ino
, fragsp
, fsb
, sblock
.fs_bsize
/ sizeof (daddr32_t
));
4325 for (i
= 0; i
< ne
&& *fragsp
; ++i
)
4326 checkindirect(ino
, fragsp
, fsb
[i
], level
-1);
4330 addcsfrag(ino_t ino
, daddr32_t frag
, struct csfrag
**cfap
)
4332 struct csfrag
*cfp
, *curr
, *prev
;
4335 * establish a range for faster checking in csfraginrange()
4337 if (frag
> maxcsfrag
)
4339 if (frag
< mincsfrag
)
4343 * if this frag belongs to an inode and is not the start of a block
4344 * then see if it is part of a frag range for this inode
4346 if (ino
&& (frag
% sblock
.fs_frag
))
4347 for (cfp
= *cfap
; cfp
; cfp
= cfp
->next
) {
4348 if (ino
!= cfp
->ino
)
4350 if (frag
!= cfp
->ofrag
+ cfp
->frags
)
4353 cfp
->size
+= sblock
.fs_fsize
;
4357 * allocate a csfrag entry and insert it in an increasing order into the
4360 cfp
= (struct csfrag
*)calloc(1, sizeof (struct csfrag
));
4364 cfp
->size
= sblock
.fs_fsize
;
4365 for (prev
= NULL
, curr
= *cfap
; curr
!= NULL
;
4366 prev
= curr
, curr
= curr
->next
) {
4367 if (frag
< curr
->ofrag
) {
4370 prev
->next
= cfp
; /* middle element */
4372 *cfap
= cfp
; /* first element */
4375 if (curr
->next
== NULL
) {
4376 curr
->next
= cfp
; /* last element */
4380 if (*cfap
== NULL
) /* will happen only once */
4385 delcsfrag(daddr32_t frag
, struct csfrag
**cfap
)
4388 struct csfrag
**cfpp
;
4391 * free up entry whose beginning frag matches
4393 for (cfpp
= cfap
; *cfpp
; cfpp
= &(*cfpp
)->next
) {
4394 if (frag
== (*cfpp
)->ofrag
) {
4396 *cfpp
= (*cfpp
)->next
;
4404 * See whether any of the direct blocks in the array pointed by "db" and of
4405 * length "ne" are within the range of frags needed to extend the cylinder
4406 * summary. If so, remove those frags from the "as-yet-unclassified" list
4407 * (csfrag) and add them to the "owned-by-inode" list (csfragino).
4408 * For each such frag found, decrement the frag count pointed to by fragsp.
4409 * "ino" is the inode that contains (either directly or indirectly) the frags
4413 checkdirect(ino_t ino
, daddr32_t
*fragsp
, daddr32_t
*db
, int ne
)
4421 * scan for allocation within the new summary info range
4423 for (i
= 0; i
< ne
&& *fragsp
; ++i
) {
4424 if ((frag
= *db
++) != 0) {
4426 for (j
= 0; j
< sblock
.fs_frag
&& *fragsp
; ++j
) {
4427 if (found
|| (found
= csfraginrange(frag
))) {
4428 addcsfrag(ino
, frag
, &csfragino
);
4429 delcsfrag(frag
, &csfrag
);
4447 * scan all old inodes looking for allocations in the new
4448 * summary info range. Move the affected frag from the
4449 * generic csfrag list onto the `owned-by-inode' list csfragino.
4451 for (i
= UFSROOTINO
; i
< grow_fs_ncg
*sblock
.fs_ipg
&& csfrag
; ++i
) {
4452 dp
= gdinode((ino_t
)i
);
4453 switch (dp
->di_mode
& IFMT
) {
4461 frags
= dbtofsb(&sblock
, dp
->di_blocks
);
4463 checkdirect((ino_t
)i
, &frags
, &dp
->di_db
[0], NDADDR
+NIADDR
);
4464 for (j
= 0; j
< NIADDR
&& frags
; ++j
) {
4465 /* Negate the block if its an fallocate'd block */
4466 if (dp
->di_ib
[j
] < 0 && dp
->di_ib
[j
] != UFS_HOLE
)
4467 checkindirect((ino_t
)i
, &frags
,
4468 -(dp
->di_ib
[j
]), j
);
4470 checkindirect((ino_t
)i
, &frags
,
4477 fixindirect(daddr32_t frag
, int level
)
4480 int ne
= sblock
.fs_bsize
/ sizeof (daddr32_t
);
4481 daddr32_t fsb
[MAXBSIZE
/ sizeof (daddr32_t
)];
4486 rdfs(fsbtodb(&sblock
, (uint64_t)frag
), (int)sblock
.fs_bsize
,
4489 fixdirect((caddr_t
)fsb
, frag
, fsb
, ne
);
4492 for (i
= 0; i
< ne
; ++i
)
4493 fixindirect(fsb
[i
], level
-1);
4497 fixdirect(caddr_t bp
, daddr32_t frag
, daddr32_t
*db
, int ne
)
4502 for (i
= 0; i
< ne
; ++i
, ++db
) {
4505 if ((cfp
= findcsfrag(*db
, &csfragino
)) == NULL
)
4509 wtfs(fsbtodb(&sblock
, (uint64_t)frag
), (int)sblock
.fs_bsize
,
4521 for (cfp
= csfragino
; cfp
; cfp
= cfp
->next
) {
4524 dp
= gdinode((ino_t
)cfp
->ino
);
4525 fixdirect((caddr_t
)dibuf
, difrag
, dp
->di_db
, NDADDR
+NIADDR
);
4526 for (i
= 0; i
< NIADDR
; ++i
)
4527 fixindirect(dp
->di_ib
[i
], i
);
4532 * Read the cylinders summary information specified by settings in the
4533 * passed 'fs' structure into a new allocated array of csum structures.
4534 * The caller is responsible for freeing the returned array.
4535 * Return a pointer to an array of csum structures.
4537 static struct csum
*
4538 read_summaryinfo(struct fs
*fsp
)
4543 if ((csp
= malloc((size_t)fsp
->fs_cssize
)) == NULL
) {
4544 (void) fprintf(stderr
, gettext("cannot create csum list,"
4545 " not enough memory\n"));
4549 for (i
= 0; i
< fsp
->fs_cssize
; i
+= fsp
->fs_bsize
) {
4551 (uint64_t)(fsp
->fs_csaddr
+ numfrags(fsp
, i
))),
4552 (int)(fsp
->fs_cssize
- i
< fsp
->fs_bsize
?
4553 fsp
->fs_cssize
- i
: fsp
->fs_bsize
), ((caddr_t
)csp
) + i
);
4560 * Check the allocation of fragments that are to be made part of a csum block.
4561 * A fragment is allocated if it is either in the csfragfree list or, it is
4562 * in the csfragino list and has new frags associated with it.
4563 * Return the number of allocated fragments.
4566 checkfragallocated(daddr32_t frag
)
4570 * Since the lists are sorted we can break the search if the asked
4571 * frag is smaller then the one in the list.
4573 for (cfp
= csfragfree
; cfp
!= NULL
&& frag
>= cfp
->ofrag
;
4575 if (frag
== cfp
->ofrag
)
4578 for (cfp
= csfragino
; cfp
!= NULL
&& frag
>= cfp
->ofrag
;
4580 if (frag
== cfp
->ofrag
&& cfp
->nfrag
!= 0)
4581 return (cfp
->frags
);
4588 * Figure out how much the filesystem can be grown. The limiting factor is
4589 * the available free space needed to extend the cg summary info block.
4590 * The free space is determined in three steps:
4591 * - Try to extend the cg summary block to the required size.
4592 * - Find free blocks in last cg.
4593 * - Find free space in the last already allocated fragment of the summary info
4594 * block, and use it for additional csum structures.
4595 * Return the maximum size of the new filesystem or 0 if it can't be grown.
4596 * Please note that this function leaves the global list pointers csfrag,
4597 * csfragfree, and csfragino initialized, and the caller is responsible for
4598 * freeing the lists.
4603 /* fragments by which the csum block can be extended. */
4604 int64_t growth_csum_frags
= 0;
4605 /* fragments by which the filesystem can be extended. */
4606 int64_t growth_fs_frags
= 0;
4607 int64_t new_fs_cssize
; /* size of csum blk in the new FS */
4608 int64_t new_fs_ncg
; /* number of cg in the new FS */
4610 daddr32_t oldfrag_daddr
;
4611 daddr32_t newfrag_daddr
;
4616 * read and verify the superblock
4618 rdfs((diskaddr_t
)(SBOFF
/ sectorsize
), (int)sbsize
, (char *)&sblock
);
4619 (void) checksblock(sblock
, 0);
4622 * check how much we can extend the cg summary info block
4626 * read current summary information
4628 fscs
= read_summaryinfo(&sblock
);
4631 * build list of frags needed for cg summary info block extension
4633 oldfrag_daddr
= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
) +
4635 new_fs_ncg
= howmany(dbtofsb(&sblock
, fssize_db
), sblock
.fs_fpg
);
4636 new_fs_cssize
= fragroundup(&sblock
, new_fs_ncg
* sizeof (struct csum
));
4637 newfrag_daddr
= howmany(new_fs_cssize
, sblock
.fs_fsize
) +
4640 * add all of the frags that are required to grow the cyl summary to the
4641 * csfrag list, which is the generic/unknown list, since at this point
4642 * we don't yet know the state of those frags.
4644 for (daddr
= oldfrag_daddr
; daddr
< newfrag_daddr
; daddr
++)
4645 addcsfrag((ino_t
)0, daddr
, &csfrag
);
4648 * filter free fragments and allocate them. Note that the free frags
4649 * must be allocated first otherwise they could be grabbed by
4650 * alloccsfragino() for data frags.
4656 * filter fragments owned by inodes and allocate them
4658 grow_fs_ncg
= sblock
.fs_ncg
; /* findcsfragino() needs this glob. var. */
4662 if (notenoughspace()) {
4664 * check how many consecutive fragments could be allocated
4668 for (daddr
= oldfrag_daddr
; daddr
< newfrag_daddr
;
4669 daddr
+= tmp_frags
) {
4670 if ((tmp_frags
= checkfragallocated(daddr
)) > 0)
4671 growth_csum_frags
+= tmp_frags
;
4677 * We have all we need for the new desired size,
4678 * so clean up and report back.
4684 * given the number of fragments by which the csum block can be grown
4685 * compute by how many new fragments the FS can be increased.
4686 * It is the number of csum instances per fragment multiplied by
4687 * `growth_csum_frags' and the number of fragments per cylinder group.
4689 growth_fs_frags
= howmany(sblock
.fs_fsize
, sizeof (struct csum
)) *
4690 growth_csum_frags
* sblock
.fs_fpg
;
4693 * compute free fragments in the last cylinder group
4695 rdcg(sblock
.fs_ncg
- 1);
4696 growth_fs_frags
+= sblock
.fs_fpg
- acg
.cg_ndblk
;
4699 * compute how many csum instances are unused in the old csum block.
4700 * For each unused csum instance the FS can be grown by one cylinder
4701 * group without extending the csum block.
4703 spare_csum
= howmany(sblock
.fs_cssize
, sizeof (struct csum
)) -
4706 growth_fs_frags
+= spare_csum
* sblock
.fs_fpg
;
4709 * recalculate the new filesystem size in sectors, shorten it by
4710 * the requested size `fssize_db' if necessary.
4712 if (growth_fs_frags
> 0) {
4714 sect
= (sblock
.fs_size
+ growth_fs_frags
) * sblock
.fs_nspf
;
4715 return ((sect
> fssize_db
) ? fssize_db
: sect
);
4725 int localtest
= test
;
4731 * if no-write (-N), don't bother
4739 * summary info did not change size -- do nothing unless in test mode
4741 if (grow_fs_cssize
== sblock
.fs_cssize
)
4746 * build list of frags needed for additional summary information
4748 oldfrag
= howmany(grow_fs_cssize
, sblock
.fs_fsize
) + grow_fs_csaddr
;
4749 newfrag
= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
) + grow_fs_csaddr
;
4751 * add all of the frags that are required to grow the cyl summary to the
4752 * csfrag list, which is the generic/unknown list, since at this point
4753 * we don't yet know the state of those frags.
4755 for (i
= oldfrag
, frags
= 0; i
< newfrag
; ++i
, ++frags
)
4756 addcsfrag((ino_t
)0, (diskaddr_t
)i
, &csfrag
);
4758 * reduce the number of data blocks in the file system (fs_dsize) by
4759 * the number of frags that need to be added to the cyl summary
4761 sblock
.fs_dsize
-= (newfrag
- oldfrag
);
4764 * In test mode, we move more data than necessary from
4765 * cylinder group 0. The lookup/allocate/move code can be
4766 * better stressed without having to create HUGE file systems.
4769 for (i
= newfrag
; i
< grow_sifrag
; ++i
) {
4770 if (frags
>= testfrags
)
4773 addcsfrag((ino_t
)0, (diskaddr_t
)i
, &csfrag
);
4777 * move frags to free or inode lists, depending on owner
4783 * if not all frags can be located, file system must be inconsistent
4786 isbad
= 1; /* should already be set, but make sure */
4791 * allocate the free frags. Note that the free frags must be allocated
4792 * first otherwise they could be grabbed by alloccsfragino() for data
4797 * allocate extra space for inode frags
4804 if (notenoughspace()) {
4805 unalloccsfragfree();
4807 if (localtest
&& !testforce
) {
4811 (void) fprintf(stderr
, gettext("Not enough free space\n"));
4812 lockexit(NOTENOUGHSPACE
);
4816 * copy the data from old frags to new frags
4821 * fix the inodes to point to the new frags
4826 * We may have moved more frags than we needed. Free them.
4829 for (i
= newfrag
; i
<= maxcsfrag
; ++i
)
4830 setbit(cg_blksfree(&acg
), i
-cgbase(&sblock
, 0));
4837 * Check if all fragments in the `csfragino' list were reallocated.
4845 * If any element in the csfragino array has a "new frag location"
4846 * of 0, the allocfrags() function was unsuccessful in allocating
4847 * space for moving the frag represented by this array element.
4849 for (cfp
= csfragino
; cfp
; cfp
= cfp
->next
)
4850 if (cfp
->nfrag
== 0)
4860 while ((cfp
= csfragino
) != NULL
) {
4862 freefrags(cfp
->nfrag
, cfp
->frags
, cfp
->cylno
);
4863 delcsfrag(cfp
->ofrag
, &csfragino
);
4872 while ((cfp
= csfragfree
) != NULL
) {
4873 freefrags(cfp
->ofrag
, cfp
->frags
, cfp
->cylno
);
4874 delcsfrag(cfp
->ofrag
, &csfragfree
);
4879 * For each frag in the "as-yet-unclassified" list (csfrag), see if
4880 * it's free (i.e., its bit is set in the free frag bit map). If so,
4881 * move it from the "as-yet-unclassified" list to the csfragfree list.
4887 struct csfrag
*cfpnext
;
4890 * move free frags onto the free-frag list
4893 for (cfp
= csfrag
; cfp
; cfp
= cfpnext
) {
4894 cfpnext
= cfp
->next
;
4895 if (isset(cg_blksfree(&acg
), cfp
->ofrag
- cgbase(&sblock
, 0))) {
4896 addcsfrag(cfp
->ino
, cfp
->ofrag
, &csfragfree
);
4897 delcsfrag(cfp
->ofrag
, &csfrag
);
4909 * copy data from old frags to newly allocated frags
4911 for (cfp
= csfragino
; cfp
; cfp
= cfp
->next
) {
4912 rdfs(fsbtodb(&sblock
, (uint64_t)cfp
->ofrag
), (int)cfp
->size
,
4914 wtfs(fsbtodb(&sblock
, (uint64_t)cfp
->nfrag
), (int)cfp
->size
,
4925 if (cylno
!= curcylno
) {
4928 rdfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, curcylno
)),
4929 (int)sblock
.fs_cgsize
, (char *)&acg
);
4937 if (debug
&& Pflag
) {
4938 (void) fprintf(stderr
,
4939 "Assert: cylnodirty set in probe mode\n");
4943 wtfs(fsbtodb(&sblock
, (uint64_t)cgtod(&sblock
, curcylno
)),
4944 (int)sblock
.fs_cgsize
, (char *)&acg
);
4954 /* probe mode should never write to disk */
4960 allocfrags(long frags
, daddr32_t
*fragp
, long *cylnop
)
4968 * Allocate a free-frag range in an old cylinder group
4970 for (i
= 0, *fragp
= 0; i
< grow_fs_ncg
; ++i
) {
4971 if (((fscs
+i
)->cs_nffree
< frags
) && ((fscs
+i
)->cs_nbfree
== 0))
4975 while (findfreerange(&bit
, &bits
)) {
4976 if (frags
<= bits
) {
4977 for (j
= 0; j
< frags
; ++j
)
4978 clrbit(cg_blksfree(&acg
), bit
+j
);
4981 *fragp
= bit
+ cgbase(&sblock
, i
);
4990 * Allocate space for frags that need to be moved in order to free up space for
4991 * expanding the cylinder summary info.
4992 * For each frag that needs to be moved (each frag or range of frags in
4993 * the csfragino list), allocate a new location and store the frag number
4994 * of that new location in the nfrag field of the csfrag struct.
4995 * If a new frag can't be allocated for any element in the csfragino list,
4996 * set the new frag number for that element to 0 and return immediately.
4997 * The notenoughspace() function will detect this condition.
5005 * allocate space for inode frag ranges
5007 for (cfp
= csfragino
; cfp
; cfp
= cfp
->next
) {
5008 allocfrags(cfp
->frags
, &cfp
->nfrag
, &cfp
->cylno
);
5009 if (cfp
->nfrag
== 0)
5020 * allocate the free frags needed for extended summary info
5024 for (cfp
= csfragfree
; cfp
; cfp
= cfp
->next
)
5025 clrbit(cg_blksfree(&acg
), cfp
->ofrag
- cgbase(&sblock
, 0));
5031 freefrags(daddr32_t frag
, long frags
, long cylno
)
5039 for (i
= 0; i
< frags
; ++i
) {
5040 setbit(cg_blksfree(&acg
), (frag
+i
) - cgbase(&sblock
, cylno
));
5046 findfreerange(long *bitp
, long *bitsp
)
5051 * find a range of free bits in a cylinder group bit map
5053 for (bit
= *bitp
, *bitsp
= 0; bit
< acg
.cg_ndblk
; ++bit
)
5054 if (isset(cg_blksfree(&acg
), bit
))
5057 if (bit
>= acg
.cg_ndblk
)
5062 for (++bit
; bit
< acg
.cg_ndblk
; ++bit
, ++(*bitsp
)) {
5063 if ((bit
% sblock
.fs_frag
) == 0)
5065 if (isclr(cg_blksfree(&acg
), bit
))
5079 * Compute the free blocks/frags info and update the appropriate
5080 * inmemory superblock, summary info, and cylinder group fields
5082 sblock
.fs_cstotal
.cs_nffree
-= acg
.cg_cs
.cs_nffree
;
5083 sblock
.fs_cstotal
.cs_nbfree
-= acg
.cg_cs
.cs_nbfree
;
5085 acg
.cg_cs
.cs_nffree
= 0;
5086 acg
.cg_cs
.cs_nbfree
= 0;
5088 bzero((caddr_t
)acg
.cg_frsum
, sizeof (acg
.cg_frsum
));
5089 bzero((caddr_t
)cg_blktot(&acg
), (int)(acg
.cg_iusedoff
-acg
.cg_btotoff
));
5092 while (findfreerange(&bit
, &bits
)) {
5093 if (bits
== sblock
.fs_frag
) {
5094 acg
.cg_cs
.cs_nbfree
++;
5095 cno
= cbtocylno(&sblock
, bit
);
5096 cg_blktot(&acg
)[cno
]++;
5097 cg_blks(&sblock
, &acg
, cno
)[cbtorpos(&sblock
, bit
)]++;
5099 acg
.cg_cs
.cs_nffree
+= bits
;
5100 acg
.cg_frsum
[bits
]++;
5105 *(fscs
+ acg
.cg_cgx
) = acg
.cg_cs
;
5107 sblock
.fs_cstotal
.cs_nffree
+= acg
.cg_cs
.cs_nffree
;
5108 sblock
.fs_cstotal
.cs_nbfree
+= acg
.cg_cs
.cs_nbfree
;
5112 extendcg(long cylno
)
5120 * extend the cylinder group at the end of the old file system
5121 * if it was partially allocated becase of lack of space
5126 dupper
= acg
.cg_ndblk
;
5127 if (cylno
== sblock
.fs_ncg
- 1)
5128 acg
.cg_ncyl
= sblock
.fs_ncyl
- (sblock
.fs_cpg
* cylno
);
5130 acg
.cg_ncyl
= sblock
.fs_cpg
;
5131 cbase
= cgbase(&sblock
, cylno
);
5132 dmax
= cbase
+ sblock
.fs_fpg
;
5133 if (dmax
> sblock
.fs_size
)
5134 dmax
= sblock
.fs_size
;
5135 acg
.cg_ndblk
= dmax
- cbase
;
5137 for (i
= dupper
; i
< acg
.cg_ndblk
; ++i
)
5138 setbit(cg_blksfree(&acg
), i
);
5140 sblock
.fs_dsize
+= (acg
.cg_ndblk
- dupper
);
5146 struct lockfs lockfs
;
5150 char lockfscomment
[128];
5156 * if the file system was locked, unlock it before exiting
5162 * first, check if the lock held
5164 lockfs
.lf_flags
= LOCKFS_MOD
;
5165 if (ioctl(lockfd
, _FIOLFSS
, &lockfs
) == -1) {
5170 if (LOCKFS_IS_MOD(&lockfs
)) {
5171 (void) fprintf(stderr
,
5172 gettext("FILE SYSTEM CHANGED DURING GROWFS!\n"));
5173 (void) fprintf(stderr
,
5174 gettext(" See lockfs(1), umount(1), and fsck(1)\n"));
5178 * unlock the file system
5180 lockfs
.lf_lock
= LOCKFS_ULOCK
;
5181 lockfs
.lf_flags
= 0;
5182 lockfs
.lf_key
= lockfskey
;
5184 if (ioctl(lockfd
, _FIOLFS
, &lockfs
) == -1) {
5195 * if no-write (-N), don't bother
5200 * open the mountpoint, and write lock the file system
5202 if ((lockfd
= open64(directory
, O_RDONLY
)) == -1) {
5208 * check if it is already locked
5210 if (ioctl(lockfd
, _FIOLFSS
, &lockfs
) == -1) {
5215 if (lockfs
.lf_lock
!= LOCKFS_WLOCK
) {
5216 lockfs
.lf_lock
= LOCKFS_WLOCK
;
5217 lockfs
.lf_flags
= 0;
5220 if (ioctl(lockfd
, _FIOLFS
, &lockfs
) == -1) {
5226 lockfskey
= lockfs
.lf_key
;
5237 ct
[strlen(ct
)-1] = '\0';
5239 (void) sprintf(lockfscomment
, "%s -- mkfs pid %d", ct
, getpid());
5240 lockfs
.lf_comlen
= strlen(lockfscomment
)+1;
5241 lockfs
.lf_comment
= lockfscomment
;
5245 * Write the csum records and the superblock
5253 * write summary information
5255 for (i
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
)
5256 wtfs(fsbtodb(&sblock
, (uint64_t)(sblock
.fs_csaddr
+
5257 numfrags(&sblock
, i
))),
5258 (int)(sblock
.fs_cssize
- i
< sblock
.fs_bsize
?
5259 sblock
.fs_cssize
- i
: sblock
.fs_bsize
),
5260 ((char *)fscs
) + i
);
5265 sblock
.fs_time
= mkfstime
;
5266 wtfs((diskaddr_t
)(SBOFF
/ sectorsize
), sbsize
, (char *)&sblock
);
5270 * Verify that the optimization selection is reasonable, and advance
5271 * the global "string" appropriately.
5274 checkopt(char *optim
)
5277 int limit
= strcspn(optim
, ",");
5280 case 0: /* missing indicator (have comma or nul) */
5281 (void) fprintf(stderr
, gettext(
5282 "mkfs: missing optimization flag reset to `t' (time)\n"));
5286 case 1: /* single-character indicator */
5288 if ((opt
!= 's') && (opt
!= 't')) {
5289 (void) fprintf(stderr
, gettext(
5290 "mkfs: bad optimization value `%c' reset to `t' (time)\n"),
5296 default: /* multi-character indicator */
5297 (void) fprintf(stderr
, gettext(
5298 "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"),
5299 limit
, limit
, optim
);
5310 * Verify that the mtb selection is reasonable, and advance
5311 * the global "string" appropriately.
5314 checkmtb(char *mtbarg
)
5317 int limit
= strcspn(mtbarg
, ",");
5320 case 0: /* missing indicator (have comma or nul) */
5321 (void) fprintf(stderr
, gettext(
5322 "mkfs: missing mtb flag reset to `n' (no mtb support)\n"));
5326 case 1: /* single-character indicator */
5327 mtbc
= tolower(*mtbarg
);
5328 if ((mtbc
!= 'y') && (mtbc
!= 'n')) {
5329 (void) fprintf(stderr
, gettext(
5330 "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"),
5336 default: /* multi-character indicator */
5337 (void) fprintf(stderr
, gettext(
5338 "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"),
5339 limit
, limit
, mtbarg
);
5350 * Verify that a value is in a range. If it is not, resets it to
5351 * its default value if one is supplied, exits otherwise.
5353 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5356 range_check(long *varp
, char *name
, long minimum
, long maximum
,
5357 long def_val
, int user_supplied
)
5359 dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n",
5360 name
, *varp
, minimum
, maximum
, def_val
));
5362 if ((*varp
< minimum
) || (*varp
> maximum
)) {
5363 if (user_supplied
!= RC_DEFAULT
) {
5364 (void) fprintf(stderr
, gettext(
5365 "mkfs: bad value for %s: %ld must be between %ld and %ld\n"),
5366 name
, *varp
, minimum
, maximum
);
5368 if (def_val
!= NO_DEFAULT
) {
5369 if (user_supplied
) {
5370 (void) fprintf(stderr
,
5371 gettext("mkfs: %s reset to default %ld\n"),
5375 dprintf(("DeBuG %s : %ld\n", name
, *varp
));
5384 * Verify that a value is in a range. If it is not, resets it to
5385 * its default value if one is supplied, exits otherwise.
5387 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5390 range_check_64(uint64_t *varp
, char *name
, uint64_t minimum
, uint64_t maximum
,
5391 uint64_t def_val
, int user_supplied
)
5393 if ((*varp
< minimum
) || (*varp
> maximum
)) {
5394 if (user_supplied
!= RC_DEFAULT
) {
5395 (void) fprintf(stderr
, gettext(
5396 "mkfs: bad value for %s: %lld must be between %lld and %lld\n"),
5397 name
, *varp
, minimum
, maximum
);
5399 if (def_val
!= NO_DEFAULT
) {
5400 if (user_supplied
) {
5401 (void) fprintf(stderr
,
5402 gettext("mkfs: %s reset to default %lld\n"),
5414 * Blocks SIGINT from delivery. Returns the previous mask in the
5415 * buffer provided, so that mask may be later restored.
5418 block_sigint(sigset_t
*old_mask
)
5420 sigset_t block_mask
;
5422 if (sigemptyset(&block_mask
) < 0) {
5423 fprintf(stderr
, gettext("Could not clear signal mask\n"));
5426 if (sigaddset(&block_mask
, SIGINT
) < 0) {
5427 fprintf(stderr
, gettext("Could not set signal mask\n"));
5430 if (sigprocmask(SIG_BLOCK
, &block_mask
, old_mask
) < 0) {
5431 fprintf(stderr
, gettext("Could not block SIGINT\n"));
5437 * Restores the signal mask that was in force before a call
5438 * to block_sigint(). This may actually still have SIGINT blocked,
5439 * if we've been recursively invoked.
5442 unblock_sigint(sigset_t
*old_mask
)
5444 if (sigprocmask(SIG_UNBLOCK
, old_mask
, (sigset_t
*)NULL
) < 0) {
5445 fprintf(stderr
, gettext("Could not restore signal mask\n"));
5451 * Attempt to be somewhat graceful about being interrupted, rather than
5452 * just silently leaving the filesystem in an unusable state.
5454 * The kernel has blocked SIGINT upon entry, so we don't have to worry
5455 * about recursion if the user starts pounding on the keyboard.
5458 recover_from_sigint(int signum
)
5461 if ((Nflag
!= 0) || confirm_abort()) {
5472 printf(gettext("\n\nAborting at this point will leave the filesystem "
5473 "in an inconsistent\nstate. If you do choose to stop, "
5474 "you will be given instructions on how to\nrecover "
5475 "the filesystem. Do you wish to cancel the filesystem "
5476 "grow\noperation (y/n)?"));
5477 if (getaline(stdin
, line
, sizeof (line
)) == EOF
)
5481 if (line
[0] == 'y' || line
[0] == 'Y')
5489 getaline(FILE *fp
, char *loc
, int maxlen
)
5495 lastloc
= &p
[maxlen
-1];
5496 while ((n
= getc(fp
)) != '\n') {
5499 if (!isspace(n
) && p
< lastloc
)
5507 * Calculate the maximum value of cylinders-per-group for a file
5508 * system with the characteristics:
5510 * bsize - file system block size
5511 * fragsize - frag size
5512 * nbpi - number of bytes of disk space per inode
5513 * nrpos - number of rotational positions
5514 * spc - sectors per cylinder
5516 * These five characteristic are not adjustable (by this function).
5517 * The only attribute of the file system which IS adjusted by this
5518 * function in order to maximize cylinders-per-group is the proportion
5519 * of the cylinder group overhead block used for the inode map. The
5520 * inode map cannot occupy more than one-third of the cylinder group
5521 * overhead block, but it's OK for it to occupy less than one-third
5522 * of the overhead block.
5524 * The setting of nbpi determines one possible value for the maximum
5525 * size of a cylinder group. It does so because it determines the total
5526 * number of inodes in the file system (file system size is fixed, and
5527 * nbpi is fixed, so the total number of inodes is fixed too). The
5528 * cylinder group has to be small enough so that the number of inodes
5529 * in the cylinder group is less than or equal to the number of bits
5530 * in one-third (or whatever proportion is assumed) of a file system
5531 * block. The details of the calculation are:
5533 * The macro MAXIpG_B(bsize, inode_divisor) determines the maximum
5534 * number of inodes that can be in a cylinder group, given the
5535 * proportion of the cylinder group overhead block used for the
5536 * inode bitmaps (an inode_divisor of 3 means that 1/3 of the
5537 * block is used for inode bitmaps; an inode_divisor of 12 means
5538 * that 1/12 of the block is used for inode bitmaps.)
5540 * Once the number of inodes per cylinder group is known, the
5541 * maximum value of cylinders-per-group (determined by nbpi)
5542 * is calculated by the formula
5544 * maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder)
5546 * = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE)
5548 * (Interestingly, the size of the file system never enters
5549 * into this calculation.)
5551 * Another possible value for the maximum cylinder group size is determined
5552 * by frag_size and nrpos. The frags in the cylinder group must be
5553 * representable in the frag bitmaps in the cylinder overhead block and the
5554 * rotational positions for each cylinder must be represented in the
5555 * rotational position tables. The calculation of the maximum cpg
5556 * value, given the frag and nrpos vales, is:
5558 * maxcpg_given_fragsize =
5559 * (available space in the overhead block) / (size of per-cylinder data)
5561 * The available space in the overhead block =
5562 * bsize - sizeof (struct cg) - space_used_for_inode_bitmaps
5564 * The size of the per-cylinder data is:
5565 * sizeof(long) # for the "blocks avail per cylinder" field
5566 * + nrpos * sizeof(short) # for the rotational position table entry
5567 * + frags-per-cylinder/NBBY # number of bytes to represent this
5568 * # cylinder in the frag bitmap
5570 * The two calculated maximum values of cylinder-per-group will typically
5571 * turn out to be different, since they are derived from two different
5572 * constraints. Usually, maxcpg_given_nbpi is much bigger than
5573 * maxcpg_given_fragsize. But they can be brought together by
5574 * adjusting the proportion of the overhead block dedicated to
5575 * the inode bitmaps. Decreasing the proportion of the cylinder
5576 * group overhead block used for inode maps will decrease
5577 * maxcpg_given_nbpi and increase maxcpg_given_fragsize.
5579 * This function calculates the initial values of maxcpg_given_nbpi
5580 * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead
5581 * block is used for inode bitmaps. Then it decreases the proportion
5582 * of the cg overhead block used for inode bitmaps (by increasing
5583 * the value of inode_divisor) until maxcpg_given_nbpi and
5584 * maxcpg_given_fragsize are the same, or stop changing, or
5585 * maxcpg_given_nbpi is less than maxcpg_given_fragsize.
5587 * The loop terminates when any of the following occur:
5588 * * maxcpg_given_fragsize is greater than or equal to
5590 * * neither maxcpg_given_fragsize nor maxcpg_given_nbpi
5591 * change in the expected direction
5593 * The loop is guaranteed to terminate because it only continues
5594 * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching
5595 * each other. As soon they cross each other, or neither one changes
5596 * in the direction of the other, or one of them moves in the wrong
5597 * direction, the loop completes.
5601 compute_maxcpg(long bsize
, long fragsize
, long nbpi
, long nrpos
, long spc
)
5603 int maxcpg_given_nbpi
; /* in cylinders */
5604 int maxcpg_given_fragsize
; /* in cylinders */
5605 int spf
; /* sectors per frag */
5607 int old_max_given_frag
= 0;
5608 int old_max_given_nbpi
= INT_MAX
;
5610 spf
= fragsize
/ DEV_BSIZE
;
5615 (((int64_t)(MAXIpG_B(bsize
, inode_divisor
))) * nbpi
) /
5616 (DEV_BSIZE
* ((int64_t)spc
));
5617 maxcpg_given_fragsize
=
5618 (bsize
- (sizeof (struct cg
)) - (bsize
/ inode_divisor
)) /
5619 (sizeof (long) + nrpos
* sizeof (short) +
5620 (spc
/ spf
) / NBBY
);
5622 if (maxcpg_given_fragsize
>= maxcpg_given_nbpi
)
5623 return (maxcpg_given_nbpi
);
5626 * If neither value moves toward the other, return the
5627 * least of the old values (we use the old instead of the
5628 * new because: if the old is the same as the new, it
5629 * doesn't matter which ones we use. If one of the
5630 * values changed, but in the wrong direction, the
5631 * new values are suspect. Better use the old. This
5632 * shouldn't happen, but it's best to check.
5635 if (!(maxcpg_given_nbpi
< old_max_given_nbpi
) &&
5636 !(maxcpg_given_fragsize
> old_max_given_frag
))
5637 return (MIN(old_max_given_nbpi
, old_max_given_frag
));
5640 * This is probably impossible, but if one of the maxcpg
5641 * values moved in the "right" direction and one moved
5642 * in the "wrong" direction (that is, the two values moved
5643 * in the same direction), the previous conditional won't
5644 * recognize that the values aren't converging (since at
5645 * least one value moved in the "right" direction, the
5646 * last conditional says "keep going").
5648 * Just to make absolutely certain that the loop terminates,
5649 * check for one of the values moving in the "wrong" direction
5650 * and terminate the loop if it happens.
5653 if (maxcpg_given_nbpi
> old_max_given_nbpi
||
5654 maxcpg_given_fragsize
< old_max_given_frag
)
5655 return (MIN(old_max_given_nbpi
, old_max_given_frag
));
5657 old_max_given_nbpi
= maxcpg_given_nbpi
;
5658 old_max_given_frag
= maxcpg_given_fragsize
;
5667 /* cmd must be an absolute path, for security */
5668 char *cmd
= "/usr/bin/isainfo -b";
5674 if ((ptr
= popen(cmd
, "r")) != NULL
) {
5675 if (fgets(buf
, BUFSIZ
, ptr
) != NULL
&&
5676 strncmp(buf
, "64", 2) == 0)
5686 * Return 1 if the device appears to be at least "size" sectors long.
5687 * Return 0 if it's shorter or we can't read it.
5691 validate_size(int fd
, diskaddr_t size
)
5693 char buf
[DEV_BSIZE
];
5696 if ((llseek(fd
, (offset_t
)((size
- 1) * DEV_BSIZE
), SEEK_SET
) == -1) ||
5697 (read(fd
, buf
, DEV_BSIZE
)) != DEV_BSIZE
)
5705 * Print every field of the calculated superblock, along with
5706 * its value. To make parsing easier on the caller, the value
5707 * is printed first, then the name. Additionally, there's only
5708 * one name/value pair per line. All values are reported in
5709 * hexadecimal (with the traditional 0x prefix), as that's slightly
5710 * easier for humans to read. Not that they're expected to, but
5711 * debugging happens.
5716 int row
, column
, pending
, written
;
5720 pending
= sizeof (sblock
);
5721 source
= (caddr_t
)&sblock
;
5723 written
= write(fileno(stdout
), source
, pending
);
5726 } while ((pending
> 0) && (written
> 0));
5729 perror(gettext("Binary dump of superblock failed"));
5734 printf("0x%x sblock.fs_link\n", sblock
.fs_link
);
5735 printf("0x%x sblock.fs_rolled\n", sblock
.fs_rolled
);
5736 printf("0x%x sblock.fs_sblkno\n", sblock
.fs_sblkno
);
5737 printf("0x%x sblock.fs_cblkno\n", sblock
.fs_cblkno
);
5738 printf("0x%x sblock.fs_iblkno\n", sblock
.fs_iblkno
);
5739 printf("0x%x sblock.fs_dblkno\n", sblock
.fs_dblkno
);
5740 printf("0x%x sblock.fs_cgoffset\n", sblock
.fs_cgoffset
);
5741 printf("0x%x sblock.fs_cgmask\n", sblock
.fs_cgmask
);
5742 printf("0x%x sblock.fs_time\n", sblock
.fs_time
);
5743 printf("0x%x sblock.fs_size\n", sblock
.fs_size
);
5744 printf("0x%x sblock.fs_dsize\n", sblock
.fs_dsize
);
5745 printf("0x%x sblock.fs_ncg\n", sblock
.fs_ncg
);
5746 printf("0x%x sblock.fs_bsize\n", sblock
.fs_bsize
);
5747 printf("0x%x sblock.fs_fsize\n", sblock
.fs_fsize
);
5748 printf("0x%x sblock.fs_frag\n", sblock
.fs_frag
);
5749 printf("0x%x sblock.fs_minfree\n", sblock
.fs_minfree
);
5750 printf("0x%x sblock.fs_rotdelay\n", sblock
.fs_rotdelay
);
5751 printf("0x%x sblock.fs_rps\n", sblock
.fs_rps
);
5752 printf("0x%x sblock.fs_bmask\n", sblock
.fs_bmask
);
5753 printf("0x%x sblock.fs_fmask\n", sblock
.fs_fmask
);
5754 printf("0x%x sblock.fs_bshift\n", sblock
.fs_bshift
);
5755 printf("0x%x sblock.fs_fshift\n", sblock
.fs_fshift
);
5756 printf("0x%x sblock.fs_maxcontig\n", sblock
.fs_maxcontig
);
5757 printf("0x%x sblock.fs_maxbpg\n", sblock
.fs_maxbpg
);
5758 printf("0x%x sblock.fs_fragshift\n", sblock
.fs_fragshift
);
5759 printf("0x%x sblock.fs_fsbtodb\n", sblock
.fs_fsbtodb
);
5760 printf("0x%x sblock.fs_sbsize\n", sblock
.fs_sbsize
);
5761 printf("0x%x sblock.fs_csmask\n", sblock
.fs_csmask
);
5762 printf("0x%x sblock.fs_csshift\n", sblock
.fs_csshift
);
5763 printf("0x%x sblock.fs_nindir\n", sblock
.fs_nindir
);
5764 printf("0x%x sblock.fs_inopb\n", sblock
.fs_inopb
);
5765 printf("0x%x sblock.fs_nspf\n", sblock
.fs_nspf
);
5766 printf("0x%x sblock.fs_optim\n", sblock
.fs_optim
);
5767 #ifdef _LITTLE_ENDIAN
5768 printf("0x%x sblock.fs_state\n", sblock
.fs_state
);
5770 printf("0x%x sblock.fs_npsect\n", sblock
.fs_npsect
);
5772 printf("0x%x sblock.fs_si\n", sblock
.fs_si
);
5773 printf("0x%x sblock.fs_trackskew\n", sblock
.fs_trackskew
);
5774 printf("0x%x sblock.fs_id[0]\n", sblock
.fs_id
[0]);
5775 printf("0x%x sblock.fs_id[1]\n", sblock
.fs_id
[1]);
5776 printf("0x%x sblock.fs_csaddr\n", sblock
.fs_csaddr
);
5777 printf("0x%x sblock.fs_cssize\n", sblock
.fs_cssize
);
5778 printf("0x%x sblock.fs_cgsize\n", sblock
.fs_cgsize
);
5779 printf("0x%x sblock.fs_ntrak\n", sblock
.fs_ntrak
);
5780 printf("0x%x sblock.fs_nsect\n", sblock
.fs_nsect
);
5781 printf("0x%x sblock.fs_spc\n", sblock
.fs_spc
);
5782 printf("0x%x sblock.fs_ncyl\n", sblock
.fs_ncyl
);
5783 printf("0x%x sblock.fs_cpg\n", sblock
.fs_cpg
);
5784 printf("0x%x sblock.fs_ipg\n", sblock
.fs_ipg
);
5785 printf("0x%x sblock.fs_fpg\n", sblock
.fs_fpg
);
5786 printf("0x%x sblock.fs_cstotal\n", sblock
.fs_cstotal
);
5787 printf("0x%x sblock.fs_fmod\n", sblock
.fs_fmod
);
5788 printf("0x%x sblock.fs_clean\n", sblock
.fs_clean
);
5789 printf("0x%x sblock.fs_ronly\n", sblock
.fs_ronly
);
5790 printf("0x%x sblock.fs_flags\n", sblock
.fs_flags
);
5791 printf("0x%x sblock.fs_fsmnt\n", sblock
.fs_fsmnt
);
5792 printf("0x%x sblock.fs_cgrotor\n", sblock
.fs_cgrotor
);
5793 printf("0x%x sblock.fs_u.fs_csp\n", sblock
.fs_u
.fs_csp
);
5794 printf("0x%x sblock.fs_cpc\n", sblock
.fs_cpc
);
5797 * No macros are defined for the dimensions of the
5800 for (row
= 0; row
< 16; row
++) {
5801 for (column
= 0; column
< 8; column
++) {
5802 printf("0x%x sblock.fs_opostbl[%d][%d]\n",
5803 sblock
.fs_opostbl
[row
][column
],
5809 * Ditto the size of sparecon.
5811 for (row
= 0; row
< 51; row
++) {
5812 printf("0x%x sblock.fs_sparecon[%d]\n",
5813 sblock
.fs_sparecon
[row
], row
);
5816 printf("0x%x sblock.fs_version\n", sblock
.fs_version
);
5817 printf("0x%x sblock.fs_logbno\n", sblock
.fs_logbno
);
5818 printf("0x%x sblock.fs_reclaim\n", sblock
.fs_reclaim
);
5819 printf("0x%x sblock.fs_sparecon2\n", sblock
.fs_sparecon2
);
5820 #ifdef _LITTLE_ENDIAN
5821 printf("0x%x sblock.fs_npsect\n", sblock
.fs_npsect
);
5823 printf("0x%x sblock.fs_state\n", sblock
.fs_state
);
5825 printf("0x%llx sblock.fs_qbmask\n", sblock
.fs_qbmask
);
5826 printf("0x%llx sblock.fs_qfmask\n", sblock
.fs_qfmask
);
5827 printf("0x%x sblock.fs_postblformat\n", sblock
.fs_postblformat
);
5828 printf("0x%x sblock.fs_nrpos\n", sblock
.fs_nrpos
);
5829 printf("0x%x sblock.fs_postbloff\n", sblock
.fs_postbloff
);
5830 printf("0x%x sblock.fs_rotbloff\n", sblock
.fs_rotbloff
);
5831 printf("0x%x sblock.fs_magic\n", sblock
.fs_magic
);
5834 * fs_space isn't of much use in this context, so we'll
5835 * just ignore it for now.