Print this page
5083 avoid undefined order of operations in assignments
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c
+++ new/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 27 /* All Rights Reserved */
28 28
29 29 /*
30 30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 31 * The Regents of the University of California
32 32 * All Rights Reserved
33 33 *
34 34 * University Acknowledgment- Portions of this document are derived from
35 35 * software developed by the University of California, Berkeley, and its
36 36 * contributors.
37 37 */
38 38
39 39 /*
40 40 * The maximum supported file system size (in sectors) is the
41 41 * number of frags that can be represented in an int32_t field
42 42 * (INT_MAX) times the maximum number of sectors per frag. Since
43 43 * the maximum frag size is MAXBSIZE, the maximum number of sectors
44 44 * per frag is MAXBSIZE/DEV_BSIZE.
45 45 */
46 46 #define FS_MAX (((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
47 47
48 48 /*
49 49 * make file system for cylinder-group style file systems
50 50 *
51 51 * usage:
52 52 *
53 53 * mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
54 54 * [-o specific_options] special size
55 55 * [nsect ntrack bsize fsize cpg minfree rps nbpi opt apc rotdelay
56 56 * 2 3 4 5 6 7 8 9 10 11 12
57 57 * nrpos maxcontig mtb]
58 58 * 13 14 15
59 59 *
60 60 * where specific_options are:
61 61 * N - no create
62 62 * nsect - The number of sectors per track
63 63 * ntrack - The number of tracks per cylinder
64 64 * bsize - block size
65 65 * fragsize - fragment size
66 66 * cgsize - The number of disk cylinders per cylinder group.
67 67 * free - minimum free space
68 68 * rps - rotational speed (rev/sec).
69 69 * nbpi - number of data bytes per allocated inode
70 70 * opt - optimization (space, time)
71 71 * apc - number of alternates
72 72 * gap - gap size
73 73 * nrpos - number of rotational positions
74 74 * maxcontig - maximum number of logical blocks that will be
75 75 * allocated contiguously before inserting rotational delay
76 76 * mtb - if "y", set up file system for eventual growth to over a
77 77 * a terabyte
78 78 * -P Do not grow the file system, but print on stdout the maximal
79 79 * size in sectors to which the file system can be increased. The calculated
80 80 * size is limited by the value provided by the operand size.
81 81 *
82 82 * Note that -P is a project-private interface and together with -G intended
83 83 * to be used only by the growfs script. It is therefore purposely not
84 84 * documented in the man page.
85 85 * The -P option is covered by PSARC case 2003/422.
86 86 */
87 87
88 88 /*
89 89 * The following constants set the defaults used for the number
90 90 * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
91 91 *
92 92 * NSECT NTRAK
93 93 * 72MB CDC 18 9
94 94 * 30MB CDC 18 5
95 95 * 720KB Diskette 9 2
96 96 *
97 97 * However the defaults will be different for disks larger than CHSLIMIT.
98 98 */
99 99
100 100 #define DFLNSECT 32
101 101 #define DFLNTRAK 16
102 102
103 103 /*
104 104 * The following default sectors and tracks values are used for
105 105 * non-efi disks that are larger than the CHS addressing limit. The
106 106 * existing default cpg of 16 (DESCPG) holds good for larger disks too.
107 107 */
108 108 #define DEF_SECTORS_EFI 128
109 109 #define DEF_TRACKS_EFI 48
110 110
111 111 /*
112 112 * The maximum number of cylinders in a group depends upon how much
113 113 * information can be stored on a single cylinder. The default is to
114 114 * use 16 cylinders per group. This is effectively tradition - it was
115 115 * the largest value acceptable under SunOs 4.1
116 116 */
117 117 #define DESCPG 16 /* desired fs_cpg */
118 118
119 119 /*
120 120 * The following two constants set the default block and fragment sizes.
121 121 * Both constants must be a power of 2 and meet the following constraints:
122 122 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
123 123 * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
124 124 * DESBLKSIZE / DESFRAGSIZE <= 8
125 125 */
126 126 #define DESBLKSIZE 8192
127 127 #define DESFRAGSIZE 1024
128 128
129 129 /*
130 130 * MINFREE gives the minimum acceptable percentage of file system
131 131 * blocks which may be free. If the freelist drops below this level
132 132 * only the superuser may continue to allocate blocks. This may
133 133 * be set to 0 if no reserve of free blocks is deemed necessary,
134 134 * however throughput drops by fifty percent if the file system
135 135 * is run at between 90% and 100% full; thus the default value of
136 136 * fs_minfree is 10%. With 10% free space, fragmentation is not a
137 137 * problem, so we choose to optimize for time.
138 138 */
139 139 #define MINFREE 10
140 140 #define DEFAULTOPT FS_OPTTIME
141 141
142 142 /*
143 143 * ROTDELAY gives the minimum number of milliseconds to initiate
144 144 * another disk transfer on the same cylinder. It is no longer used
145 145 * and will always default to 0.
146 146 */
147 147 #define ROTDELAY 0
148 148
149 149 /*
150 150 * MAXBLKPG determines the maximum number of data blocks which are
151 151 * placed in a single cylinder group. The default is one indirect
152 152 * block worth of data blocks.
153 153 */
154 154 #define MAXBLKPG(bsize) ((bsize) / sizeof (daddr32_t))
155 155
156 156 /*
157 157 * Each file system has a number of inodes statically allocated.
158 158 * We allocate one inode slot per NBPI bytes, expecting this
159 159 * to be far more than we will ever need.
160 160 */
161 161 #define NBPI 2048 /* Number Bytes Per Inode */
162 162 #define MTB_NBPI (MB) /* Number Bytes Per Inode for multi-terabyte */
163 163
164 164 /*
165 165 * Disks are assumed to rotate at 60HZ, unless otherwise specified.
166 166 */
167 167 #define DEFHZ 60
168 168
169 169 /*
170 170 * Cylinder group related limits.
171 171 *
172 172 * For each cylinder we keep track of the availability of blocks at different
173 173 * rotational positions, so that we can lay out the data to be picked
174 174 * up with minimum rotational latency. NRPOS is the number of rotational
175 175 * positions which we distinguish. With NRPOS 8 the resolution of our
176 176 * summary information is 2ms for a typical 3600 rpm drive.
177 177 */
178 178 #define NRPOS 8 /* number distinct rotational positions */
179 179
180 180 #ifdef DEBUG
181 181 #define dprintf(x) printf x
182 182 #else
183 183 #define dprintf(x)
184 184 #endif
185 185
186 186 /*
187 187 * For the -N option, when calculating the backup superblocks, do not print
188 188 * them if we are not really sure. We may have to try an alternate method of
189 189 * arriving at the superblocks. So defer printing till a handful of superblocks
190 190 * look good.
191 191 */
192 192 #define tprintf(x) if (Nflag && retry) \
193 193 (void) strncat(tmpbuf, x, strlen(x)); \
194 194 else \
195 195 (void) fprintf(stderr, x);
196 196
197 197 #define ALTSB 32 /* Location of first backup superblock */
198 198
199 199 /*
200 200 * range_check "user_supplied" flag values.
201 201 */
202 202 #define RC_DEFAULT 0
203 203 #define RC_KEYWORD 1
204 204 #define RC_POSITIONAL 2
205 205
206 206 /*
207 207 * ufs hole
208 208 */
209 209 #define UFS_HOLE -1
210 210
211 211 #ifndef STANDALONE
212 212 #include <stdio.h>
213 213 #include <sys/mnttab.h>
214 214 #endif
215 215
216 216 #include <stdlib.h>
217 217 #include <unistd.h>
218 218 #include <malloc.h>
219 219 #include <string.h>
220 220 #include <strings.h>
221 221 #include <ctype.h>
222 222 #include <errno.h>
223 223 #include <sys/param.h>
224 224 #include <time.h>
225 225 #include <sys/types.h>
226 226 #include <sys/sysmacros.h>
227 227 #include <sys/vnode.h>
228 228 #include <sys/fs/ufs_fsdir.h>
229 229 #include <sys/fs/ufs_inode.h>
230 230 #include <sys/fs/ufs_fs.h>
231 231 #include <sys/fs/ufs_log.h>
232 232 #include <sys/mntent.h>
233 233 #include <sys/filio.h>
234 234 #include <limits.h>
235 235 #include <sys/int_const.h>
236 236 #include <signal.h>
237 237 #include <sys/efi_partition.h>
238 238 #include "roll_log.h"
239 239
240 240 #define bcopy(f, t, n) (void) memcpy(t, f, n)
241 241 #define bzero(s, n) (void) memset(s, 0, n)
242 242 #define bcmp(s, d, n) memcmp(s, d, n)
243 243
244 244 #define index(s, r) strchr(s, r)
245 245 #define rindex(s, r) strrchr(s, r)
246 246
247 247 #include <sys/stat.h>
248 248 #include <sys/statvfs.h>
249 249 #include <locale.h>
250 250 #include <fcntl.h>
251 251 #include <sys/isa_defs.h> /* for ENDIAN defines */
252 252 #include <sys/vtoc.h>
253 253
254 254 #include <sys/dkio.h>
255 255 #include <sys/asynch.h>
256 256
257 257 extern offset_t llseek();
258 258 extern char *getfullblkname();
259 259 extern long lrand48();
260 260
261 261 extern int optind;
262 262 extern char *optarg;
263 263
264 264
265 265 /*
266 266 * The size of a cylinder group is calculated by CGSIZE. The maximum size
267 267 * is limited by the fact that cylinder groups are at most one block.
268 268 * Its size is derived from the size of the maps maintained in the
269 269 * cylinder group and the (struct cg) size.
270 270 */
271 271 #define CGSIZE(fs) \
272 272 /* base cg */ (sizeof (struct cg) + \
273 273 /* blktot size */ (fs)->fs_cpg * sizeof (long) + \
274 274 /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
275 275 /* inode map */ howmany((fs)->fs_ipg, NBBY) + \
276 276 /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
277 277
278 278 /*
279 279 * We limit the size of the inode map to be no more than a
280 280 * third of the cylinder group space, since we must leave at
281 281 * least an equal amount of space for the block map.
282 282 *
283 283 * N.B.: MAXIpG must be a multiple of INOPB(fs).
284 284 */
285 285 #define MAXIpG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
286 286
287 287 /*
288 288 * Same as MAXIpG, but parameterized by the block size (b) and the
289 289 * cylinder group divisor (d), which is the reciprocal of the fraction of the
290 290 * cylinder group overhead block that is used for the inode map. So for
291 291 * example, if d = 5, the macro's computation assumes that 1/5 of the
292 292 * cylinder group overhead block can be dedicated to the inode map.
293 293 */
294 294 #define MAXIpG_B(b, d) roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
295 295
296 296 #define UMASK 0755
297 297 #define MAXINOPB (MAXBSIZE / sizeof (struct dinode))
298 298 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
299 299 #define MB (1024*1024)
300 300 #define BETWEEN(x, l, h) ((x) >= (l) && (x) <= (h))
301 301
302 302 /*
303 303 * Used to set the inode generation number. Since both inodes and dinodes
304 304 * are dealt with, we really need a pointer to an icommon here.
305 305 */
306 306 #define IRANDOMIZE(icp) (icp)->ic_gen = lrand48();
307 307
308 308 /*
309 309 * Flags for number()
310 310 */
311 311 #define ALLOW_PERCENT 0x01 /* allow trailing `%' on number */
312 312 #define ALLOW_MS1 0x02 /* allow trailing `ms', state 1 */
313 313 #define ALLOW_MS2 0x04 /* allow trailing `ms', state 2 */
314 314 #define ALLOW_END_ONLY 0x08 /* must be at end of number & suffixes */
315 315
316 316 #define MAXAIO 1000 /* maximum number of outstanding I/O's we'll manage */
317 317 #define BLOCK 1 /* block in aiowait */
318 318 #define NOBLOCK 0 /* don't block in aiowait */
319 319
320 320 #define RELEASE 1 /* free an aio buffer after use */
321 321 #define SAVE 0 /* don't free the buffer */
322 322
323 323 typedef struct aio_trans {
324 324 aio_result_t resultbuf;
325 325 diskaddr_t bno;
326 326 char *buffer;
327 327 int size;
328 328 int release;
329 329 struct aio_trans *next;
330 330 } aio_trans;
331 331
332 332 typedef struct aio_results {
333 333 int max;
334 334 int outstanding;
335 335 int maxpend;
336 336 aio_trans *trans;
337 337 } aio_results;
338 338
339 339 int aio_inited = 0;
340 340 aio_results results;
341 341
342 342 /*
343 343 * Allow up to MAXBUF aio requests that each have a unique buffer.
344 344 * More aio's might be done, but not using memory through the getbuf()
345 345 * interface. This can be raised, but you run into the potential of
346 346 * using more memory than is physically available on the machine,
347 347 * and if you start swapping, you can forget about performance.
348 348 * To prevent this, we also limit the total memory used for a given
349 349 * type of buffer to MAXBUFMEM.
350 350 *
351 351 * Tests indicate a cylinder group's worth of inodes takes:
352 352 *
353 353 * NBPI Size of Inode Buffer
354 354 * 2k 1688k
355 355 * 8k 424k
356 356 *
357 357 * initcg() stores all the inodes for a cylinder group in one buffer,
358 358 * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
359 359 */
360 360 #define MAXBUF 20
361 361 #define MAXBUFMEM (8 * 1024 * 1024)
362 362
363 363 /*
364 364 * header information for buffers managed by getbuf() and freebuf()
365 365 */
366 366 typedef struct bufhdr {
367 367 struct bufhdr *head;
368 368 struct bufhdr *next;
369 369 } bufhdr;
370 370
371 371 int bufhdrsize;
372 372
373 373 bufhdr inodebuf = { NULL, NULL };
374 374 bufhdr cgsumbuf = { NULL, NULL };
375 375
376 376 #define SECTORS_PER_TERABYTE (1LL << 31)
377 377 /*
378 378 * The following constant specifies an upper limit for file system size
379 379 * that is actually a lot bigger than we expect to support with UFS. (Since
380 380 * it's specified in sectors, the file system size would be 2**44 * 512,
381 381 * which is 2**53, which is 8192 Terabytes.) However, it's useful
382 382 * for checking the basic sanity of a size value that is input on the
383 383 * command line.
384 384 */
385 385 #define FS_SIZE_UPPER_LIMIT 0x100000000000LL
386 386
387 387 /*
388 388 * Forward declarations
389 389 */
390 390 static char *getbuf(bufhdr *bufhead, int size);
391 391 static void freebuf(char *buf);
392 392 static void freetrans(aio_trans *transp);
393 393 static aio_trans *get_aiop();
394 394 static aio_trans *wait_for_write(int block);
395 395 static void initcg(int cylno);
396 396 static void fsinit();
397 397 static int makedir(struct direct *protodir, int entries);
398 398 static void iput(struct inode *ip);
399 399 static void rdfs(diskaddr_t bno, int size, char *bf);
400 400 static void wtfs(diskaddr_t bno, int size, char *bf);
401 401 static void awtfs(diskaddr_t bno, int size, char *bf, int release);
402 402 static void wtfs_breakup(diskaddr_t bno, int size, char *bf);
403 403 static int isblock(struct fs *fs, unsigned char *cp, int h);
404 404 static void clrblock(struct fs *fs, unsigned char *cp, int h);
405 405 static void setblock(struct fs *fs, unsigned char *cp, int h);
406 406 static void usage();
407 407 static void dump_fscmd(char *fsys, int fsi);
408 408 static uint64_t number(uint64_t d_value, char *param, int flags);
409 409 static int match(char *s);
410 410 static char checkopt(char *optim);
411 411 static char checkmtb(char *mtbarg);
412 412 static void range_check(long *varp, char *name, long minimum,
413 413 long maximum, long def_val, int user_supplied);
414 414 static void range_check_64(uint64_t *varp, char *name, uint64_t minimum,
415 415 uint64_t maximum, uint64_t def_val, int user_supplied);
416 416 static daddr32_t alloc(int size, int mode);
417 417 static diskaddr_t get_max_size(int fd);
418 418 static long get_max_track_size(int fd);
419 419 static void block_sigint(sigset_t *old_mask);
420 420 static void unblock_sigint(sigset_t *old_mask);
421 421 static void recover_from_sigint(int signum);
422 422 static int confirm_abort(void);
423 423 static int getaline(FILE *fp, char *loc, int maxlen);
424 424 static void flush_writes(void);
425 425 static long compute_maxcpg(long, long, long, long, long);
426 426 static int in_64bit_mode(void);
427 427 static int validate_size(int fd, diskaddr_t size);
428 428 static void dump_sblock(void);
429 429
430 430 /*
431 431 * Workaround for mkfs to function properly on disks attached to XMIT 2.X
432 432 * controller. If the address is not aligned at 8 byte boundary, mkfs on
433 433 * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
434 434 */
435 435 #define XMIT_2_X_ALIGN 8
436 436 #pragma align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
437 437
438 438 union {
439 439 struct fs fs;
440 440 char pad[SBSIZE];
441 441 } fsun, altfsun;
442 442 #define sblock fsun.fs
443 443 #define altsblock altfsun.fs
444 444
445 445 struct csum *fscs;
446 446
447 447 union cgun {
448 448 struct cg cg;
449 449 char pad[MAXBSIZE];
450 450 } cgun;
451 451
452 452 #define acg cgun.cg
453 453 /*
454 454 * Size of screen in cols in which to fit output
455 455 */
456 456 #define WIDTH 80
457 457
458 458 struct dinode zino[MAXBSIZE / sizeof (struct dinode)];
459 459
460 460 /*
461 461 * file descriptors used for rdfs(fsi) and wtfs(fso).
462 462 * Initialized to an illegal file descriptor number.
463 463 */
464 464 int fsi = -1;
465 465 int fso = -1;
466 466
467 467 /*
468 468 * The BIG parameter is machine dependent. It should be a longlong integer
469 469 * constant that can be used by the number parser to check the validity
470 470 * of numeric parameters.
471 471 */
472 472
473 473 #define BIG 0x7fffffffffffffffLL
474 474
475 475 /* Used to indicate to number() that a bogus value should cause us to exit */
476 476 #define NO_DEFAULT LONG_MIN
477 477
478 478 /*
479 479 * INVALIDSBLIMIT is the number of bad backup superblocks that will be
480 480 * tolerated before we decide to try arriving at a different set of them
481 481 * using a different logic. This is applicable for non-EFI disks only.
482 482 */
483 483 #define INVALIDSBLIMIT 10
484 484
485 485 /*
486 486 * The *_flag variables are used to indicate that the user specified
487 487 * the values, rather than that we made them up ourselves. We can
488 488 * complain about the user giving us bogus values.
489 489 */
490 490
491 491 /* semi-constants */
492 492 long sectorsize = DEV_BSIZE; /* bytes/sector from param.h */
493 493 long bbsize = BBSIZE; /* boot block size */
494 494 long sbsize = SBSIZE; /* superblock size */
495 495
496 496 /* parameters */
497 497 diskaddr_t fssize_db; /* file system size in disk blocks */
498 498 diskaddr_t fssize_frag; /* file system size in frags */
499 499 long cpg; /* cylinders/cylinder group */
500 500 int cpg_flag = RC_DEFAULT;
501 501 long rotdelay = -1; /* rotational delay between blocks */
502 502 int rotdelay_flag = RC_DEFAULT;
503 503 long maxcontig; /* max contiguous blocks to allocate */
504 504 int maxcontig_flag = RC_DEFAULT;
505 505 long nsect = DFLNSECT; /* sectors per track */
506 506 int nsect_flag = RC_DEFAULT;
507 507 long ntrack = DFLNTRAK; /* tracks per cylinder group */
508 508 int ntrack_flag = RC_DEFAULT;
509 509 long bsize = DESBLKSIZE; /* filesystem block size */
510 510 int bsize_flag = RC_DEFAULT;
511 511 long fragsize = DESFRAGSIZE; /* filesystem fragment size */
512 512 int fragsize_flag = RC_DEFAULT;
513 513 long minfree = MINFREE; /* fs_minfree */
514 514 int minfree_flag = RC_DEFAULT;
515 515 long rps = DEFHZ; /* revolutions/second of drive */
516 516 int rps_flag = RC_DEFAULT;
517 517 long nbpi = NBPI; /* number of bytes per inode */
518 518 int nbpi_flag = RC_DEFAULT;
519 519 long nrpos = NRPOS; /* number of rotational positions */
520 520 int nrpos_flag = RC_DEFAULT;
521 521 long apc = 0; /* alternate sectors per cylinder */
522 522 int apc_flag = RC_DEFAULT;
523 523 char opt = 't'; /* optimization style, `t' or `s' */
524 524 char mtb = 'n'; /* multi-terabyte format, 'y' or 'n' */
525 525 #define DEFAULT_SECT_TRAK_CPG (nsect_flag == RC_DEFAULT && \
526 526 ntrack_flag == RC_DEFAULT && \
527 527 cpg_flag == RC_DEFAULT)
528 528
529 529 long debug = 0; /* enable debugging output */
530 530
531 531 int spc_flag = 0; /* alternate sectors specified or */
532 532 /* found */
533 533
534 534 /* global state */
535 535 int Nflag; /* do not write to disk */
536 536 int mflag; /* return the command line used to create this FS */
537 537 int rflag; /* report the superblock in an easily-parsed form */
538 538 int Rflag; /* dump the superblock in binary */
539 539 char *fsys;
540 540 time_t mkfstime;
541 541 char *string;
542 542 int label_type;
543 543
544 544 /*
545 545 * logging support
546 546 */
547 547 int ismdd; /* true if device is a SVM device */
548 548 int islog; /* true if ufs or SVM logging is enabled */
549 549 int islogok; /* true if ufs/SVM log state is good */
550 550
551 551 static int isufslog; /* true if ufs logging is enabled */
552 552 static int waslog; /* true when ufs logging disabled during grow */
553 553
554 554 /*
555 555 * growfs defines, globals, and forward references
556 556 */
557 557 #define NOTENOUGHSPACE 33
558 558 int grow;
559 559 #define GROW_WITH_DEFAULT_TRAK (grow && ntrack_flag == RC_DEFAULT)
560 560
561 561 static int Pflag; /* probe to which size the fs can be grown */
562 562 int ismounted;
563 563 char *directory;
564 564 diskaddr_t grow_fssize;
565 565 long grow_fs_size;
566 566 long grow_fs_ncg;
567 567 diskaddr_t grow_fs_csaddr;
568 568 long grow_fs_cssize;
569 569 int grow_fs_clean;
570 570 struct csum *grow_fscs;
571 571 diskaddr_t grow_sifrag;
572 572 int test;
573 573 int testforce;
574 574 diskaddr_t testfrags;
575 575 int inlockexit;
576 576 int isbad;
577 577
578 578 void lockexit(int);
579 579 void randomgeneration(void);
580 580 void checksummarysize(void);
581 581 int checksblock(struct fs, int);
582 582 void growinit(char *);
583 583 void checkdev(char *, char *);
584 584 void checkmount(struct mnttab *, char *);
585 585 struct dinode *gdinode(ino_t);
586 586 int csfraginrange(daddr32_t);
587 587 struct csfrag *findcsfrag(daddr32_t, struct csfrag **);
588 588 void checkindirect(ino_t, daddr32_t *, daddr32_t, int);
589 589 void addcsfrag(ino_t, daddr32_t, struct csfrag **);
590 590 void delcsfrag(daddr32_t, struct csfrag **);
591 591 void checkdirect(ino_t, daddr32_t *, daddr32_t *, int);
592 592 void findcsfragino(void);
593 593 void fixindirect(daddr32_t, int);
594 594 void fixdirect(caddr_t, daddr32_t, daddr32_t *, int);
595 595 void fixcsfragino(void);
596 596 void extendsummaryinfo(void);
597 597 int notenoughspace(void);
598 598 void unalloccsfragino(void);
599 599 void unalloccsfragfree(void);
600 600 void findcsfragfree(void);
601 601 void copycsfragino(void);
602 602 void rdcg(long);
603 603 void wtcg(void);
604 604 void flcg(void);
605 605 void allocfrags(long, daddr32_t *, long *);
606 606 void alloccsfragino(void);
607 607 void alloccsfragfree(void);
608 608 void freefrags(daddr32_t, long, long);
609 609 int findfreerange(long *, long *);
610 610 void resetallocinfo(void);
611 611 void extendcg(long);
612 612 void ulockfs(void);
613 613 void wlockfs(void);
614 614 void clockfs(void);
615 615 void wtsb(void);
616 616 static int64_t checkfragallocated(daddr32_t);
617 617 static struct csum *read_summaryinfo(struct fs *);
618 618 static diskaddr_t probe_summaryinfo();
619 619
620 620 int
621 621 main(int argc, char *argv[])
622 622 {
623 623 long i, mincpc, mincpg, ibpcl;
624 624 long cylno, rpos, blk, j, warn = 0;
625 625 long mincpgcnt, maxcpg;
626 626 uint64_t used, bpcg, inospercg;
627 627 long mapcramped, inodecramped;
628 628 long postblsize, rotblsize, totalsbsize;
629 629 FILE *mnttab;
630 630 struct mnttab mntp;
631 631 char *special;
632 632 struct statvfs64 fs;
633 633 struct dk_geom dkg;
634 634 struct dk_cinfo dkcinfo;
635 635 struct dk_minfo dkminfo;
636 636 char pbuf[sizeof (uint64_t) * 3 + 1];
637 637 char *tmpbuf;
638 638 int width, plen;
639 639 uint64_t num;
640 640 int c, saverr;
641 641 diskaddr_t max_fssize;
642 642 long tmpmaxcontig = -1;
643 643 struct sigaction sigact;
644 644 uint64_t nbytes64;
645 645 int remaining_cg;
646 646 int do_dot = 0;
647 647 int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0;
648 648 int invalid_sb_cnt, ret, skip_this_sb, cg_too_small;
649 649 int geom_nsect, geom_ntrack, geom_cpg;
650 650
651 651 (void) setlocale(LC_ALL, "");
652 652
653 653 #if !defined(TEXT_DOMAIN)
654 654 #define TEXT_DOMAIN "SYS_TEST"
655 655 #endif
656 656 (void) textdomain(TEXT_DOMAIN);
657 657
658 658 while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) {
659 659 switch (c) {
660 660
661 661 case 'F':
662 662 string = optarg;
663 663 if (strcmp(string, "ufs") != 0)
664 664 usage();
665 665 break;
666 666
667 667 case 'm': /* return command line used to create this FS */
668 668 mflag++;
669 669 break;
670 670
671 671 case 'o':
672 672 /*
673 673 * ufs specific options.
674 674 */
675 675 string = optarg;
676 676 while (*string != '\0') {
677 677 if (match("nsect=")) {
678 678 nsect = number(DFLNSECT, "nsect", 0);
679 679 nsect_flag = RC_KEYWORD;
680 680 } else if (match("ntrack=")) {
681 681 ntrack = number(DFLNTRAK, "ntrack", 0);
682 682 ntrack_flag = RC_KEYWORD;
683 683 } else if (match("bsize=")) {
684 684 bsize = number(DESBLKSIZE, "bsize", 0);
685 685 bsize_flag = RC_KEYWORD;
686 686 } else if (match("fragsize=")) {
687 687 fragsize = number(DESFRAGSIZE,
688 688 "fragsize", 0);
689 689 fragsize_flag = RC_KEYWORD;
690 690 } else if (match("cgsize=")) {
691 691 cpg = number(DESCPG, "cgsize", 0);
692 692 cpg_flag = RC_KEYWORD;
693 693 } else if (match("free=")) {
694 694 minfree = number(MINFREE, "free",
695 695 ALLOW_PERCENT);
696 696 minfree_flag = RC_KEYWORD;
697 697 } else if (match("maxcontig=")) {
698 698 tmpmaxcontig =
699 699 number(-1, "maxcontig", 0);
700 700 maxcontig_flag = RC_KEYWORD;
701 701 } else if (match("nrpos=")) {
702 702 nrpos = number(NRPOS, "nrpos", 0);
703 703 nrpos_flag = RC_KEYWORD;
704 704 } else if (match("rps=")) {
705 705 rps = number(DEFHZ, "rps", 0);
706 706 rps_flag = RC_KEYWORD;
707 707 } else if (match("nbpi=")) {
708 708 nbpi = number(NBPI, "nbpi", 0);
709 709 nbpi_flag = RC_KEYWORD;
710 710 } else if (match("opt=")) {
711 711 opt = checkopt(string);
712 712 } else if (match("mtb=")) {
713 713 mtb = checkmtb(string);
714 714 } else if (match("apc=")) {
715 715 apc = number(0, "apc", 0);
716 716 apc_flag = RC_KEYWORD;
717 717 } else if (match("gap=")) {
718 718 (void) number(0, "gap", ALLOW_MS1);
719 719 rotdelay = ROTDELAY;
720 720 rotdelay_flag = RC_DEFAULT;
721 721 } else if (match("debug=")) {
722 722 debug = number(0, "debug", 0);
723 723 } else if (match("N")) {
724 724 Nflag++;
725 725 } else if (match("calcsb")) {
726 726 rflag++;
727 727 Nflag++;
728 728 } else if (match("calcbinsb")) {
729 729 rflag++;
730 730 Rflag++;
731 731 Nflag++;
732 732 } else if (*string == '\0') {
733 733 break;
734 734 } else {
735 735 (void) fprintf(stderr, gettext(
736 736 "illegal option: %s\n"), string);
737 737 usage();
738 738 }
739 739
740 740 if (*string == ',') string++;
741 741 if (*string == ' ') string++;
742 742 }
743 743 break;
744 744
745 745 case 'V':
746 746 {
747 747 char *opt_text;
748 748 int opt_count;
749 749
750 750 (void) fprintf(stdout, gettext("mkfs -F ufs "));
751 751 for (opt_count = 1; opt_count < argc;
752 752 opt_count++) {
753 753 opt_text = argv[opt_count];
754 754 if (opt_text)
755 755 (void) fprintf(stdout, " %s ",
756 756 opt_text);
757 757 }
758 758 (void) fprintf(stdout, "\n");
759 759 }
760 760 break;
761 761
762 762 case 'b': /* do nothing for this */
763 763 break;
764 764
765 765 case 'M': /* grow the mounted file system */
766 766 directory = optarg;
767 767
768 768 /* FALLTHROUGH */
769 769 case 'G': /* grow the file system */
770 770 grow = 1;
771 771 break;
772 772 case 'P': /* probe the file system growing size */
773 773 Pflag = 1;
774 774 grow = 1; /* probe mode implies fs growing */
775 775 break;
776 776 case 'T': /* For testing */
777 777 testforce = 1;
778 778
779 779 /* FALLTHROUGH */
780 780 case 't':
781 781 test = 1;
782 782 string = optarg;
783 783 testfrags = number(NO_DEFAULT, "testfrags", 0);
784 784 break;
785 785
786 786 case '?':
787 787 usage();
788 788 break;
789 789 }
790 790 }
791 791 #ifdef MKFS_DEBUG
792 792 /*
793 793 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
794 794 * that can be reproduced by setting the time to 0 and seeding
795 795 * the random number generator to a constant.
796 796 */
797 797 mkfstime = 0; /* reproducible results */
798 798 #else
799 799 (void) time(&mkfstime);
800 800 #endif
801 801
802 802 if (optind >= (argc - 1)) {
803 803 if (optind > (argc - 1)) {
804 804 (void) fprintf(stderr,
805 805 gettext("special not specified\n"));
806 806 usage();
807 807 } else if (mflag == 0) {
808 808 (void) fprintf(stderr,
809 809 gettext("size not specified\n"));
810 810 usage();
811 811 }
812 812 }
813 813 argc -= optind;
814 814 argv = &argv[optind];
815 815
816 816 fsys = argv[0];
817 817 fsi = open64(fsys, O_RDONLY);
818 818 if (fsi < 0) {
819 819 (void) fprintf(stderr, gettext("%s: cannot open\n"), fsys);
820 820 lockexit(32);
821 821 }
822 822
823 823 if (mflag) {
824 824 dump_fscmd(fsys, fsi);
825 825 lockexit(0);
826 826 }
827 827
828 828 /*
829 829 * The task of setting all of the configuration parameters for a
830 830 * UFS file system is basically a matter of solving n equations
831 831 * in m variables. Typically, m is greater than n, so there is
832 832 * usually more than one valid solution. Since this is usually
833 833 * an under-constrained problem, it's not always obvious what the
834 834 * "best" configuration is.
835 835 *
836 836 * In general, the approach is to
837 837 * 1. Determine the values for the file system parameters
838 838 * that are externally contrained and therefore not adjustable
839 839 * by mkfs (such as the device's size and maxtransfer size).
840 840 * 2. Acquire the user's requested setting for all configuration
841 841 * values that can be set on the command line.
842 842 * 3. Determine the final value of all configuration values, by
843 843 * the following approach:
844 844 * - set the file system block size (fs_bsize). Although
845 845 * this could be regarded as an adjustable parameter, in
846 846 * fact, it's pretty much a constant. At this time, it's
847 847 * generally set to 8k (with older hardware, it can
848 848 * sometimes make sense to set it to 4k, but those
849 849 * situations are pretty rare now).
850 850 * - re-adjust the maximum file system size based on the
851 851 * value of the file system block size. Since the
852 852 * frag size can't be any larger than a file system
853 853 * block, and the number of frags in the file system
854 854 * has to fit into 31 bits, the file system block size
855 855 * affects the maximum file system size.
856 856 * - now that the real maximum file system is known, set the
857 857 * actual size of the file system to be created to
858 858 * MIN(requested size, maximum file system size).
859 859 * - now validate, and if necessary, adjust the following
860 860 * values:
861 861 * rotdelay
862 862 * nsect
863 863 * maxcontig
864 864 * apc
865 865 * frag_size
866 866 * rps
867 867 * minfree
868 868 * nrpos
869 869 * nrack
870 870 * nbpi
871 871 * - calculate maxcpg (the maximum value of the cylinders-per-
872 872 * cylinder-group configuration parameters). There are two
873 873 * algorithms for calculating maxcpg: an old one, which is
874 874 * used for file systems of less than 1 terabyte, and a
875 875 * new one, implemented in the function compute_maxcpg(),
876 876 * which is used for file systems of greater than 1 TB.
877 877 * The difference between them is that compute_maxcpg()
878 878 * really tries to maximize the cpg value. The old
879 879 * algorithm fails to take advantage of smaller frags and
880 880 * lower inode density when determining the maximum cpg,
881 881 * and thus comes up with much lower numbers in some
882 882 * configurations. At some point, we might use the
883 883 * new algorithm for determining maxcpg for all file
884 884 * systems, but at this time, the changes implemented for
885 885 * multi-terabyte UFS are NOT being automatically applied
886 886 * to UFS file systems of less than a terabyte (in the
887 887 * interest of not changing existing UFS policy too much
888 888 * until the ramifications of the changes are well-understood
889 889 * and have been evaluated for their effects on performance.)
890 890 * - check the current values of the configuration parameters
891 891 * against the various constraints imposed by UFS. These
892 892 * include:
893 893 * * There must be at least one inode in each
894 894 * cylinder group.
895 895 * * The cylinder group overhead block, which
896 896 * contains the inode and frag bigmaps, must fit
897 897 * within one file system block.
898 898 * * The space required for inode maps should
899 899 * occupy no more than a third of the cylinder
900 900 * group overhead block.
901 901 * * The rotational position tables have to fit
902 902 * within the available space in the super block.
903 903 * Adjust the configuration values that can be adjusted
904 904 * so that these constraints are satisfied. The
905 905 * configuration values that are adjustable are:
906 906 * * frag size
907 907 * * cylinders per group
908 908 * * inode density (can be increased)
909 909 * * number of rotational positions (the rotational
910 910 * position tables are eliminated altogether if
911 911 * there isn't enough room for them.)
912 912 * 4. Set the values for all the dependent configuration
913 913 * values (those that aren't settable on the command
914 914 * line and which are completely dependent on the
915 915 * adjustable parameters). This include cpc (cycles
916 916 * per cylinder, spc (sectors-per-cylinder), and many others.
917 917 */
918 918
919 919 /*
920 920 * Figure out the partition size and initialize the label_type.
921 921 */
922 922 max_fssize = get_max_size(fsi);
923 923
924 924 /*
925 925 * Get and check positional arguments, if any.
926 926 */
927 927 switch (argc - 1) {
928 928 default:
929 929 usage();
930 930 /*NOTREACHED*/
931 931 case 15:
932 932 mtb = checkmtb(argv[15]);
933 933 /* FALLTHROUGH */
934 934 case 14:
935 935 string = argv[14];
936 936 tmpmaxcontig = number(-1, "maxcontig", 0);
937 937 maxcontig_flag = RC_POSITIONAL;
938 938 /* FALLTHROUGH */
939 939 case 13:
940 940 string = argv[13];
941 941 nrpos = number(NRPOS, "nrpos", 0);
942 942 nrpos_flag = RC_POSITIONAL;
943 943 /* FALLTHROUGH */
944 944 case 12:
945 945 string = argv[12];
946 946 rotdelay = ROTDELAY;
947 947 rotdelay_flag = RC_DEFAULT;
948 948 /* FALLTHROUGH */
949 949 case 11:
950 950 string = argv[11];
951 951 apc = number(0, "apc", 0);
952 952 apc_flag = RC_POSITIONAL;
953 953 /* FALLTHROUGH */
954 954 case 10:
955 955 opt = checkopt(argv[10]);
956 956 /* FALLTHROUGH */
957 957 case 9:
958 958 string = argv[9];
959 959 nbpi = number(NBPI, "nbpi", 0);
960 960 nbpi_flag = RC_POSITIONAL;
961 961 /* FALLTHROUGH */
962 962 case 8:
963 963 string = argv[8];
964 964 rps = number(DEFHZ, "rps", 0);
965 965 rps_flag = RC_POSITIONAL;
966 966 /* FALLTHROUGH */
967 967 case 7:
968 968 string = argv[7];
969 969 minfree = number(MINFREE, "free", ALLOW_PERCENT);
970 970 minfree_flag = RC_POSITIONAL;
971 971 /* FALLTHROUGH */
972 972 case 6:
973 973 string = argv[6];
974 974 cpg = number(DESCPG, "cgsize", 0);
975 975 cpg_flag = RC_POSITIONAL;
976 976 /* FALLTHROUGH */
977 977 case 5:
978 978 string = argv[5];
979 979 fragsize = number(DESFRAGSIZE, "fragsize", 0);
980 980 fragsize_flag = RC_POSITIONAL;
981 981 /* FALLTHROUGH */
982 982 case 4:
983 983 string = argv[4];
984 984 bsize = number(DESBLKSIZE, "bsize", 0);
985 985 bsize_flag = RC_POSITIONAL;
986 986 /* FALLTHROUGH */
987 987 case 3:
988 988 string = argv[3];
989 989 ntrack = number(DFLNTRAK, "ntrack", 0);
990 990 ntrack_flag = RC_POSITIONAL;
991 991 /* FALLTHROUGH */
992 992 case 2:
993 993 string = argv[2];
994 994 nsect = number(DFLNSECT, "nsect", 0);
995 995 nsect_flag = RC_POSITIONAL;
996 996 /* FALLTHROUGH */
997 997 case 1:
998 998 string = argv[1];
999 999 fssize_db = number(max_fssize, "size", 0);
1000 1000 }
1001 1001
1002 1002 /*
1003 1003 * Initialize the parameters in the same way as newfs so that
1004 1004 * newfs and mkfs would result in the same file system layout
1005 1005 * for EFI labelled disks. Do this only in the absence of user
1006 1006 * specified values for these parameters.
1007 1007 */
1008 1008 if (label_type == LABEL_TYPE_EFI) {
1009 1009 if (apc_flag == RC_DEFAULT) apc = 0;
1010 1010 if (nrpos_flag == RC_DEFAULT) nrpos = 1;
1011 1011 if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI;
1012 1012 if (rps_flag == RC_DEFAULT) rps = DEFHZ;
1013 1013 if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI;
1014 1014 }
1015 1015
1016 1016 if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) ||
1017 1017 (maxcontig == -1)) {
1018 1018 long maxtrax = get_max_track_size(fsi);
1019 1019 maxcontig = maxtrax / bsize;
1020 1020
1021 1021 } else {
1022 1022 maxcontig = tmpmaxcontig;
1023 1023 }
1024 1024 dprintf(("DeBuG maxcontig : %ld\n", maxcontig));
1025 1025
1026 1026 if (rotdelay == -1) { /* default by newfs and mkfs */
1027 1027 rotdelay = ROTDELAY;
1028 1028 }
1029 1029
1030 1030 if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */
1031 1031 cpg = DESCPG;
1032 1032 }
1033 1033 dprintf(("DeBuG cpg : %ld\n", cpg));
1034 1034
1035 1035 /*
1036 1036 * Now that we have the semi-sane args, either positional, via -o,
1037 1037 * or by defaulting, handle inter-dependencies and range checks.
1038 1038 */
1039 1039
1040 1040 /*
1041 1041 * Settle the file system block size first, since it's a fixed
1042 1042 * parameter once set and so many other parameters, including
1043 1043 * max_fssize, depend on it.
1044 1044 */
1045 1045 range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE,
1046 1046 bsize_flag);
1047 1047
1048 1048 if (!POWEROF2(bsize)) {
1049 1049 (void) fprintf(stderr,
1050 1050 gettext("block size must be a power of 2, not %ld\n"),
1051 1051 bsize);
1052 1052 bsize = DESBLKSIZE;
1053 1053 (void) fprintf(stderr,
1054 1054 gettext("mkfs: bsize reset to default %ld\n"),
1055 1055 bsize);
1056 1056 }
1057 1057
1058 1058 if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) {
1059 1059 (void) fprintf(stderr, gettext(
1060 1060 "Warning: the requested size of this file system\n"
1061 1061 "(%lld sectors) is greater than the size of the\n"
1062 1062 "device reported by the driver (%lld sectors).\n"
1063 1063 "However, a read of the device at the requested size\n"
1064 1064 "does succeed, so the requested size will be used.\n"),
1065 1065 fssize_db, max_fssize);
1066 1066 max_fssize = fssize_db;
1067 1067 }
1068 1068 /*
1069 1069 * Since the maximum allocatable unit (the frag) must be less than
1070 1070 * or equal to bsize, and the number of frags must be less than or
1071 1071 * equal to INT_MAX, the total size of the file system (in
1072 1072 * bytes) must be less than or equal to bsize * INT_MAX.
1073 1073 */
1074 1074
1075 1075 if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX)
1076 1076 max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX;
1077 1077
1078 1078 range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1);
1079 1079
1080 1080 if (fssize_db >= SECTORS_PER_TERABYTE) {
1081 1081 mtb = 'y';
1082 1082 if (!in_64bit_mode()) {
1083 1083 (void) fprintf(stderr, gettext(
1084 1084 "mkfs: Warning: Creating a file system greater than 1 terabyte on a\n"
1085 1085 " system running a 32-bit kernel. This file system will not be\n"
1086 1086 " accessible until the system is rebooted with a 64-bit kernel.\n"));
1087 1087 }
1088 1088 }
1089 1089 dprintf(("DeBuG mtb : %c\n", mtb));
1090 1090
1091 1091 /*
1092 1092 * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M)
1093 1093 * commands had problems in correctly handling the "native" geometries
1094 1094 * for various storage devices.
1095 1095 *
1096 1096 * To handle the new age disks, mkfs_ufs(1M) will use the EFI style
1097 1097 * for non-EFI disks that are larger than the CHS addressing limit
1098 1098 * ( > 8GB approx ) and ignore the disk geometry information for
1099 1099 * these drives. This is what is currently done for multi-terrabyte
1100 1100 * filesystems on EFI disks.
1101 1101 *
1102 1102 * However if the user asked for a specific layout by supplying values
1103 1103 * for even one of the three parameters (nsect, ntrack, cpg), honour
1104 1104 * the user supplied parameters.
1105 1105 *
1106 1106 * Choosing EFI style or native geometry style can make a lot of
1107 1107 * difference, because the size of a cylinder group is dependent on
1108 1108 * this choice. This in turn means that the position of alternate
1109 1109 * superblocks varies depending on the style chosen. It is not
1110 1110 * necessary that all disks of size > CHSLIMIT have EFI style layout.
1111 1111 * There can be disks which are > CHSLIMIT size, but have native
1112 1112 * geometry style layout, thereby warranting the need for alternate
1113 1113 * logic in superblock detection.
1114 1114 */
1115 1115 if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK ||
1116 1116 DEFAULT_SECT_TRAK_CPG)) {
1117 1117 /*
1118 1118 * "-1" indicates that we were called from newfs and ntracks
1119 1119 * was not specified in newfs command line. Calculate nsect
1120 1120 * and ntrack in the same manner as newfs.
1121 1121 *
1122 1122 * This is required because, the defaults for nsect and ntrack
1123 1123 * is hardcoded in mkfs, whereas to generate the alternate
1124 1124 * superblock locations for the -N option, there is a need for
1125 1125 * the geometry based values that newfs would have arrived at.
1126 1126 * Newfs would have arrived at these values as below.
1127 1127 */
1128 1128 if (label_type == LABEL_TYPE_EFI ||
1129 1129 label_type == LABEL_TYPE_OTHER) {
1130 1130 use_efi_dflts = 1;
1131 1131 retry = 1;
1132 1132 } else if (ioctl(fsi, DKIOCGGEOM, &dkg)) {
1133 1133 dprintf(("%s: Unable to read Disk geometry", fsys));
1134 1134 perror(gettext("Unable to read Disk geometry"));
1135 1135 lockexit(32);
1136 1136 } else {
1137 1137 nsect = dkg.dkg_nsect;
1138 1138 ntrack = dkg.dkg_nhead;
1139 1139 #ifdef i386 /* Bug 1170182 */
1140 1140 if (ntrack > 32 && (ntrack % 16) != 0) {
1141 1141 ntrack -= (ntrack % 16);
1142 1142 }
1143 1143 #endif
1144 1144 if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) {
1145 1145 dprintf(("DeBuG Unable to determine if %s is"
1146 1146 " Removable Media. Proceeding with system"
1147 1147 " determined parameters.\n", fsys));
1148 1148 isremovable = 0;
1149 1149 }
1150 1150 if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) {
1151 1151 dprintf(("DeBuG Unable to determine if %s is"
1152 1152 " Hotpluggable Media. Proceeding with "
1153 1153 "system determined parameters.\n", fsys));
1154 1154 ishotpluggable = 0;
1155 1155 }
1156 1156 if ((((diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead *
1157 1157 dkg.dkg_nsect) > CHSLIMIT) || isremovable ||
1158 1158 ishotpluggable) {
1159 1159 use_efi_dflts = 1;
1160 1160 retry = 1;
1161 1161 }
1162 1162 }
1163 1163 }
1164 1164 dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT,
1165 1165 (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect));
1166 1166 dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d "
1167 1167 "use_efi_dflts = %d\n", label_type, isremovable, ishotpluggable,
1168 1168 use_efi_dflts));
1169 1169
1170 1170 /*
1171 1171 * For the newfs -N case, even if the disksize is > CHSLIMIT, do not
1172 1172 * blindly follow EFI style. If the fs_version indicates a geometry
1173 1173 * based layout, try that one first. If it fails we can always try the
1174 1174 * other logic.
1175 1175 *
1176 1176 * If we were called from growfs, we will have a problem if we mix
1177 1177 * and match the filesystem creation and growth styles. For example,
1178 1178 * if we create using EFI style, we have to also grow using EFI
1179 1179 * style. So follow the style indicated by the fs_version.
1180 1180 *
1181 1181 * Read and verify the primary superblock. If it looks sane, use the
1182 1182 * fs_version from the superblock. If the primary superblock does
1183 1183 * not look good, read and verify the first alternate superblock at
1184 1184 * ALTSB. Use the fs_version to decide whether to use the
1185 1185 * EFI style logic or the old geometry based logic to calculate
1186 1186 * the alternate superblock locations.
1187 1187 */
1188 1188 if ((Nflag && use_efi_dflts) || (grow)) {
1189 1189 if (grow && ntrack_flag != RC_DEFAULT)
1190 1190 goto start_fs_creation;
1191 1191 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize,
1192 1192 (char *)&altsblock);
1193 1193 ret = checksblock(altsblock, 1);
1194 1194
1195 1195 if (!ret) {
1196 1196 if (altsblock.fs_magic == MTB_UFS_MAGIC) {
1197 1197 mtb = 'y';
1198 1198 goto start_fs_creation;
1199 1199 }
1200 1200 use_efi_dflts = (altsblock.fs_version ==
1201 1201 UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
1202 1202 } else {
1203 1203 /*
1204 1204 * The primary superblock didn't help in determining
1205 1205 * the fs_version. Try the first alternate superblock.
1206 1206 */
1207 1207 dprintf(("DeBuG checksblock() failed - error : %d"
1208 1208 " for sb : %d\n", ret, SBOFF/sectorsize));
1209 1209 rdfs((diskaddr_t)ALTSB, (int)sbsize,
1210 1210 (char *)&altsblock);
1211 1211 ret = checksblock(altsblock, 1);
1212 1212
1213 1213 if (!ret) {
1214 1214 if (altsblock.fs_magic == MTB_UFS_MAGIC) {
1215 1215 mtb = 'y';
1216 1216 goto start_fs_creation;
1217 1217 }
1218 1218 use_efi_dflts = (altsblock.fs_version ==
1219 1219 UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
1220 1220 }
1221 1221 dprintf(("DeBuG checksblock() returned : %d"
1222 1222 " for sb : %d\n", ret, ALTSB));
1223 1223 }
1224 1224 }
1225 1225
1226 1226 geom_nsect = nsect;
1227 1227 geom_ntrack = ntrack;
1228 1228 geom_cpg = cpg;
1229 1229 dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n",
1230 1230 geom_nsect, geom_ntrack, geom_cpg));
1231 1231
1232 1232 start_fs_creation:
1233 1233 retry_alternate_logic:
1234 1234 invalid_sb_cnt = 0;
1235 1235 cg_too_small = 0;
1236 1236 if (use_efi_dflts) {
1237 1237 nsect = DEF_SECTORS_EFI;
1238 1238 ntrack = DEF_TRACKS_EFI;
1239 1239 cpg = DESCPG;
1240 1240 dprintf(("\nDeBuG Using EFI defaults\n"));
1241 1241 } else {
1242 1242 nsect = geom_nsect;
1243 1243 ntrack = geom_ntrack;
1244 1244 cpg = geom_cpg;
1245 1245 dprintf(("\nDeBuG Using Geometry\n"));
1246 1246 /*
1247 1247 * 32K based on max block size of 64K, and rotational layout
1248 1248 * test of nsect <= (256 * sectors/block). Current block size
1249 1249 * limit is not 64K, but it's growing soon.
1250 1250 */
1251 1251 range_check(&nsect, "nsect", 1, 32768, DFLNSECT, nsect_flag);
1252 1252 /*
1253 1253 * ntrack is the number of tracks per cylinder.
1254 1254 * The ntrack value must be between 1 and the total number of
1255 1255 * sectors in the file system.
1256 1256 */
1257 1257 range_check(&ntrack, "ntrack", 1,
1258 1258 fssize_db > INT_MAX ? INT_MAX : (uint32_t)fssize_db,
1259 1259 DFLNTRAK, ntrack_flag);
1260 1260 }
1261 1261
1262 1262 range_check(&apc, "apc", 0, nsect - 1, 0, apc_flag);
1263 1263
1264 1264 if (mtb == 'y')
1265 1265 fragsize = bsize;
1266 1266
1267 1267 range_check(&fragsize, "fragsize", sectorsize, bsize,
1268 1268 MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)), fragsize_flag);
1269 1269
1270 1270 if ((bsize / MAXFRAG) > fragsize) {
1271 1271 (void) fprintf(stderr, gettext(
1272 1272 "fragment size %ld is too small, minimum with block size %ld is %ld\n"),
1273 1273 fragsize, bsize, bsize / MAXFRAG);
1274 1274 (void) fprintf(stderr,
1275 1275 gettext("mkfs: fragsize reset to minimum %ld\n"),
1276 1276 bsize / MAXFRAG);
1277 1277 fragsize = bsize / MAXFRAG;
1278 1278 }
1279 1279
1280 1280 if (!POWEROF2(fragsize)) {
1281 1281 (void) fprintf(stderr,
1282 1282 gettext("fragment size must be a power of 2, not %ld\n"),
1283 1283 fragsize);
1284 1284 fragsize = MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize));
1285 1285 (void) fprintf(stderr,
1286 1286 gettext("mkfs: fragsize reset to %ld\n"),
1287 1287 fragsize);
1288 1288 }
1289 1289
1290 1290 /* At this point, bsize must be >= fragsize, so no need to check it */
1291 1291
1292 1292 if (bsize < PAGESIZE) {
1293 1293 (void) fprintf(stderr, gettext(
1294 1294 "WARNING: filesystem block size (%ld) is smaller than "
1295 1295 "memory page size (%ld).\nResulting filesystem can not be "
1296 1296 "mounted on this system.\n\n"),
1297 1297 bsize, (long)PAGESIZE);
1298 1298 }
1299 1299
1300 1300 range_check(&rps, "rps", 1, 1000, DEFHZ, rps_flag);
1301 1301 range_check(&minfree, "free", 0, 99, MINFREE, minfree_flag);
1302 1302 range_check(&nrpos, "nrpos", 1, nsect, MIN(nsect, NRPOS), nrpos_flag);
1303 1303
1304 1304 /*
1305 1305 * nbpi is variable, but 2MB seems a reasonable upper limit,
1306 1306 * as 4MB tends to cause problems (using otherwise-default
1307 1307 * parameters). The true limit is where we end up with one
1308 1308 * inode per cylinder group. If this file system is being
1309 1309 * configured for multi-terabyte access, nbpi must be at least 1MB.
1310 1310 */
1311 1311 if (mtb == 'y' && nbpi < MTB_NBPI) {
1312 1312 if (nbpi_flag != RC_DEFAULT)
1313 1313 (void) fprintf(stderr, gettext("mkfs: bad value for "
1314 1314 "nbpi: must be at least 1048576 for multi-terabyte,"
1315 1315 " nbpi reset to default 1048576\n"));
1316 1316 nbpi = MTB_NBPI;
1317 1317 }
1318 1318
1319 1319 if (mtb == 'y')
1320 1320 range_check(&nbpi, "nbpi", MTB_NBPI, 2 * MB, MTB_NBPI,
1321 1321 nbpi_flag);
1322 1322 else
1323 1323 range_check(&nbpi, "nbpi", DEV_BSIZE, 2 * MB, NBPI, nbpi_flag);
1324 1324
1325 1325 /*
1326 1326 * maxcpg is another variably-limited parameter. Calculate
1327 1327 * the limit based on what we've got for its dependent
1328 1328 * variables. Effectively, it's how much space is left in the
1329 1329 * superblock after all the other bits are accounted for. We
1330 1330 * only fill in sblock fields so we can use MAXIpG.
1331 1331 *
1332 1332 * If the calculation of maxcpg below (for the mtb == 'n'
1333 1333 * case) is changed, update newfs as well.
1334 1334 *
1335 1335 * For old-style, non-MTB format file systems, use the old
1336 1336 * algorithm for calculating the maximum cylinder group size,
1337 1337 * even though it limits the cylinder group more than necessary.
1338 1338 * Since layout can affect performance, we don't want to change
1339 1339 * the default layout for non-MTB file systems at this time.
1340 1340 * However, for MTB file systems, use the new maxcpg calculation,
1341 1341 * which really maxes out the cylinder group size.
1342 1342 */
1343 1343
1344 1344 sblock.fs_bsize = bsize;
1345 1345 sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
1346 1346
1347 1347 if (mtb == 'n') {
1348 1348 maxcpg = (bsize - sizeof (struct cg) -
1349 1349 howmany(MAXIpG(&sblock), NBBY)) /
1350 1350 (sizeof (long) + nrpos * sizeof (short) +
1351 1351 nsect / (MAXFRAG * NBBY));
1352 1352 } else {
1353 1353 maxcpg = compute_maxcpg(bsize, fragsize, nbpi, nrpos,
1354 1354 nsect * ntrack);
1355 1355 }
1356 1356
1357 1357 dprintf(("DeBuG cpg : %ld\n", cpg));
1358 1358 /*
1359 1359 * Increase the cpg to maxcpg if either newfs was invoked
1360 1360 * with -T option or if mkfs wants to create a mtb file system
1361 1361 * and if the user has not specified the cpg.
1362 1362 */
1363 1363 if (cpg == -1 || (mtb == 'y' && cpg_flag == RC_DEFAULT))
1364 1364 cpg = maxcpg;
1365 1365 dprintf(("DeBuG cpg : %ld\n", cpg));
1366 1366
1367 1367 /*
1368 1368 * mincpg is variable in complex ways, so we really can't
1369 1369 * do a sane lower-end limit check at this point.
1370 1370 */
1371 1371 range_check(&cpg, "cgsize", 1, maxcpg, MIN(maxcpg, DESCPG), cpg_flag);
1372 1372
1373 1373 /*
1374 1374 * get the controller info
1375 1375 */
1376 1376 ismdd = 0;
1377 1377 islog = 0;
1378 1378 islogok = 0;
1379 1379 waslog = 0;
1380 1380
1381 1381 if (ioctl(fsi, DKIOCINFO, &dkcinfo) == 0)
1382 1382 /*
1383 1383 * if it is an MDD (disksuite) device
1384 1384 */
1385 1385 if (dkcinfo.dki_ctype == DKC_MD) {
1386 1386 ismdd++;
1387 1387 /*
1388 1388 * check the logging device
1389 1389 */
1390 1390 if (ioctl(fsi, _FIOISLOG, NULL) == 0) {
1391 1391 islog++;
1392 1392 if (ioctl(fsi, _FIOISLOGOK, NULL) == 0)
1393 1393 islogok++;
1394 1394 }
1395 1395 }
1396 1396
1397 1397 /*
1398 1398 * Do not grow the file system, but print on stdout the maximum
1399 1399 * size in sectors to which the file system can be increased.
1400 1400 * The calculated size is limited by fssize_db.
1401 1401 * Note that we don't lock the filesystem and therefore under rare
1402 1402 * conditions (the filesystem is mounted, the free block count is
1403 1403 * almost zero, and the superuser is still changing it) the calculated
1404 1404 * size can be imprecise.
1405 1405 */
1406 1406 if (Pflag) {
1407 1407 (void) printf("%llu\n", probe_summaryinfo());
1408 1408 exit(0);
1409 1409 }
1410 1410
1411 1411 /*
1412 1412 * If we're growing an existing filesystem, then we're about
1413 1413 * to start doing things that can require recovery efforts if
1414 1414 * we get interrupted, so make sure we get a chance to do so.
1415 1415 */
1416 1416 if (grow) {
1417 1417 sigact.sa_handler = recover_from_sigint;
1418 1418 sigemptyset(&sigact.sa_mask);
1419 1419 sigact.sa_flags = SA_RESTART;
1420 1420
1421 1421 if (sigaction(SIGINT, &sigact, (struct sigaction *)NULL) < 0) {
1422 1422 perror(gettext("Could not register SIGINT handler"));
1423 1423 lockexit(3);
1424 1424 }
1425 1425 }
1426 1426
1427 1427 if (!Nflag) {
1428 1428 /*
1429 1429 * Check if MNTTAB is trustable
1430 1430 */
1431 1431 if (statvfs64(MNTTAB, &fs) < 0) {
1432 1432 (void) fprintf(stderr, gettext("can't statvfs %s\n"),
1433 1433 MNTTAB);
1434 1434 exit(32);
1435 1435 }
1436 1436
1437 1437 if (strcmp(MNTTYPE_MNTFS, fs.f_basetype) != 0) {
1438 1438 (void) fprintf(stderr, gettext(
1439 1439 "%s file system type is not %s, can't mkfs\n"),
1440 1440 MNTTAB, MNTTYPE_MNTFS);
1441 1441 exit(32);
1442 1442 }
1443 1443
1444 1444 special = getfullblkname(fsys);
1445 1445 checkdev(fsys, special);
1446 1446
1447 1447 /*
1448 1448 * If we found the block device name,
1449 1449 * then check the mount table.
1450 1450 * if mounted, and growing write lock the file system
1451 1451 *
1452 1452 */
1453 1453 if ((special != NULL) && (*special != '\0')) {
1454 1454 if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
1455 1455 (void) fprintf(stderr, gettext(
1456 1456 "can't open %s\n"), MNTTAB);
1457 1457 exit(32);
1458 1458 }
1459 1459 while ((getmntent(mnttab, &mntp)) == NULL) {
1460 1460 if (grow) {
1461 1461 checkmount(&mntp, special);
1462 1462 continue;
1463 1463 }
1464 1464 if (strcmp(special, mntp.mnt_special) == 0) {
1465 1465 (void) fprintf(stderr, gettext(
1466 1466 "%s is mounted, can't mkfs\n"),
1467 1467 special);
1468 1468 exit(32);
1469 1469 }
1470 1470 }
1471 1471 (void) fclose(mnttab);
1472 1472 }
1473 1473
1474 1474 if (directory && (ismounted == 0)) {
1475 1475 (void) fprintf(stderr, gettext("%s is not mounted\n"),
1476 1476 special);
1477 1477 lockexit(32);
1478 1478 }
1479 1479
1480 1480 fso = (grow) ? open64(fsys, O_WRONLY) : creat64(fsys, 0666);
1481 1481 if (fso < 0) {
1482 1482 saverr = errno;
1483 1483 (void) fprintf(stderr,
1484 1484 gettext("%s: cannot create: %s\n"),
1485 1485 fsys, strerror(saverr));
1486 1486 lockexit(32);
1487 1487 }
1488 1488
1489 1489 } else {
1490 1490
1491 1491 /*
1492 1492 * For the -N case, a file descriptor is needed for the llseek()
1493 1493 * in wtfs(). See the comment in wtfs() for more information.
1494 1494 *
1495 1495 * Get a file descriptor that's read-only so that this code
1496 1496 * doesn't accidentally write to the file.
1497 1497 */
1498 1498 fso = open64(fsys, O_RDONLY);
1499 1499 if (fso < 0) {
1500 1500 saverr = errno;
1501 1501 (void) fprintf(stderr, gettext("%s: cannot open: %s\n"),
1502 1502 fsys, strerror(saverr));
1503 1503 lockexit(32);
1504 1504 }
1505 1505 }
1506 1506
1507 1507 /*
1508 1508 * Check the media sector size
1509 1509 */
1510 1510 if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) {
1511 1511 if (dkminfo.dki_lbsize != 0 &&
1512 1512 POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) &&
1513 1513 dkminfo.dki_lbsize != DEV_BSIZE) {
1514 1514 fprintf(stderr,
1515 1515 gettext("The device sector size %u is not "
1516 1516 "supported by ufs!\n"), dkminfo.dki_lbsize);
1517 1517 (void) close(fso);
1518 1518 exit(1);
1519 1519 }
1520 1520 }
1521 1521
1522 1522 /*
1523 1523 * seed random # generator (for ic_generation)
1524 1524 */
1525 1525 #ifdef MKFS_DEBUG
1526 1526 srand48(12962); /* reproducible results */
1527 1527 #else
1528 1528 srand48((long)(time((time_t *)NULL) + getpid()));
1529 1529 #endif
1530 1530
1531 1531 if (grow) {
1532 1532 growinit(fsys);
1533 1533 goto grow00;
1534 1534 }
1535 1535
1536 1536 /*
1537 1537 * Validate the given file system size.
1538 1538 * Verify that its last block can actually be accessed.
1539 1539 *
1540 1540 * Note: it's ok to use sblock as a buffer because it is immediately
1541 1541 * overwritten by the rdfs() of the superblock in the next line.
1542 1542 *
1543 1543 * ToDo: Because the size checking is done in rdfs()/wtfs(), the
1544 1544 * error message for specifying an illegal size is very unfriendly.
1545 1545 * In the future, one could replace the rdfs()/wtfs() calls
1546 1546 * below with in-line calls to read() or write(). This allows better
1547 1547 * error messages to be put in place.
1548 1548 */
1549 1549 rdfs(fssize_db - 1, (int)sectorsize, (char *)&sblock);
1550 1550
1551 1551 /*
1552 1552 * make the fs unmountable
1553 1553 */
1554 1554 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
1555 1555 sblock.fs_magic = -1;
1556 1556 sblock.fs_clean = FSBAD;
1557 1557 sblock.fs_state = FSOKAY - sblock.fs_time;
1558 1558 wtfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
1559 1559 bzero(&sblock, (size_t)sbsize);
1560 1560
1561 1561 sblock.fs_nsect = nsect;
1562 1562 sblock.fs_ntrak = ntrack;
1563 1563
1564 1564 /*
1565 1565 * Validate specified/determined spc
1566 1566 * and calculate minimum cylinders per group.
1567 1567 */
1568 1568
1569 1569 /*
1570 1570 * sectors/cyl = tracks/cyl * sectors/track
1571 1571 */
1572 1572 sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
1573 1573
1574 1574 grow00:
1575 1575 if (apc_flag) {
1576 1576 sblock.fs_spc -= apc;
1577 1577 }
1578 1578 /*
1579 1579 * Have to test for this separately from apc_flag, due to
1580 1580 * the growfs case....
1581 1581 */
1582 1582 if (sblock.fs_spc != sblock.fs_ntrak * sblock.fs_nsect) {
1583 1583 spc_flag = 1;
1584 1584 }
1585 1585 if (grow)
1586 1586 goto grow10;
1587 1587
1588 1588 sblock.fs_nrpos = nrpos;
1589 1589 sblock.fs_bsize = bsize;
1590 1590 sblock.fs_fsize = fragsize;
1591 1591 sblock.fs_minfree = minfree;
1592 1592
1593 1593 grow10:
1594 1594 if (nbpi < sblock.fs_fsize) {
1595 1595 (void) fprintf(stderr, gettext(
1596 1596 "warning: wasteful data byte allocation / inode (nbpi):\n"));
1597 1597 (void) fprintf(stderr, gettext(
1598 1598 "%ld smaller than allocatable fragment size of %d\n"),
1599 1599 nbpi, sblock.fs_fsize);
1600 1600 }
1601 1601 if (grow)
1602 1602 goto grow20;
1603 1603
1604 1604 if (opt == 's')
1605 1605 sblock.fs_optim = FS_OPTSPACE;
1606 1606 else
1607 1607 sblock.fs_optim = FS_OPTTIME;
1608 1608
1609 1609 sblock.fs_bmask = ~(sblock.fs_bsize - 1);
1610 1610 sblock.fs_fmask = ~(sblock.fs_fsize - 1);
1611 1611 /*
1612 1612 * Planning now for future expansion.
1613 1613 */
1614 1614 #if defined(_BIG_ENDIAN)
1615 1615 sblock.fs_qbmask.val[0] = 0;
1616 1616 sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
1617 1617 sblock.fs_qfmask.val[0] = 0;
1618 1618 sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
1619 1619 #endif
1620 1620 #if defined(_LITTLE_ENDIAN)
1621 1621 sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
1622 1622 sblock.fs_qbmask.val[1] = 0;
1623 1623 sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
1624 1624 sblock.fs_qfmask.val[1] = 0;
1625 1625 #endif
1626 1626 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
1627 1627 sblock.fs_bshift++;
1628 1628 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
1629 1629 sblock.fs_fshift++;
1630 1630 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
1631 1631 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
1632 1632 sblock.fs_fragshift++;
1633 1633 if (sblock.fs_frag > MAXFRAG) {
1634 1634 (void) fprintf(stderr, gettext(
1635 1635 "fragment size %d is too small, minimum with block size %d is %d\n"),
1636 1636 sblock.fs_fsize, sblock.fs_bsize,
1637 1637 sblock.fs_bsize / MAXFRAG);
1638 1638 lockexit(32);
1639 1639 }
1640 1640 sblock.fs_nindir = sblock.fs_bsize / sizeof (daddr32_t);
1641 1641 sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
1642 1642 sblock.fs_nspf = sblock.fs_fsize / sectorsize;
1643 1643 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
1644 1644 sblock.fs_fsbtodb++;
1645 1645
1646 1646 /*
1647 1647 * Compute the super-block, cylinder group, and inode blocks.
1648 1648 * Note that these "blkno" are really fragment addresses.
1649 1649 * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16,
1650 1650 * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so
1651 1651 * important: only 1 FS block is allocated for the cg struct (fragment
1652 1652 * numbers 24 through 31).
1653 1653 */
1654 1654 sblock.fs_sblkno =
1655 1655 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
1656 1656 sblock.fs_cblkno = (daddr32_t)(sblock.fs_sblkno +
1657 1657 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
1658 1658 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
1659 1659
1660 1660 sblock.fs_cgoffset = roundup(
1661 1661 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
1662 1662 for (sblock.fs_cgmask = -1, i = sblock.fs_ntrak; i > 1; i >>= 1)
1663 1663 sblock.fs_cgmask <<= 1;
1664 1664 if (!POWEROF2(sblock.fs_ntrak))
1665 1665 sblock.fs_cgmask <<= 1;
1666 1666 /*
1667 1667 * Validate specified/determined spc
1668 1668 * and calculate minimum cylinders per group.
1669 1669 */
1670 1670
1671 1671 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
1672 1672 sblock.fs_cpc > 1 && (i & 1) == 0;
1673 1673 sblock.fs_cpc >>= 1, i >>= 1)
1674 1674 /* void */;
1675 1675 mincpc = sblock.fs_cpc;
1676 1676
1677 1677 /* if these calculations are changed, check dump_fscmd also */
1678 1678 bpcg = (uint64_t)sblock.fs_spc * sectorsize;
1679 1679 inospercg = (uint64_t)roundup(bpcg / sizeof (struct dinode),
1680 1680 INOPB(&sblock));
1681 1681 if (inospercg > MAXIpG(&sblock))
1682 1682 inospercg = MAXIpG(&sblock);
1683 1683 used = (uint64_t)(sblock.fs_iblkno + inospercg /
1684 1684 INOPF(&sblock)) * NSPF(&sblock);
1685 1685 mincpgcnt = (long)howmany((uint64_t)sblock.fs_cgoffset *
1686 1686 (~sblock.fs_cgmask) + used, sblock.fs_spc);
1687 1687 mincpg = roundup(mincpgcnt, mincpc);
1688 1688 /*
1689 1689 * Insure that cylinder group with mincpg has enough space
1690 1690 * for block maps
1691 1691 */
1692 1692 sblock.fs_cpg = mincpg;
1693 1693 sblock.fs_ipg = (int32_t)inospercg;
1694 1694 mapcramped = 0;
1695 1695
1696 1696 /*
1697 1697 * Make sure the cg struct fits within the file system block.
1698 1698 * Use larger block sizes until it fits
1699 1699 */
1700 1700 while (CGSIZE(&sblock) > sblock.fs_bsize) {
1701 1701 mapcramped = 1;
1702 1702 if (sblock.fs_bsize < MAXBSIZE) {
1703 1703 sblock.fs_bsize <<= 1;
1704 1704 if ((i & 1) == 0) {
1705 1705 i >>= 1;
1706 1706 } else {
1707 1707 sblock.fs_cpc <<= 1;
1708 1708 mincpc <<= 1;
1709 1709 mincpg = roundup(mincpgcnt, mincpc);
1710 1710 sblock.fs_cpg = mincpg;
1711 1711 }
1712 1712 sblock.fs_frag <<= 1;
1713 1713 sblock.fs_fragshift += 1;
1714 1714 if (sblock.fs_frag <= MAXFRAG)
1715 1715 continue;
1716 1716 }
1717 1717
1718 1718 /*
1719 1719 * Looped far enough. The fragment is now as large as the
1720 1720 * filesystem block!
1721 1721 */
1722 1722 if (sblock.fs_fsize == sblock.fs_bsize) {
1723 1723 (void) fprintf(stderr, gettext(
1724 1724 "There is no block size that can support this disk\n"));
1725 1725 lockexit(32);
1726 1726 }
1727 1727
1728 1728 /*
1729 1729 * Try a larger fragment. Double the fragment size.
1730 1730 */
1731 1731 sblock.fs_frag >>= 1;
1732 1732 sblock.fs_fragshift -= 1;
1733 1733 sblock.fs_fsize <<= 1;
1734 1734 sblock.fs_nspf <<= 1;
1735 1735 }
1736 1736 /*
1737 1737 * Insure that cylinder group with mincpg has enough space for inodes
1738 1738 */
1739 1739 inodecramped = 0;
1740 1740 used *= sectorsize;
1741 1741 nbytes64 = (uint64_t)mincpg * bpcg - used;
1742 1742 inospercg = (uint64_t)roundup((nbytes64 / nbpi), INOPB(&sblock));
1743 1743 sblock.fs_ipg = (int32_t)inospercg;
1744 1744 while (inospercg > MAXIpG(&sblock)) {
1745 1745 inodecramped = 1;
1746 1746 if (mincpc == 1 || sblock.fs_frag == 1 ||
1747 1747 sblock.fs_bsize == MINBSIZE)
1748 1748 break;
1749 1749 nbytes64 = (uint64_t)mincpg * bpcg - used;
1750 1750 (void) fprintf(stderr,
1751 1751 gettext("With a block size of %d %s %lu\n"),
1752 1752 sblock.fs_bsize, gettext("minimum bytes per inode is"),
1753 1753 (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
1754 1754 sblock.fs_bsize >>= 1;
1755 1755 sblock.fs_frag >>= 1;
1756 1756 sblock.fs_fragshift -= 1;
1757 1757 mincpc >>= 1;
1758 1758 sblock.fs_cpg = roundup(mincpgcnt, mincpc);
1759 1759 if (CGSIZE(&sblock) > sblock.fs_bsize) {
1760 1760 sblock.fs_bsize <<= 1;
1761 1761 break;
1762 1762 }
1763 1763 mincpg = sblock.fs_cpg;
1764 1764 nbytes64 = (uint64_t)mincpg * bpcg - used;
1765 1765 inospercg = (uint64_t)roundup((nbytes64 / nbpi),
1766 1766 INOPB(&sblock));
1767 1767 sblock.fs_ipg = (int32_t)inospercg;
1768 1768 }
1769 1769 if (inodecramped) {
1770 1770 if (inospercg > MAXIpG(&sblock)) {
1771 1771 nbytes64 = (uint64_t)mincpg * bpcg - used;
1772 1772 (void) fprintf(stderr, gettext(
1773 1773 "Minimum bytes per inode is %d\n"),
1774 1774 (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
1775 1775 } else if (!mapcramped) {
1776 1776 (void) fprintf(stderr, gettext(
1777 1777 "With %ld bytes per inode, minimum cylinders per group is %ld\n"),
1778 1778 nbpi, mincpg);
1779 1779 }
1780 1780 }
1781 1781 if (mapcramped) {
1782 1782 (void) fprintf(stderr, gettext(
1783 1783 "With %d sectors per cylinder, minimum cylinders "
1784 1784 "per group is %ld\n"),
1785 1785 sblock.fs_spc, mincpg);
1786 1786 }
1787 1787 if (inodecramped || mapcramped) {
1788 1788 /*
1789 1789 * To make this at least somewhat comprehensible in
1790 1790 * the world of i18n, figure out what we're going to
1791 1791 * say and then say it all at one time. The days of
1792 1792 * needing to scrimp on string space are behind us....
1793 1793 */
1794 1794 if ((sblock.fs_bsize != bsize) &&
1795 1795 (sblock.fs_fsize != fragsize)) {
1796 1796 (void) fprintf(stderr, gettext(
1797 1797 "This requires the block size to be changed from %ld to %d\n"
1798 1798 "and the fragment size to be changed from %ld to %d\n"),
1799 1799 bsize, sblock.fs_bsize,
1800 1800 fragsize, sblock.fs_fsize);
1801 1801 } else if (sblock.fs_bsize != bsize) {
1802 1802 (void) fprintf(stderr, gettext(
1803 1803 "This requires the block size to be changed from %ld to %d\n"),
1804 1804 bsize, sblock.fs_bsize);
1805 1805 } else if (sblock.fs_fsize != fragsize) {
1806 1806 (void) fprintf(stderr, gettext(
1807 1807 "This requires the fragment size to be changed from %ld to %d\n"),
1808 1808 fragsize, sblock.fs_fsize);
1809 1809 } else {
1810 1810 (void) fprintf(stderr, gettext(
1811 1811 "Unable to make filesystem fit with the given constraints\n"));
1812 1812 }
1813 1813 (void) fprintf(stderr, gettext(
1814 1814 "Please re-run mkfs with corrected parameters\n"));
1815 1815 lockexit(32);
1816 1816 }
1817 1817 /*
1818 1818 * Calculate the number of cylinders per group
1819 1819 */
1820 1820 sblock.fs_cpg = cpg;
1821 1821 if (sblock.fs_cpg % mincpc != 0) {
1822 1822 (void) fprintf(stderr, gettext(
1823 1823 "Warning: cylinder groups must have a multiple "
1824 1824 "of %ld cylinders with the given\n parameters\n"),
1825 1825 mincpc);
1826 1826 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
1827 1827 (void) fprintf(stderr, gettext("Rounded cgsize up to %d\n"),
1828 1828 sblock.fs_cpg);
1829 1829 }
1830 1830 /*
1831 1831 * Must insure there is enough space for inodes
1832 1832 */
1833 1833 /* if these calculations are changed, check dump_fscmd also */
1834 1834 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1835 1835 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), INOPB(&sblock));
1836 1836
1837 1837 /*
1838 1838 * Slim down cylinders per group, until the inodes can fit.
1839 1839 */
1840 1840 while (sblock.fs_ipg > MAXIpG(&sblock)) {
1841 1841 inodecramped = 1;
1842 1842 sblock.fs_cpg -= mincpc;
1843 1843 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1844 1844 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
1845 1845 INOPB(&sblock));
1846 1846 }
1847 1847 /*
1848 1848 * Must insure there is enough space to hold block map.
1849 1849 * Cut down on cylinders per group, until the cg struct fits in a
1850 1850 * filesystem block.
1851 1851 */
1852 1852 while (CGSIZE(&sblock) > sblock.fs_bsize) {
1853 1853 mapcramped = 1;
1854 1854 sblock.fs_cpg -= mincpc;
1855 1855 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1856 1856 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
1857 1857 INOPB(&sblock));
1858 1858 }
1859 1859 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
1860 1860 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
1861 1861 (void) fprintf(stderr,
1862 1862 gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n"));
1863 1863 lockexit(32);
1864 1864 }
1865 1865 if (sblock.fs_cpg < mincpg) {
1866 1866 (void) fprintf(stderr, gettext(
1867 1867 "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"),
1868 1868 mincpg);
1869 1869 lockexit(32);
1870 1870 }
1871 1871 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
1872 1872 grow20:
1873 1873 /*
1874 1874 * Now have size for file system and nsect and ntrak.
1875 1875 * Determine number of cylinders and blocks in the file system.
1876 1876 */
1877 1877 fssize_frag = (int64_t)dbtofsb(&sblock, fssize_db);
1878 1878 if (fssize_frag > INT_MAX) {
1879 1879 (void) fprintf(stderr, gettext(
1880 1880 "There are too many fragments in the system, increase fragment size\n"),
1881 1881 mincpg);
1882 1882 lockexit(32);
1883 1883 }
1884 1884 sblock.fs_size = (int32_t)fssize_frag;
1885 1885 sblock.fs_ncyl = (int32_t)(fssize_frag * NSPF(&sblock) / sblock.fs_spc);
1886 1886 if (fssize_frag * NSPF(&sblock) >
1887 1887 (uint64_t)sblock.fs_ncyl * sblock.fs_spc) {
1888 1888 sblock.fs_ncyl++;
1889 1889 warn = 1;
1890 1890 }
1891 1891 if (sblock.fs_ncyl < 1) {
1892 1892 (void) fprintf(stderr, gettext(
1893 1893 "file systems must have at least one cylinder\n"));
1894 1894 lockexit(32);
1895 1895 }
1896 1896 if (grow)
1897 1897 goto grow30;
1898 1898 /*
1899 1899 * Determine feasability/values of rotational layout tables.
1900 1900 *
1901 1901 * The size of the rotational layout tables is limited by the size
1902 1902 * of the file system block, fs_bsize. The amount of space
1903 1903 * available for tables is calculated as (fs_bsize - sizeof (struct
1904 1904 * fs)). The size of these tables is inversely proportional to the
1905 1905 * block size of the file system. The size increases if sectors per
1906 1906 * track are not powers of two, because more cylinders must be
1907 1907 * described by the tables before the rotational pattern repeats
1908 1908 * (fs_cpc).
1909 1909 */
1910 1910 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
1911 1911 sblock.fs_sbsize = fragroundup(&sblock, sizeof (struct fs));
1912 1912 sblock.fs_npsect = sblock.fs_nsect;
1913 1913 if (sblock.fs_ntrak == 1) {
1914 1914 sblock.fs_cpc = 0;
1915 1915 goto next;
1916 1916 }
1917 1917 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof (short);
1918 1918 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
1919 1919 totalsbsize = sizeof (struct fs) + rotblsize;
1920 1920
1921 1921 /* do static allocation if nrpos == 8 and fs_cpc == 16 */
1922 1922 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
1923 1923 /* use old static table space */
1924 1924 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
1925 1925 (char *)(&sblock.fs_link);
1926 1926 sblock.fs_rotbloff = &sblock.fs_space[0] -
1927 1927 (uchar_t *)(&sblock.fs_link);
1928 1928 } else {
1929 1929 /* use 4.3 dynamic table space */
1930 1930 sblock.fs_postbloff = &sblock.fs_space[0] -
1931 1931 (uchar_t *)(&sblock.fs_link);
1932 1932 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
1933 1933 totalsbsize += postblsize;
1934 1934 }
1935 1935 if (totalsbsize > sblock.fs_bsize ||
1936 1936 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
1937 1937 (void) fprintf(stderr, gettext(
1938 1938 "Warning: insufficient space in super block for\n"
1939 1939 "rotational layout tables with nsect %d, ntrack %d, "
1940 1940 "and nrpos %d.\nOmitting tables - file system "
1941 1941 "performance may be impaired.\n"),
1942 1942 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_nrpos);
1943 1943
1944 1944 /*
1945 1945 * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to
1946 1946 * ignore the positional layout table and rotational
1947 1947 * position table.
1948 1948 */
1949 1949 sblock.fs_cpc = 0;
1950 1950 goto next;
1951 1951 }
1952 1952 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
1953 1953
1954 1954
1955 1955 /*
1956 1956 * calculate the available blocks for each rotational position
1957 1957 */
1958 1958 for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
1959 1959 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
1960 1960 fs_postbl(&sblock, cylno)[rpos] = -1;
1961 1961 for (i = (rotblsize - 1) * sblock.fs_frag;
1962 1962 i >= 0; i -= sblock.fs_frag) {
1963 1963 cylno = cbtocylno(&sblock, i);
1964 1964 rpos = cbtorpos(&sblock, i);
1965 1965 blk = fragstoblks(&sblock, i);
1966 1966 if (fs_postbl(&sblock, cylno)[rpos] == -1)
1967 1967 fs_rotbl(&sblock)[blk] = 0;
1968 1968 else
1969 1969 fs_rotbl(&sblock)[blk] =
1970 1970 fs_postbl(&sblock, cylno)[rpos] - blk;
1971 1971 fs_postbl(&sblock, cylno)[rpos] = blk;
1972 1972 }
1973 1973 next:
1974 1974 grow30:
1975 1975 /*
1976 1976 * Compute/validate number of cylinder groups.
1977 1977 * Note that if an excessively large filesystem is specified
1978 1978 * (e.g., more than 16384 cylinders for an 8K filesystem block), it
1979 1979 * does not get detected until checksummarysize()
1980 1980 */
1981 1981 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
1982 1982 if (sblock.fs_ncyl % sblock.fs_cpg)
1983 1983 sblock.fs_ncg++;
1984 1984 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
1985 1985 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
1986 1986 ibpcl = cgdmin(&sblock, i) - cgbase(&sblock, i);
1987 1987 if (ibpcl >= sblock.fs_fpg) {
1988 1988 (void) fprintf(stderr, gettext(
1989 1989 "inode blocks/cyl group (%d) >= data blocks (%d)\n"),
1990 1990 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
1991 1991 sblock.fs_fpg / sblock.fs_frag);
1992 1992 if ((ibpcl < 0) || (sblock.fs_fpg < 0)) {
1993 1993 (void) fprintf(stderr, gettext(
1994 1994 "number of cylinders per cylinder group (%d) must be decreased.\n"),
1995 1995 sblock.fs_cpg);
1996 1996 } else {
1997 1997 (void) fprintf(stderr, gettext(
1998 1998 "number of cylinders per cylinder group (%d) must be increased.\n"),
1999 1999 sblock.fs_cpg);
2000 2000 }
2001 2001 (void) fprintf(stderr, gettext(
2002 2002 "Note that cgsize may have been adjusted to allow struct cg to fit.\n"));
2003 2003 lockexit(32);
2004 2004 }
2005 2005 j = sblock.fs_ncg - 1;
2006 2006 if ((i = fssize_frag - j * sblock.fs_fpg) < sblock.fs_fpg &&
2007 2007 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
2008 2008 (void) fprintf(stderr, gettext(
2009 2009 "Warning: inode blocks/cyl group (%d) >= data "
2010 2010 "blocks (%ld) in last\n cylinder group. This "
2011 2011 "implies %ld sector(s) cannot be allocated.\n"),
2012 2012 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
2013 2013 i / sblock.fs_frag, i * NSPF(&sblock));
2014 2014 /*
2015 2015 * If there is only one cylinder group and that is not even
2016 2016 * big enough to hold the inodes, exit.
2017 2017 */
2018 2018 if (sblock.fs_ncg == 1)
2019 2019 cg_too_small = 1;
2020 2020 sblock.fs_ncg--;
2021 2021 sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
2022 2022 sblock.fs_size = fssize_frag =
2023 2023 (int64_t)sblock.fs_ncyl * (int64_t)sblock.fs_spc /
2024 2024 (int64_t)NSPF(&sblock);
2025 2025 warn = 0;
2026 2026 }
2027 2027 if (warn && !spc_flag) {
2028 2028 (void) fprintf(stderr, gettext(
2029 2029 "Warning: %d sector(s) in last cylinder unallocated\n"),
2030 2030 sblock.fs_spc - (uint32_t)(fssize_frag * NSPF(&sblock) -
2031 2031 (uint64_t)(sblock.fs_ncyl - 1) * sblock.fs_spc));
2032 2032 }
2033 2033 /*
2034 2034 * fill in remaining fields of the super block
2035 2035 */
2036 2036
2037 2037 /*
2038 2038 * The csum records are stored in cylinder group 0, starting at
2039 2039 * cgdmin, the first data block.
2040 2040 */
2041 2041 sblock.fs_csaddr = cgdmin(&sblock, 0);
2042 2042 sblock.fs_cssize =
2043 2043 fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum));
2044 2044 i = sblock.fs_bsize / sizeof (struct csum);
2045 2045 sblock.fs_csmask = ~(i - 1);
2046 2046 for (sblock.fs_csshift = 0; i > 1; i >>= 1)
2047 2047 sblock.fs_csshift++;
2048 2048 fscs = (struct csum *)calloc(1, sblock.fs_cssize);
2049 2049
2050 2050 checksummarysize();
2051 2051 if (mtb == 'y') {
2052 2052 sblock.fs_magic = MTB_UFS_MAGIC;
2053 2053 sblock.fs_version = MTB_UFS_VERSION_1;
2054 2054 } else {
2055 2055 sblock.fs_magic = FS_MAGIC;
2056 2056 if (use_efi_dflts)
2057 2057 sblock.fs_version = UFS_EFISTYLE4NONEFI_VERSION_2;
2058 2058 else
2059 2059 sblock.fs_version = UFS_VERSION_MIN;
2060 2060 }
2061 2061
2062 2062 if (grow) {
2063 2063 bcopy((caddr_t)grow_fscs, (caddr_t)fscs, (int)grow_fs_cssize);
2064 2064 extendsummaryinfo();
2065 2065 goto grow40;
2066 2066 }
2067 2067 sblock.fs_rotdelay = rotdelay;
2068 2068 sblock.fs_maxcontig = maxcontig;
2069 2069 sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
2070 2070
2071 2071 sblock.fs_rps = rps;
2072 2072 sblock.fs_cgrotor = 0;
2073 2073 sblock.fs_cstotal.cs_ndir = 0;
2074 2074 sblock.fs_cstotal.cs_nbfree = 0;
2075 2075 sblock.fs_cstotal.cs_nifree = 0;
2076 2076 sblock.fs_cstotal.cs_nffree = 0;
2077 2077 sblock.fs_fmod = 0;
2078 2078 sblock.fs_ronly = 0;
2079 2079 sblock.fs_time = mkfstime;
2080 2080 sblock.fs_state = FSOKAY - sblock.fs_time;
2081 2081 sblock.fs_clean = FSCLEAN;
2082 2082 grow40:
2083 2083
2084 2084 /*
2085 2085 * If all that's needed is a dump of the superblock we
2086 2086 * would use by default, we've got it now. So, splat it
2087 2087 * out and leave.
2088 2088 */
2089 2089 if (rflag) {
2090 2090 dump_sblock();
2091 2091 lockexit(0);
2092 2092 }
2093 2093 /*
2094 2094 * Dump out summary information about file system.
2095 2095 */
2096 2096 (void) fprintf(stderr, gettext(
2097 2097 "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"),
2098 2098 fsys, (uint64_t)sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
2099 2099 sblock.fs_ntrak, sblock.fs_nsect);
2100 2100 (void) fprintf(stderr, gettext(
2101 2101 "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"),
2102 2102 (float)sblock.fs_size * sblock.fs_fsize / MB, sblock.fs_ncg,
2103 2103 sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize / MB,
2104 2104 sblock.fs_ipg);
2105 2105
2106 2106 tmpbuf = calloc(sblock.fs_ncg / 50 + 500, 1);
2107 2107 if (tmpbuf == NULL) {
2108 2108 perror("calloc");
2109 2109 lockexit(32);
2110 2110 }
2111 2111 if (cg_too_small) {
2112 2112 (void) fprintf(stderr, gettext("File system creation failed. "
2113 2113 "There is only one cylinder group and\nthat is "
2114 2114 "not even big enough to hold the inodes.\n"));
2115 2115 lockexit(32);
2116 2116 }
2117 2117 /*
2118 2118 * Now build the cylinders group blocks and
2119 2119 * then print out indices of cylinder groups.
2120 2120 */
2121 2121 tprintf(gettext(
2122 2122 "super-block backups (for fsck -F ufs -o b=#) at:\n"));
2123 2123 for (width = cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) {
2124 2124 if ((grow == 0) || (cylno >= grow_fs_ncg))
2125 2125 initcg(cylno);
2126 2126 num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
2127 2127 /*
2128 2128 * If Nflag and if the disk is larger than the CHSLIMIT,
2129 2129 * then sanity test the superblocks before reporting. If there
2130 2130 * are too many superblocks which look insane, we have
2131 2131 * to retry with alternate logic. If both methods have
2132 2132 * failed, then our efforts to arrive at alternate
2133 2133 * superblocks failed, so complain and exit.
2134 2134 */
2135 2135 if (Nflag && retry) {
2136 2136 skip_this_sb = 0;
2137 2137 rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
2138 2138 ret = checksblock(altsblock, 1);
2139 2139 if (ret) {
2140 2140 skip_this_sb = 1;
2141 2141 invalid_sb_cnt++;
2142 2142 dprintf(("DeBuG checksblock() failed - error :"
2143 2143 " %d for sb : %llu invalid_sb_cnt : %d\n",
2144 2144 ret, num, invalid_sb_cnt));
2145 2145 } else {
2146 2146 /*
2147 2147 * Though the superblock looks sane, verify if
2148 2148 * the fs_version in the superblock and the
2149 2149 * logic that we are using to arrive at the
2150 2150 * superblocks match.
2151 2151 */
2152 2152 if (use_efi_dflts && altsblock.fs_version
2153 2153 != UFS_EFISTYLE4NONEFI_VERSION_2) {
2154 2154 skip_this_sb = 1;
2155 2155 invalid_sb_cnt++;
2156 2156 }
2157 2157 }
2158 2158 if (invalid_sb_cnt >= INVALIDSBLIMIT) {
2159 2159 if (retry > 1) {
2160 2160 (void) fprintf(stderr, gettext(
2161 2161 "Error determining alternate "
2162 2162 "superblock locations\n"));
2163 2163 free(tmpbuf);
2164 2164 lockexit(32);
2165 2165 }
2166 2166 retry++;
2167 2167 use_efi_dflts = !use_efi_dflts;
2168 2168 free(tmpbuf);
2169 2169 goto retry_alternate_logic;
2170 2170 }
2171 2171 if (skip_this_sb)
2172 2172 continue;
2173 2173 }
2174 2174 (void) sprintf(pbuf, " %llu,", num);
2175 2175 plen = strlen(pbuf);
2176 2176 if ((width + plen) > (WIDTH - 1)) {
2177 2177 width = plen;
2178 2178 tprintf("\n");
2179 2179 } else {
2180 2180 width += plen;
2181 2181 }
2182 2182 if (Nflag && retry)
2183 2183 (void) strncat(tmpbuf, pbuf, strlen(pbuf));
2184 2184 else
2185 2185 (void) fprintf(stderr, "%s", pbuf);
2186 2186 }
2187 2187 tprintf("\n");
2188 2188
2189 2189 remaining_cg = sblock.fs_ncg - cylno;
2190 2190
2191 2191 /*
2192 2192 * If there are more than 300 cylinder groups still to be
2193 2193 * initialized, print a "." for every 50 cylinder groups.
2194 2194 */
2195 2195 if (remaining_cg > 300) {
2196 2196 tprintf(gettext("Initializing cylinder groups:\n"));
2197 2197 do_dot = 1;
2198 2198 }
2199 2199
2200 2200 /*
2201 2201 * Now initialize all cylinder groups between the first ten
2202 2202 * and the last ten.
2203 2203 *
2204 2204 * If the number of cylinder groups was less than 10, all of the
2205 2205 * cylinder group offsets would have printed in the last loop
2206 2206 * and cylno will already be equal to sblock.fs_ncg and so this
2207 2207 * loop will not be entered. If there are less than 20 cylinder
2208 2208 * groups, cylno is already less than fs_ncg - 10, so this loop
2209 2209 * won't be entered in that case either.
2210 2210 */
2211 2211
2212 2212 i = 0;
2213 2213 for (; cylno < sblock.fs_ncg - 10; cylno++) {
2214 2214 if ((grow == 0) || (cylno >= grow_fs_ncg))
2215 2215 initcg(cylno);
2216 2216 if (do_dot && cylno % 50 == 0) {
2217 2217 tprintf(".");
2218 2218 i++;
2219 2219 if (i == WIDTH - 1) {
2220 2220 tprintf("\n");
2221 2221 i = 0;
2222 2222 }
2223 2223 }
2224 2224 }
2225 2225
2226 2226 /*
2227 2227 * Now print the cylinder group offsets for the last 10
2228 2228 * cylinder groups, if any are left.
2229 2229 */
2230 2230
2231 2231 if (do_dot) {
2232 2232 tprintf(gettext(
2233 2233 "\nsuper-block backups for last 10 cylinder groups at:\n"));
2234 2234 }
2235 2235 for (width = 0; cylno < sblock.fs_ncg; cylno++) {
2236 2236 if ((grow == 0) || (cylno >= grow_fs_ncg))
2237 2237 initcg(cylno);
2238 2238 num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
2239 2239 if (Nflag && retry) {
2240 2240 skip_this_sb = 0;
2241 2241 rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
2242 2242 ret = checksblock(altsblock, 1);
2243 2243 if (ret) {
2244 2244 skip_this_sb = 1;
2245 2245 invalid_sb_cnt++;
2246 2246 dprintf(("DeBuG checksblock() failed - error :"
2247 2247 " %d for sb : %llu invalid_sb_cnt : %d\n",
2248 2248 ret, num, invalid_sb_cnt));
2249 2249 } else {
2250 2250 /*
2251 2251 * Though the superblock looks sane, verify if
2252 2252 * the fs_version in the superblock and the
2253 2253 * logic that we are using to arrive at the
2254 2254 * superblocks match.
2255 2255 */
2256 2256 if (use_efi_dflts && altsblock.fs_version
2257 2257 != UFS_EFISTYLE4NONEFI_VERSION_2) {
2258 2258 skip_this_sb = 1;
2259 2259 invalid_sb_cnt++;
2260 2260 }
2261 2261 }
2262 2262 if (invalid_sb_cnt >= INVALIDSBLIMIT) {
2263 2263 if (retry > 1) {
2264 2264 (void) fprintf(stderr, gettext(
2265 2265 "Error determining alternate "
2266 2266 "superblock locations\n"));
2267 2267 free(tmpbuf);
2268 2268 lockexit(32);
2269 2269 }
2270 2270 retry++;
2271 2271 use_efi_dflts = !use_efi_dflts;
2272 2272 free(tmpbuf);
2273 2273 goto retry_alternate_logic;
2274 2274 }
2275 2275 if (skip_this_sb)
2276 2276 continue;
2277 2277 }
2278 2278 /* Don't print ',' for the last superblock */
2279 2279 if (cylno == sblock.fs_ncg-1)
2280 2280 (void) sprintf(pbuf, " %llu", num);
2281 2281 else
2282 2282 (void) sprintf(pbuf, " %llu,", num);
2283 2283 plen = strlen(pbuf);
2284 2284 if ((width + plen) > (WIDTH - 1)) {
2285 2285 width = plen;
2286 2286 tprintf("\n");
2287 2287 } else {
2288 2288 width += plen;
2289 2289 }
2290 2290 if (Nflag && retry)
2291 2291 (void) strncat(tmpbuf, pbuf, strlen(pbuf));
2292 2292 else
2293 2293 (void) fprintf(stderr, "%s", pbuf);
2294 2294 }
2295 2295 tprintf("\n");
2296 2296 if (Nflag) {
2297 2297 if (retry)
2298 2298 (void) fprintf(stderr, "%s", tmpbuf);
2299 2299 free(tmpbuf);
2300 2300 lockexit(0);
2301 2301 }
2302 2302
2303 2303 free(tmpbuf);
2304 2304 if (grow)
2305 2305 goto grow50;
2306 2306
2307 2307 /*
2308 2308 * Now construct the initial file system,
2309 2309 * then write out the super-block.
2310 2310 */
2311 2311 fsinit();
2312 2312 grow50:
2313 2313 /*
2314 2314 * write the superblock and csum information
2315 2315 */
2316 2316 wtsb();
2317 2317
2318 2318 /*
2319 2319 * extend the last cylinder group in the original file system
2320 2320 */
2321 2321 if (grow) {
2322 2322 extendcg(grow_fs_ncg-1);
2323 2323 wtsb();
2324 2324 }
2325 2325
2326 2326 /*
2327 2327 * Write out the duplicate super blocks to the first 10
2328 2328 * cylinder groups (or fewer, if there are fewer than 10
2329 2329 * cylinder groups).
2330 2330 */
2331 2331 for (cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++)
2332 2332 awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
2333 2333 (int)sbsize, (char *)&sblock, SAVE);
2334 2334
2335 2335 /*
2336 2336 * Now write out duplicate super blocks to the remaining
2337 2337 * cylinder groups. In the case of multi-terabyte file
2338 2338 * systems, just write out the super block to the last ten
2339 2339 * cylinder groups (or however many are left).
2340 2340 */
2341 2341 if (mtb == 'y') {
2342 2342 if (sblock.fs_ncg <= 10)
2343 2343 cylno = sblock.fs_ncg;
2344 2344 else if (sblock.fs_ncg <= 20)
2345 2345 cylno = 10;
2346 2346 else
2347 2347 cylno = sblock.fs_ncg - 10;
2348 2348 }
2349 2349
2350 2350 for (; cylno < sblock.fs_ncg; cylno++)
2351 2351 awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
2352 2352 (int)sbsize, (char *)&sblock, SAVE);
2353 2353
2354 2354 /*
2355 2355 * Flush out all the AIO writes we've done. It's not
2356 2356 * necessary to do this explicitly, but it's the only
2357 2357 * way to report any errors from those writes.
2358 2358 */
2359 2359 flush_writes();
2360 2360
2361 2361 /*
2362 2362 * set clean flag
2363 2363 */
2364 2364 if (grow)
2365 2365 sblock.fs_clean = grow_fs_clean;
2366 2366 else
2367 2367 sblock.fs_clean = FSCLEAN;
2368 2368 sblock.fs_time = mkfstime;
2369 2369 sblock.fs_state = FSOKAY - sblock.fs_time;
2370 2370 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
2371 2371 isbad = 0;
2372 2372
2373 2373 if (fsync(fso) == -1) {
2374 2374 saverr = errno;
2375 2375 (void) fprintf(stderr,
2376 2376 gettext("mkfs: fsync failed on write disk: %s\n"),
2377 2377 strerror(saverr));
2378 2378 /* we're just cleaning up, so keep going */
2379 2379 }
2380 2380 if (close(fsi) == -1) {
2381 2381 saverr = errno;
2382 2382 (void) fprintf(stderr,
2383 2383 gettext("mkfs: close failed on read disk: %s\n"),
2384 2384 strerror(saverr));
2385 2385 /* we're just cleaning up, so keep going */
2386 2386 }
2387 2387 if (close(fso) == -1) {
2388 2388 saverr = errno;
2389 2389 (void) fprintf(stderr,
2390 2390 gettext("mkfs: close failed on write disk: %s\n"),
2391 2391 strerror(saverr));
2392 2392 /* we're just cleaning up, so keep going */
2393 2393 }
2394 2394 fsi = fso = -1;
2395 2395
2396 2396 #ifndef STANDALONE
2397 2397 lockexit(0);
2398 2398 #endif
2399 2399
2400 2400 return (0);
2401 2401 }
2402 2402
2403 2403 /*
2404 2404 * Figure out how big the partition we're dealing with is.
2405 2405 * The value returned is in disk blocks (sectors);
2406 2406 */
2407 2407 static diskaddr_t
2408 2408 get_max_size(int fd)
2409 2409 {
2410 2410 struct extvtoc vtoc;
2411 2411 dk_gpt_t *efi_vtoc;
2412 2412 diskaddr_t slicesize;
2413 2413
2414 2414 int index = read_extvtoc(fd, &vtoc);
2415 2415
2416 2416 if (index >= 0) {
2417 2417 label_type = LABEL_TYPE_VTOC;
2418 2418 } else {
2419 2419 if (index == VT_ENOTSUP || index == VT_ERROR) {
2420 2420 /* it might be an EFI label */
2421 2421 index = efi_alloc_and_read(fd, &efi_vtoc);
2422 2422 label_type = LABEL_TYPE_EFI;
2423 2423 }
2424 2424 }
2425 2425
2426 2426 if (index < 0) {
2427 2427 switch (index) {
2428 2428 case VT_ERROR:
2429 2429 break;
2430 2430 case VT_EIO:
2431 2431 errno = EIO;
2432 2432 break;
2433 2433 case VT_EINVAL:
2434 2434 errno = EINVAL;
2435 2435 }
2436 2436 perror(gettext("Can not determine partition size"));
2437 2437 lockexit(32);
2438 2438 }
2439 2439
2440 2440 if (label_type == LABEL_TYPE_EFI) {
2441 2441 slicesize = efi_vtoc->efi_parts[index].p_size;
2442 2442 efi_free(efi_vtoc);
2443 2443 } else {
2444 2444 /*
2445 2445 * In the vtoc struct, p_size is a 32-bit signed quantity.
2446 2446 * In the dk_gpt struct (efi's version of the vtoc), p_size
2447 2447 * is an unsigned 64-bit quantity. By casting the vtoc's
2448 2448 * psize to an unsigned 32-bit quantity, it will be copied
2449 2449 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without
2450 2450 * sign extension.
2451 2451 */
2452 2452
2453 2453 slicesize = (uint32_t)vtoc.v_part[index].p_size;
2454 2454 }
2455 2455
2456 2456 dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n",
2457 2457 index, slicesize, (slicesize > FS_MAX)));
2458 2458
2459 2459 /*
2460 2460 * The next line limits a UFS file system to the maximum
2461 2461 * supported size.
2462 2462 */
2463 2463
2464 2464 if (slicesize > FS_MAX)
2465 2465 return (FS_MAX);
2466 2466 return (slicesize);
2467 2467 }
2468 2468
2469 2469 static long
2470 2470 get_max_track_size(int fd)
2471 2471 {
2472 2472 struct dk_cinfo ci;
2473 2473 long track_size = -1;
2474 2474
2475 2475 if (ioctl(fd, DKIOCINFO, &ci) == 0) {
2476 2476 track_size = ci.dki_maxtransfer * DEV_BSIZE;
2477 2477 }
2478 2478
2479 2479 if ((track_size < 0)) {
2480 2480 int error = 0;
2481 2481 int maxphys;
2482 2482 int gotit = 0;
2483 2483
2484 2484 gotit = fsgetmaxphys(&maxphys, &error);
2485 2485 if (gotit) {
2486 2486 track_size = MIN(MB, maxphys);
2487 2487 } else {
2488 2488 (void) fprintf(stderr, gettext(
2489 2489 "Warning: Could not get system value for maxphys. The value for\n"
2490 2490 "maxcontig will default to 1MB.\n"));
2491 2491 track_size = MB;
2492 2492 }
2493 2493 }
2494 2494 return (track_size);
2495 2495 }
2496 2496
2497 2497 /*
2498 2498 * Initialize a cylinder group.
2499 2499 */
2500 2500 static void
2501 2501 initcg(int cylno)
2502 2502 {
2503 2503 diskaddr_t cbase, d;
2504 2504 diskaddr_t dlower; /* last data block before cg metadata */
2505 2505 diskaddr_t dupper; /* first data block after cg metadata */
2506 2506 diskaddr_t dmax;
2507 2507 int64_t i;
2508 2508 struct csum *cs;
2509 2509 struct dinode *inode_buffer;
2510 2510 int size;
2511 2511
2512 2512 /*
2513 2513 * Variables used to store intermediate results as a part of
2514 2514 * the internal implementation of the cbtocylno() macros.
2515 2515 */
2516 2516 diskaddr_t bno; /* UFS block number (not sector number) */
2517 2517 int cbcylno; /* current cylinder number */
2518 2518 int cbcylno_sect; /* sector offset within cylinder */
2519 2519 int cbsect_incr; /* amount to increment sector offset */
2520 2520
2521 2521 /*
2522 2522 * Variables used to store intermediate results as a part of
2523 2523 * the internal implementation of the cbtorpos() macros.
2524 2524 */
2525 2525 short *cgblks; /* pointer to array of free blocks in cg */
2526 2526 int trackrpos; /* tmp variable for rotation position */
2527 2527 int trackoff; /* offset within a track */
2528 2528 int trackoff_incr; /* amount to increment trackoff */
2529 2529 int rpos; /* rotation position of current block */
2530 2530 int rpos_incr; /* amount to increment rpos per block */
2531 2531
2532 2532 union cgun *icgun; /* local pointer to a cg summary block */
2533 2533 #define icg (icgun->cg)
2534 2534
2535 2535 icgun = (union cgun *)getbuf(&cgsumbuf, sizeof (union cgun));
2536 2536
2537 2537 /*
2538 2538 * Determine block bounds for cylinder group.
2539 2539 * Allow space for super block summary information in first
2540 2540 * cylinder group.
2541 2541 */
2542 2542 cbase = cgbase(&sblock, cylno);
2543 2543 dmax = cbase + sblock.fs_fpg;
2544 2544 if (dmax > sblock.fs_size) /* last cg may be smaller than normal */
2545 2545 dmax = sblock.fs_size;
2546 2546 dlower = cgsblock(&sblock, cylno) - cbase;
2547 2547 dupper = cgdmin(&sblock, cylno) - cbase;
2548 2548 if (cylno == 0)
2549 2549 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
2550 2550 cs = fscs + cylno;
2551 2551 icg.cg_time = mkfstime;
2552 2552 icg.cg_magic = CG_MAGIC;
2553 2553 icg.cg_cgx = cylno;
2554 2554 /* last one gets whatever's left */
2555 2555 if (cylno == sblock.fs_ncg - 1)
2556 2556 icg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
2557 2557 else
2558 2558 icg.cg_ncyl = sblock.fs_cpg;
2559 2559 icg.cg_niblk = sblock.fs_ipg;
2560 2560 icg.cg_ndblk = dmax - cbase;
2561 2561 icg.cg_cs.cs_ndir = 0;
2562 2562 icg.cg_cs.cs_nffree = 0;
2563 2563 icg.cg_cs.cs_nbfree = 0;
2564 2564 icg.cg_cs.cs_nifree = 0;
2565 2565 icg.cg_rotor = 0;
2566 2566 icg.cg_frotor = 0;
2567 2567 icg.cg_irotor = 0;
2568 2568 icg.cg_btotoff = &icg.cg_space[0] - (uchar_t *)(&icg.cg_link);
2569 2569 icg.cg_boff = icg.cg_btotoff + sblock.fs_cpg * sizeof (long);
2570 2570 icg.cg_iusedoff = icg.cg_boff +
2571 2571 sblock.fs_cpg * sblock.fs_nrpos * sizeof (short);
2572 2572 icg.cg_freeoff = icg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
2573 2573 icg.cg_nextfreeoff = icg.cg_freeoff +
2574 2574 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
2575 2575 for (i = 0; i < sblock.fs_frag; i++) {
2576 2576 icg.cg_frsum[i] = 0;
2577 2577 }
2578 2578 bzero((caddr_t)cg_inosused(&icg), icg.cg_freeoff - icg.cg_iusedoff);
2579 2579 icg.cg_cs.cs_nifree += sblock.fs_ipg;
2580 2580 if (cylno == 0)
2581 2581 for (i = 0; i < UFSROOTINO; i++) {
2582 2582 setbit(cg_inosused(&icg), i);
2583 2583 icg.cg_cs.cs_nifree--;
2584 2584 }
2585 2585
2586 2586 /*
2587 2587 * Initialize all the inodes in the cylinder group using
2588 2588 * random numbers.
2589 2589 */
2590 2590 size = sblock.fs_ipg * sizeof (struct dinode);
2591 2591 inode_buffer = (struct dinode *)getbuf(&inodebuf, size);
2592 2592
2593 2593 for (i = 0; i < sblock.fs_ipg; i++) {
2594 2594 IRANDOMIZE(&(inode_buffer[i].di_ic));
2595 2595 }
2596 2596
2597 2597 /*
2598 2598 * Write all inodes in a single write for performance.
2599 2599 */
2600 2600 awtfs(fsbtodb(&sblock, (uint64_t)cgimin(&sblock, cylno)), (int)size,
2601 2601 (char *)inode_buffer, RELEASE);
2602 2602
2603 2603 bzero((caddr_t)cg_blktot(&icg), icg.cg_boff - icg.cg_btotoff);
2604 2604 bzero((caddr_t)cg_blks(&sblock, &icg, 0),
2605 2605 icg.cg_iusedoff - icg.cg_boff);
2606 2606 bzero((caddr_t)cg_blksfree(&icg), icg.cg_nextfreeoff - icg.cg_freeoff);
2607 2607
2608 2608 if (cylno > 0) {
2609 2609 for (d = 0; d < dlower; d += sblock.fs_frag) {
2610 2610 setblock(&sblock, cg_blksfree(&icg), d/sblock.fs_frag);
2611 2611 icg.cg_cs.cs_nbfree++;
2612 2612 cg_blktot(&icg)[cbtocylno(&sblock, d)]++;
2613 2613 cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
2614 2614 [cbtorpos(&sblock, d)]++;
2615 2615 }
2616 2616 sblock.fs_dsize += dlower;
2617 2617 }
2618 2618 sblock.fs_dsize += icg.cg_ndblk - dupper;
2619 2619 if ((i = dupper % sblock.fs_frag) != 0) {
2620 2620 icg.cg_frsum[sblock.fs_frag - i]++;
2621 2621 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
2622 2622 setbit(cg_blksfree(&icg), dupper);
2623 2623 icg.cg_cs.cs_nffree++;
2624 2624 }
2625 2625 }
2626 2626
2627 2627 /*
2628 2628 * WARNING: The following code is somewhat confusing, but
2629 2629 * results in a substantial performance improvement in mkfs.
2630 2630 *
2631 2631 * Instead of using cbtocylno() and cbtorpos() macros, we
2632 2632 * keep track of all the intermediate state of those macros
2633 2633 * in some variables. This allows simple addition to be
2634 2634 * done to calculate the results as we step through the
2635 2635 * blocks in an orderly fashion instead of the slower
2636 2636 * multiplication and division the macros are forced to
2637 2637 * used so they can support random input. (Multiplication,
2638 2638 * division, and remainder operations typically take about
2639 2639 * 10x as many processor cycles as other operations.)
2640 2640 *
2641 2641 * The basic idea is to take code:
2642 2642 *
2643 2643 * for (x = starting_x; x < max; x++)
2644 2644 * y = (x * c) / z
2645 2645 *
2646 2646 * and rewrite it to take advantage of the fact that
2647 2647 * the variable x is incrementing in an orderly way:
2648 2648 *
2649 2649 * intermediate = starting_x * c
2650 2650 * yval = intermediate / z
2651 2651 * for (x = starting_x; x < max; x++) {
2652 2652 * y = yval;
2653 2653 * intermediate += c
2654 2654 * if (intermediate > z) {
2655 2655 * yval++;
2656 2656 * intermediate -= z
2657 2657 * }
2658 2658 * }
2659 2659 *
2660 2660 * Performance has improved as much as 4X using this code.
2661 2661 */
2662 2662
2663 2663 /*
2664 2664 * Initialize the starting points for all the cbtocylno()
2665 2665 * macro variables and figure out the increments needed each
2666 2666 * time through the loop.
2667 2667 */
2668 2668 cbcylno_sect = dupper * NSPF(&sblock);
2669 2669 cbsect_incr = sblock.fs_frag * NSPF(&sblock);
2670 2670 cbcylno = cbcylno_sect / sblock.fs_spc;
2671 2671 cbcylno_sect %= sblock.fs_spc;
2672 2672 cgblks = cg_blks(&sblock, &icg, cbcylno);
2673 2673 bno = dupper / sblock.fs_frag;
2674 2674
2675 2675 /*
2676 2676 * Initialize the starting points for all the cbtorpos()
2677 2677 * macro variables and figure out the increments needed each
2678 2678 * time through the loop.
2679 2679 *
2680 2680 * It's harder to simplify the cbtorpos() macro if there were
2681 2681 * alternate sectors specified (or if they previously existed
2682 2682 * in the growfs case). Since this is rare, we just revert to
2683 2683 * using the macros in this case and skip the variable setup.
2684 2684 */
2685 2685 if (!spc_flag) {
2686 2686 trackrpos = (cbcylno_sect % sblock.fs_nsect) * sblock.fs_nrpos;
2687 2687 rpos = trackrpos / sblock.fs_nsect;
2688 2688 trackoff = trackrpos % sblock.fs_nsect;
2689 2689 trackoff_incr = cbsect_incr * sblock.fs_nrpos;
2690 2690 rpos_incr = (trackoff_incr / sblock.fs_nsect) % sblock.fs_nrpos;
2691 2691 trackoff_incr = trackoff_incr % sblock.fs_nsect;
2692 2692 }
2693 2693
2694 2694 /*
2695 2695 * Loop through all the blocks, marking them free and
2696 2696 * updating totals kept in the superblock and cg summary.
2697 2697 */
2698 2698 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
2699 2699 setblock(&sblock, cg_blksfree(&icg), bno);
2700 2700 icg.cg_cs.cs_nbfree++;
2701 2701
2702 2702 cg_blktot(&icg)[cbcylno]++;
2703 2703
2704 2704 if (!spc_flag)
2705 2705 cgblks[rpos]++;
2706 2706 else
2707 2707 cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
2708 2708 [cbtorpos(&sblock, d)]++;
2709 2709
2710 2710 d += sblock.fs_frag;
2711 2711 bno++;
2712 2712
2713 2713 /*
2714 2714 * Increment the sector offset within the cylinder
2715 2715 * for the cbtocylno() macro reimplementation. If
2716 2716 * we're beyond the end of the cylinder, update the
2717 2717 * cylinder number, calculate the offset in the
2718 2718 * new cylinder, and update the cgblks pointer
2719 2719 * to the next rotational position.
2720 2720 */
2721 2721 cbcylno_sect += cbsect_incr;
2722 2722 if (cbcylno_sect >= sblock.fs_spc) {
2723 2723 cbcylno++;
2724 2724 cbcylno_sect -= sblock.fs_spc;
2725 2725 cgblks += sblock.fs_nrpos;
2726 2726 }
2727 2727
2728 2728 /*
2729 2729 * If there aren't alternate sectors, increment the
2730 2730 * rotational position variables for the cbtorpos()
2731 2731 * reimplementation. Note that we potentially
2732 2732 * increment rpos twice. Once by rpos_incr, and one
2733 2733 * more time when we wrap to a new track because
2734 2734 * trackoff >= fs_nsect.
2735 2735 */
2736 2736 if (!spc_flag) {
2737 2737 trackoff += trackoff_incr;
2738 2738 rpos += rpos_incr;
2739 2739 if (trackoff >= sblock.fs_nsect) {
2740 2740 trackoff -= sblock.fs_nsect;
2741 2741 rpos++;
2742 2742 }
2743 2743 if (rpos >= sblock.fs_nrpos)
2744 2744 rpos -= sblock.fs_nrpos;
2745 2745 }
2746 2746 }
2747 2747
2748 2748 if (d < dmax - cbase) {
2749 2749 icg.cg_frsum[dmax - cbase - d]++;
2750 2750 for (; d < dmax - cbase; d++) {
2751 2751 setbit(cg_blksfree(&icg), d);
2752 2752 icg.cg_cs.cs_nffree++;
2753 2753 }
2754 2754 }
2755 2755 sblock.fs_cstotal.cs_ndir += icg.cg_cs.cs_ndir;
2756 2756 sblock.fs_cstotal.cs_nffree += icg.cg_cs.cs_nffree;
2757 2757 sblock.fs_cstotal.cs_nbfree += icg.cg_cs.cs_nbfree;
2758 2758 sblock.fs_cstotal.cs_nifree += icg.cg_cs.cs_nifree;
2759 2759 *cs = icg.cg_cs;
2760 2760 awtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, cylno)),
2761 2761 sblock.fs_bsize, (char *)&icg, RELEASE);
2762 2762 }
2763 2763
2764 2764 /*
2765 2765 * initialize the file system
2766 2766 */
2767 2767 struct inode node;
2768 2768
2769 2769 #define LOSTDIR
2770 2770 #ifdef LOSTDIR
2771 2771 #define PREDEFDIR 3
2772 2772 #else
2773 2773 #define PREDEFDIR 2
2774 2774 #endif
2775 2775
2776 2776 struct direct root_dir[] = {
2777 2777 { UFSROOTINO, sizeof (struct direct), 1, "." },
2778 2778 { UFSROOTINO, sizeof (struct direct), 2, ".." },
2779 2779 #ifdef LOSTDIR
2780 2780 { LOSTFOUNDINO, sizeof (struct direct), 10, "lost+found" },
2781 2781 #endif
2782 2782 };
2783 2783 #ifdef LOSTDIR
2784 2784 struct direct lost_found_dir[] = {
2785 2785 { LOSTFOUNDINO, sizeof (struct direct), 1, "." },
2786 2786 { UFSROOTINO, sizeof (struct direct), 2, ".." },
2787 2787 { 0, DIRBLKSIZ, 0, 0 },
2788 2788 };
2789 2789 #endif
2790 2790 char buf[MAXBSIZE];
2791 2791
2792 2792 static void
2793 2793 fsinit()
2794 2794 {
2795 2795 int i;
2796 2796
2797 2797
2798 2798 /*
2799 2799 * initialize the node
2800 2800 */
2801 2801 node.i_atime = mkfstime;
2802 2802 node.i_mtime = mkfstime;
↓ open down ↓ |
2802 lines elided |
↑ open up ↑ |
2803 2803 node.i_ctime = mkfstime;
2804 2804 #ifdef LOSTDIR
2805 2805 /*
2806 2806 * create the lost+found directory
2807 2807 */
2808 2808 (void) makedir(lost_found_dir, 2);
2809 2809 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) {
2810 2810 bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
2811 2811 }
2812 2812 node.i_number = LOSTFOUNDINO;
2813 - node.i_smode = node.i_mode = IFDIR | 0700;
2813 + node.i_smode = IFDIR | 0700;
2814 2814 node.i_nlink = 2;
2815 2815 node.i_size = sblock.fs_bsize;
2816 2816 node.i_db[0] = alloc((int)node.i_size, node.i_mode);
2817 2817 node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
2818 2818 IRANDOMIZE(&node.i_ic);
2819 2819 wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), (int)node.i_size, buf);
2820 2820 iput(&node);
2821 2821 #endif
2822 2822 /*
2823 2823 * create the root directory
2824 2824 */
2825 2825 node.i_number = UFSROOTINO;
2826 - node.i_mode = node.i_smode = IFDIR | UMASK;
2826 + node.i_mode = IFDIR | UMASK;
2827 2827 node.i_nlink = PREDEFDIR;
2828 2828 node.i_size = makedir(root_dir, PREDEFDIR);
2829 2829 node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
2830 2830 /* i_size < 2GB because we are initializing the file system */
2831 2831 node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
2832 2832 IRANDOMIZE(&node.i_ic);
2833 2833 wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), sblock.fs_fsize, buf);
2834 2834 iput(&node);
2835 2835 }
2836 2836
2837 2837 /*
2838 2838 * construct a set of directory entries in "buf".
2839 2839 * return size of directory.
2840 2840 */
2841 2841 static int
2842 2842 makedir(struct direct *protodir, int entries)
2843 2843 {
2844 2844 char *cp;
2845 2845 int i;
2846 2846 ushort_t spcleft;
2847 2847
2848 2848 spcleft = DIRBLKSIZ;
2849 2849 for (cp = buf, i = 0; i < entries - 1; i++) {
2850 2850 protodir[i].d_reclen = DIRSIZ(&protodir[i]);
2851 2851 bcopy(&protodir[i], cp, protodir[i].d_reclen);
2852 2852 cp += protodir[i].d_reclen;
2853 2853 spcleft -= protodir[i].d_reclen;
2854 2854 }
2855 2855 protodir[i].d_reclen = spcleft;
2856 2856 bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
2857 2857 return (DIRBLKSIZ);
2858 2858 }
2859 2859
2860 2860 /*
2861 2861 * allocate a block or frag
2862 2862 */
2863 2863 static daddr32_t
2864 2864 alloc(int size, int mode)
2865 2865 {
2866 2866 int i, frag;
2867 2867 daddr32_t d;
2868 2868
2869 2869 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2870 2870 (char *)&acg);
2871 2871 if (acg.cg_magic != CG_MAGIC) {
2872 2872 (void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
2873 2873 lockexit(32);
2874 2874 }
2875 2875 if (acg.cg_cs.cs_nbfree == 0) {
2876 2876 (void) fprintf(stderr,
2877 2877 gettext("first cylinder group ran out of space\n"));
2878 2878 lockexit(32);
2879 2879 }
2880 2880 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
2881 2881 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
2882 2882 goto goth;
2883 2883 (void) fprintf(stderr,
2884 2884 gettext("internal error: can't find block in cyl 0\n"));
2885 2885 lockexit(32);
2886 2886 goth:
2887 2887 clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
2888 2888 acg.cg_cs.cs_nbfree--;
2889 2889 sblock.fs_cstotal.cs_nbfree--;
2890 2890 fscs[0].cs_nbfree--;
2891 2891 if (mode & IFDIR) {
2892 2892 acg.cg_cs.cs_ndir++;
2893 2893 sblock.fs_cstotal.cs_ndir++;
2894 2894 fscs[0].cs_ndir++;
2895 2895 }
2896 2896 cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
2897 2897 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
2898 2898 if (size != sblock.fs_bsize) {
2899 2899 frag = howmany(size, sblock.fs_fsize);
2900 2900 fscs[0].cs_nffree += sblock.fs_frag - frag;
2901 2901 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
2902 2902 acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
2903 2903 acg.cg_frsum[sblock.fs_frag - frag]++;
2904 2904 for (i = frag; i < sblock.fs_frag; i++)
2905 2905 setbit(cg_blksfree(&acg), d + i);
2906 2906 }
2907 2907 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2908 2908 (char *)&acg);
2909 2909 return (d);
2910 2910 }
2911 2911
2912 2912 /*
2913 2913 * Allocate an inode on the disk
2914 2914 */
2915 2915 static void
2916 2916 iput(struct inode *ip)
2917 2917 {
2918 2918 struct dinode buf[MAXINOPB];
2919 2919 diskaddr_t d;
2920 2920
2921 2921 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2922 2922 (char *)&acg);
2923 2923 if (acg.cg_magic != CG_MAGIC) {
2924 2924 (void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
2925 2925 lockexit(32);
2926 2926 }
2927 2927 acg.cg_cs.cs_nifree--;
2928 2928 setbit(cg_inosused(&acg), ip->i_number);
2929 2929 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2930 2930 (char *)&acg);
2931 2931 sblock.fs_cstotal.cs_nifree--;
2932 2932 fscs[0].cs_nifree--;
2933 2933 if ((int)ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
2934 2934 (void) fprintf(stderr,
2935 2935 gettext("fsinit: inode value out of range (%d).\n"),
2936 2936 ip->i_number);
2937 2937 lockexit(32);
2938 2938 }
2939 2939 d = fsbtodb(&sblock, (uint64_t)itod(&sblock, (int)ip->i_number));
2940 2940 rdfs(d, sblock.fs_bsize, (char *)buf);
2941 2941 buf[itoo(&sblock, (int)ip->i_number)].di_ic = ip->i_ic;
2942 2942 wtfs(d, sblock.fs_bsize, (char *)buf);
2943 2943 }
2944 2944
2945 2945 /*
2946 2946 * getbuf() -- Get a buffer for use in an AIO operation. Buffer
2947 2947 * is zero'd the first time returned, left with whatever
2948 2948 * was in memory after that. This function actually gets
2949 2949 * enough memory the first time it's called to support
2950 2950 * MAXBUF buffers like a slab allocator. When all the
2951 2951 * buffers are in use, it waits for an aio to complete
2952 2952 * and make a buffer available.
2953 2953 *
2954 2954 * Never returns an error. Either succeeds or exits.
2955 2955 */
2956 2956 static char *
2957 2957 getbuf(bufhdr *bufhead, int size)
2958 2958 {
2959 2959 bufhdr *pbuf;
2960 2960 bufhdr *prev;
2961 2961 int i;
2962 2962 int buf_size, max_bufs;
2963 2963
2964 2964 /*
2965 2965 * Initialize all the buffers
2966 2966 */
2967 2967 if (bufhead->head == NULL) {
2968 2968 /*
2969 2969 * round up the size of our buffer header to a
2970 2970 * 16 byte boundary so the address we return to
2971 2971 * the caller is "suitably aligned".
2972 2972 */
2973 2973 bufhdrsize = (sizeof (bufhdr) + 15) & ~15;
2974 2974
2975 2975 /*
2976 2976 * Add in our header to the buffer and round it all up to
2977 2977 * a 16 byte boundry so each member of the slab is aligned.
2978 2978 */
2979 2979 buf_size = (size + bufhdrsize + 15) & ~15;
2980 2980
2981 2981 /*
2982 2982 * Limit number of buffers to lesser of MAXBUFMEM's worth
2983 2983 * or MAXBUF, whichever is less.
2984 2984 */
2985 2985 max_bufs = MAXBUFMEM / buf_size;
2986 2986 if (max_bufs > MAXBUF)
2987 2987 max_bufs = MAXBUF;
2988 2988
2989 2989 pbuf = (bufhdr *)calloc(max_bufs, buf_size);
2990 2990 if (pbuf == NULL) {
2991 2991 perror("calloc");
2992 2992 lockexit(32);
2993 2993 }
2994 2994
2995 2995 bufhead->head = bufhead;
2996 2996 prev = bufhead;
2997 2997 for (i = 0; i < max_bufs; i++) {
2998 2998 pbuf->head = bufhead;
2999 2999 prev->next = pbuf;
3000 3000 prev = pbuf;
3001 3001 pbuf = (bufhdr *)((char *)pbuf + buf_size);
3002 3002 }
3003 3003 }
3004 3004
3005 3005 /*
3006 3006 * Get an available buffer, waiting for I/O if necessary
3007 3007 */
3008 3008 wait_for_write(NOBLOCK);
3009 3009 while (bufhead->next == NULL)
3010 3010 wait_for_write(BLOCK);
3011 3011
3012 3012 /*
3013 3013 * Take the buffer off the list
3014 3014 */
3015 3015 pbuf = bufhead->next;
3016 3016 bufhead->next = pbuf->next;
3017 3017 pbuf->next = NULL;
3018 3018
3019 3019 /*
3020 3020 * return the empty buffer space just past the header
3021 3021 */
3022 3022 return ((char *)pbuf + bufhdrsize);
3023 3023 }
3024 3024
3025 3025 /*
3026 3026 * freebuf() -- Free a buffer gotten previously through getbuf.
3027 3027 * Puts the buffer back on the appropriate list for
3028 3028 * later use. Never calls free().
3029 3029 *
3030 3030 * Assumes that SIGINT is blocked.
3031 3031 */
3032 3032 static void
3033 3033 freebuf(char *buf)
3034 3034 {
3035 3035 bufhdr *pbuf;
3036 3036 bufhdr *bufhead;
3037 3037
3038 3038 /*
3039 3039 * get the header for this buffer
3040 3040 */
3041 3041 pbuf = (bufhdr *)(buf - bufhdrsize);
3042 3042
3043 3043 /*
3044 3044 * Put it back on the list of available buffers
3045 3045 */
3046 3046 bufhead = pbuf->head;
3047 3047 pbuf->next = bufhead->next;
3048 3048 bufhead->next = pbuf;
3049 3049 }
3050 3050
3051 3051 /*
3052 3052 * freetrans() -- Free a transaction gotten previously through getaiop.
3053 3053 * Puts the transaction struct back on the appropriate list for
3054 3054 * later use. Never calls free().
3055 3055 *
3056 3056 * Assumes that SIGINT is blocked.
3057 3057 */
3058 3058 static void
3059 3059 freetrans(aio_trans *transp)
3060 3060 {
3061 3061 /*
3062 3062 * free the buffer associated with this AIO if needed
3063 3063 */
3064 3064 if (transp->release == RELEASE)
3065 3065 freebuf(transp->buffer);
3066 3066
3067 3067 /*
3068 3068 * Put transaction on the free list
3069 3069 */
3070 3070 transp->next = results.trans;
3071 3071 results.trans = transp;
3072 3072 }
3073 3073
3074 3074 /*
3075 3075 * wait_for_write() -- Wait for an aio write to complete. Return
3076 3076 * the transaction structure for that write.
3077 3077 *
3078 3078 * Blocks SIGINT if necessary.
3079 3079 */
3080 3080 aio_trans *
3081 3081 wait_for_write(int block)
3082 3082 {
3083 3083 aio_trans *transp;
3084 3084 aio_result_t *resultp;
3085 3085 static struct timeval zero_wait = { 0, 0 };
3086 3086 sigset_t old_mask;
3087 3087
3088 3088 /*
3089 3089 * If we know there aren't any outstanding transactions, just return
3090 3090 */
3091 3091 if (results.outstanding == 0)
3092 3092 return ((aio_trans *) 0);
3093 3093
3094 3094 block_sigint(&old_mask);
3095 3095
3096 3096 resultp = aiowait(block ? NULL : &zero_wait);
3097 3097 if (resultp == NULL ||
3098 3098 (resultp == (aio_result_t *)-1 && errno == EINVAL)) {
3099 3099 unblock_sigint(&old_mask);
3100 3100 return ((aio_trans *) 0);
3101 3101 }
3102 3102
3103 3103 results.outstanding--;
3104 3104 transp = (aio_trans *)resultp;
3105 3105
3106 3106 if (resultp->aio_return != transp->size) {
3107 3107 if (resultp->aio_return == -1) {
3108 3108 /*
3109 3109 * The aiowrite() may have failed because the
3110 3110 * kernel didn't have enough memory to do the job.
3111 3111 * Flush all pending writes and try a normal
3112 3112 * write(). wtfs_breakup() will call exit if it
3113 3113 * fails, so we don't worry about errors here.
3114 3114 */
3115 3115 flush_writes();
3116 3116 wtfs_breakup(transp->bno, transp->size, transp->buffer);
3117 3117 } else {
3118 3118 (void) fprintf(stderr, gettext(
3119 3119 "short write (%d of %d bytes) on sector %lld\n"),
3120 3120 resultp->aio_return, transp->size,
3121 3121 transp->bno);
3122 3122 /*
3123 3123 * Don't unblock SIGINT, to avoid potential
3124 3124 * looping due to queued interrupts and
3125 3125 * error handling.
3126 3126 */
3127 3127 lockexit(32);
3128 3128 }
3129 3129 }
3130 3130
3131 3131 resultp->aio_return = 0;
3132 3132 freetrans(transp);
3133 3133 unblock_sigint(&old_mask);
3134 3134 return (transp);
3135 3135 }
3136 3136
3137 3137 /*
3138 3138 * flush_writes() -- flush all the outstanding aio writes.
3139 3139 */
3140 3140 static void
3141 3141 flush_writes(void)
3142 3142 {
3143 3143 while (wait_for_write(BLOCK))
3144 3144 ;
3145 3145 }
3146 3146
3147 3147 /*
3148 3148 * get_aiop() -- find and return an aio_trans structure on which a new
3149 3149 * aio can be done. Blocks on aiowait() if needed. Reaps
3150 3150 * all outstanding completed aio's.
3151 3151 *
3152 3152 * Assumes that SIGINT is blocked.
3153 3153 */
3154 3154 aio_trans *
3155 3155 get_aiop()
3156 3156 {
3157 3157 int i;
3158 3158 aio_trans *transp;
3159 3159 aio_trans *prev;
3160 3160
3161 3161 /*
3162 3162 * initialize aio stuff
3163 3163 */
3164 3164 if (!aio_inited) {
3165 3165 aio_inited = 1;
3166 3166
3167 3167 results.maxpend = 0;
3168 3168 results.outstanding = 0;
3169 3169 results.max = MAXAIO;
3170 3170
3171 3171 results.trans = (aio_trans *)calloc(results.max,
3172 3172 sizeof (aio_trans));
3173 3173 if (results.trans == NULL) {
3174 3174 perror("calloc");
3175 3175 lockexit(32);
3176 3176 }
3177 3177
3178 3178 /*
3179 3179 * Initialize the linked list of aio transaction
3180 3180 * structures. Note that the final "next" pointer
3181 3181 * will be NULL since we got the buffer from calloc().
3182 3182 */
3183 3183 prev = results.trans;
3184 3184 for (i = 1; i < results.max; i++) {
3185 3185 prev->next = &(results.trans[i]);
3186 3186 prev = prev->next;
3187 3187 }
3188 3188 }
3189 3189
3190 3190 wait_for_write(NOBLOCK);
3191 3191 while (results.trans == NULL)
3192 3192 wait_for_write(BLOCK);
3193 3193 transp = results.trans;
3194 3194 results.trans = results.trans->next;
3195 3195
3196 3196 transp->next = 0;
3197 3197 transp->resultbuf.aio_return = AIO_INPROGRESS;
3198 3198 return (transp);
3199 3199 }
3200 3200
3201 3201 /*
3202 3202 * read a block from the file system
3203 3203 */
3204 3204 static void
3205 3205 rdfs(diskaddr_t bno, int size, char *bf)
3206 3206 {
3207 3207 int n, saverr;
3208 3208
3209 3209 /*
3210 3210 * In case we need any data that's pending in an aiowrite(),
3211 3211 * we wait for them all to complete before doing a read.
3212 3212 */
3213 3213 flush_writes();
3214 3214
3215 3215 /*
3216 3216 * Note: the llseek() can succeed, even if the offset is out of range.
3217 3217 * It's not until the file i/o operation (the read()) that one knows
3218 3218 * for sure if the raw device can handle the offset.
3219 3219 */
3220 3220 if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) {
3221 3221 saverr = errno;
3222 3222 (void) fprintf(stderr,
3223 3223 gettext("seek error on sector %lld: %s\n"),
3224 3224 bno, strerror(saverr));
3225 3225 lockexit(32);
3226 3226 }
3227 3227 n = read(fsi, bf, size);
3228 3228 if (n != size) {
3229 3229 saverr = errno;
3230 3230 if (n == -1)
3231 3231 (void) fprintf(stderr,
3232 3232 gettext("read error on sector %lld: %s\n"),
3233 3233 bno, strerror(saverr));
3234 3234 else
3235 3235 (void) fprintf(stderr, gettext(
3236 3236 "short read (%d of %d bytes) on sector %lld\n"),
3237 3237 n, size, bno);
3238 3238 lockexit(32);
3239 3239 }
3240 3240 }
3241 3241
3242 3242 /*
3243 3243 * write a block to the file system
3244 3244 */
3245 3245 static void
3246 3246 wtfs(diskaddr_t bno, int size, char *bf)
3247 3247 {
3248 3248 int n, saverr;
3249 3249
3250 3250 if (fso == -1)
3251 3251 return;
3252 3252
3253 3253 /*
3254 3254 * Note: the llseek() can succeed, even if the offset is out of range.
3255 3255 * It's not until the file i/o operation (the write()) that one knows
3256 3256 * for sure if the raw device can handle the offset.
3257 3257 */
3258 3258 if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
3259 3259 saverr = errno;
3260 3260 (void) fprintf(stderr,
3261 3261 gettext("seek error on sector %lld: %s\n"),
3262 3262 bno, strerror(saverr));
3263 3263 lockexit(32);
3264 3264 }
3265 3265 if (Nflag)
3266 3266 return;
3267 3267 n = write(fso, bf, size);
3268 3268 if (n != size) {
3269 3269 saverr = errno;
3270 3270 if (n == -1)
3271 3271 (void) fprintf(stderr,
3272 3272 gettext("write error on sector %lld: %s\n"),
3273 3273 bno, strerror(saverr));
3274 3274 else
3275 3275 (void) fprintf(stderr, gettext(
3276 3276 "short write (%d of %d bytes) on sector %lld\n"),
3277 3277 n, size, bno);
3278 3278 lockexit(32);
3279 3279 }
3280 3280 }
3281 3281
3282 3282 /*
3283 3283 * write a block to the file system -- buffered with aio
3284 3284 */
3285 3285 static void
3286 3286 awtfs(diskaddr_t bno, int size, char *bf, int release)
3287 3287 {
3288 3288 int n;
3289 3289 aio_trans *transp;
3290 3290 sigset_t old_mask;
3291 3291
3292 3292 if (fso == -1)
3293 3293 return;
3294 3294
3295 3295 /*
3296 3296 * We need to keep things consistent if we get interrupted,
3297 3297 * so defer any expected interrupts for the time being.
3298 3298 */
3299 3299 block_sigint(&old_mask);
3300 3300
3301 3301 if (Nflag) {
3302 3302 if (release == RELEASE)
3303 3303 freebuf(bf);
3304 3304 } else {
3305 3305 transp = get_aiop();
3306 3306 transp->bno = bno;
3307 3307 transp->buffer = bf;
3308 3308 transp->size = size;
3309 3309 transp->release = release;
3310 3310
3311 3311 n = aiowrite(fso, bf, size, (off_t)bno * sectorsize,
3312 3312 SEEK_SET, &transp->resultbuf);
3313 3313
3314 3314 if (n < 0) {
3315 3315 /*
3316 3316 * The aiowrite() may have failed because the
3317 3317 * kernel didn't have enough memory to do the job.
3318 3318 * Flush all pending writes and try a normal
3319 3319 * write(). wtfs_breakup() will call exit if it
3320 3320 * fails, so we don't worry about errors here.
3321 3321 */
3322 3322 flush_writes();
3323 3323 wtfs_breakup(transp->bno, transp->size, transp->buffer);
3324 3324 freetrans(transp);
3325 3325 } else {
3326 3326 /*
3327 3327 * Keep track of our pending writes.
3328 3328 */
3329 3329 results.outstanding++;
3330 3330 if (results.outstanding > results.maxpend)
3331 3331 results.maxpend = results.outstanding;
3332 3332 }
3333 3333 }
3334 3334
3335 3335 unblock_sigint(&old_mask);
3336 3336 }
3337 3337
3338 3338
3339 3339 /*
3340 3340 * write a block to the file system, but break it up into sbsize
3341 3341 * chunks to avoid forcing a large amount of memory to be locked down.
3342 3342 * Only used as a fallback when an aio write has failed.
3343 3343 */
3344 3344 static void
3345 3345 wtfs_breakup(diskaddr_t bno, int size, char *bf)
3346 3346 {
3347 3347 int n, saverr;
3348 3348 int wsize;
3349 3349 int block_incr = sbsize / sectorsize;
3350 3350
3351 3351 if (size < sbsize)
3352 3352 wsize = size;
3353 3353 else
3354 3354 wsize = sbsize;
3355 3355
3356 3356 n = 0;
3357 3357 while (size) {
3358 3358 /*
3359 3359 * Note: the llseek() can succeed, even if the offset is
3360 3360 * out of range. It's not until the file i/o operation
3361 3361 * (the write()) that one knows for sure if the raw device
3362 3362 * can handle the offset.
3363 3363 */
3364 3364 if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
3365 3365 saverr = errno;
3366 3366 (void) fprintf(stderr,
3367 3367 gettext("seek error on sector %lld: %s\n"),
3368 3368 bno, strerror(saverr));
3369 3369 lockexit(32);
3370 3370 }
3371 3371
3372 3372 n = write(fso, bf, wsize);
3373 3373 if (n == -1) {
3374 3374 saverr = errno;
3375 3375 (void) fprintf(stderr,
3376 3376 gettext("write error on sector %lld: %s\n"),
3377 3377 bno, strerror(saverr));
3378 3378 lockexit(32);
3379 3379 }
3380 3380 if (n != wsize) {
3381 3381 saverr = errno;
3382 3382 (void) fprintf(stderr, gettext(
3383 3383 "short write (%d of %d bytes) on sector %lld\n"),
3384 3384 n, size, bno);
3385 3385 lockexit(32);
3386 3386 }
3387 3387
3388 3388 bno += block_incr;
3389 3389 bf += wsize;
3390 3390 size -= wsize;
3391 3391 if (size < wsize)
3392 3392 wsize = size;
3393 3393 }
3394 3394 }
3395 3395
3396 3396
3397 3397 /*
3398 3398 * check if a block is available
3399 3399 */
3400 3400 static int
3401 3401 isblock(struct fs *fs, unsigned char *cp, int h)
3402 3402 {
3403 3403 unsigned char mask;
3404 3404
3405 3405 switch (fs->fs_frag) {
3406 3406 case 8:
3407 3407 return (cp[h] == 0xff);
3408 3408 case 4:
3409 3409 mask = 0x0f << ((h & 0x1) << 2);
3410 3410 return ((cp[h >> 1] & mask) == mask);
3411 3411 case 2:
3412 3412 mask = 0x03 << ((h & 0x3) << 1);
3413 3413 return ((cp[h >> 2] & mask) == mask);
3414 3414 case 1:
3415 3415 mask = 0x01 << (h & 0x7);
3416 3416 return ((cp[h >> 3] & mask) == mask);
3417 3417 default:
3418 3418 (void) fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
3419 3419 return (0);
3420 3420 }
3421 3421 }
3422 3422
3423 3423 /*
3424 3424 * take a block out of the map
3425 3425 */
3426 3426 static void
3427 3427 clrblock(struct fs *fs, unsigned char *cp, int h)
3428 3428 {
3429 3429 switch ((fs)->fs_frag) {
3430 3430 case 8:
3431 3431 cp[h] = 0;
3432 3432 return;
3433 3433 case 4:
3434 3434 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
3435 3435 return;
3436 3436 case 2:
3437 3437 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
3438 3438 return;
3439 3439 case 1:
3440 3440 cp[h >> 3] &= ~(0x01 << (h & 0x7));
3441 3441 return;
3442 3442 default:
3443 3443 (void) fprintf(stderr,
3444 3444 gettext("clrblock: bad fs_frag value %d\n"), fs->fs_frag);
3445 3445 return;
3446 3446 }
3447 3447 }
3448 3448
3449 3449 /*
3450 3450 * put a block into the map
3451 3451 */
3452 3452 static void
3453 3453 setblock(struct fs *fs, unsigned char *cp, int h)
3454 3454 {
3455 3455 switch (fs->fs_frag) {
3456 3456 case 8:
3457 3457 cp[h] = 0xff;
3458 3458 return;
3459 3459 case 4:
3460 3460 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
3461 3461 return;
3462 3462 case 2:
3463 3463 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
3464 3464 return;
3465 3465 case 1:
3466 3466 cp[h >> 3] |= (0x01 << (h & 0x7));
3467 3467 return;
3468 3468 default:
3469 3469 (void) fprintf(stderr,
3470 3470 gettext("setblock: bad fs_frag value %d\n"), fs->fs_frag);
3471 3471 return;
3472 3472 }
3473 3473 }
3474 3474
3475 3475 static void
3476 3476 usage()
3477 3477 {
3478 3478 (void) fprintf(stderr,
3479 3479 gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] "
3480 3480 "special " /* param 0 */
3481 3481 "size(sectors) \\ \n")); /* param 1 */
3482 3482 (void) fprintf(stderr,
3483 3483 "[nsect " /* param 2 */
3484 3484 "ntrack " /* param 3 */
3485 3485 "bsize " /* param 4 */
3486 3486 "fragsize " /* param 5 */
3487 3487 "cpg " /* param 6 */
3488 3488 "free " /* param 7 */
3489 3489 "rps " /* param 8 */
3490 3490 "nbpi " /* param 9 */
3491 3491 "opt " /* param 10 */
3492 3492 "apc " /* param 11 */
3493 3493 "gap " /* param 12 */
3494 3494 "nrpos " /* param 13 */
3495 3495 "maxcontig " /* param 14 */
3496 3496 "mtb]\n"); /* param 15 */
3497 3497 (void) fprintf(stderr,
3498 3498 gettext(" -m : dump fs cmd line used to make this partition\n"
3499 3499 " -V :print this command line and return\n"
3500 3500 " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n"
3501 3501 " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n"
3502 3502 " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n"
3503 3503 " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n"
3504 3504 "NOTE that all -o suboptions: must be separated only by commas so as to\n"
3505 3505 "be parsed as a single argument\n"),
3506 3506 nsect, ntrack, bsize, fragsize, cpg, sblock.fs_minfree, rps,
3507 3507 nbpi, opt, apc, (rotdelay == -1) ? 0 : rotdelay,
3508 3508 sblock.fs_nrpos, maxcontig, mtb);
3509 3509 lockexit(32);
3510 3510 }
3511 3511
3512 3512 /*ARGSUSED*/
3513 3513 static void
3514 3514 dump_fscmd(char *fsys, int fsi)
3515 3515 {
3516 3516 int64_t used, bpcg, inospercg;
3517 3517 int64_t nbpi;
3518 3518 uint64_t nbytes64;
3519 3519
3520 3520 bzero((char *)&sblock, sizeof (sblock));
3521 3521 rdfs((diskaddr_t)SBLOCK, SBSIZE, (char *)&sblock);
3522 3522
3523 3523 /*
3524 3524 * ensure a valid file system and if not, exit with error or else
3525 3525 * we will end up computing block numbers etc and dividing by zero
3526 3526 * which will cause floating point errors in this routine.
3527 3527 */
3528 3528
3529 3529 if ((sblock.fs_magic != FS_MAGIC) &&
3530 3530 (sblock.fs_magic != MTB_UFS_MAGIC)) {
3531 3531 (void) fprintf(stderr, gettext(
3532 3532 "[not currently a valid file system - bad superblock]\n"));
3533 3533 lockexit(32);
3534 3534 }
3535 3535
3536 3536 if (sblock.fs_magic == FS_MAGIC &&
3537 3537 (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
3538 3538 sblock.fs_version != UFS_VERSION_MIN)) {
3539 3539 (void) fprintf(stderr, gettext(
3540 3540 "Unknown version of UFS format: %d\n"), sblock.fs_version);
3541 3541 lockexit(32);
3542 3542 }
3543 3543
3544 3544 if (sblock.fs_magic == MTB_UFS_MAGIC &&
3545 3545 (sblock.fs_version > MTB_UFS_VERSION_1 ||
3546 3546 sblock.fs_version < MTB_UFS_VERSION_MIN)) {
3547 3547 (void) fprintf(stderr, gettext(
3548 3548 "Unknown version of UFS format: %d\n"), sblock.fs_version);
3549 3549 lockexit(32);
3550 3550 }
3551 3551
3552 3552 /*
3553 3553 * Compute a reasonable nbpi value.
3554 3554 * The algorithm for "used" is copied from code
3555 3555 * in main() verbatim.
3556 3556 * The nbpi equation is taken from main where the
3557 3557 * fs_ipg value is set for the last time. The INOPB(...) - 1
3558 3558 * is used to account for the roundup.
3559 3559 * The problem is that a range of nbpi values map to
3560 3560 * the same file system layout. So it is not possible
3561 3561 * to calculate the exact value specified when the file
3562 3562 * system was created. So instead we determine the top
3563 3563 * end of the range of values.
3564 3564 */
3565 3565 bpcg = sblock.fs_spc * sectorsize;
3566 3566 inospercg = (int64_t)roundup(bpcg / sizeof (struct dinode),
3567 3567 INOPB(&sblock));
3568 3568 if (inospercg > MAXIpG(&sblock))
3569 3569 inospercg = MAXIpG(&sblock);
3570 3570 used = (int64_t)
3571 3571 (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
3572 3572 used *= sectorsize;
3573 3573 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
3574 3574
3575 3575 /*
3576 3576 * The top end of the range of values for nbpi may not be
3577 3577 * a valid command line value for mkfs. Report the bottom
3578 3578 * end instead.
3579 3579 */
3580 3580 nbpi = (int64_t)(nbytes64 / (sblock.fs_ipg));
3581 3581
3582 3582 (void) fprintf(stdout, gettext("mkfs -F ufs -o "), fsys);
3583 3583 (void) fprintf(stdout, "nsect=%d,ntrack=%d,",
3584 3584 sblock.fs_nsect, sblock.fs_ntrak);
3585 3585 (void) fprintf(stdout, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,",
3586 3586 sblock.fs_bsize, sblock.fs_fsize, sblock.fs_cpg, sblock.fs_minfree);
3587 3587 (void) fprintf(stdout, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,",
3588 3588 sblock.fs_rps, nbpi, (sblock.fs_optim == FS_OPTSPACE) ? 's' : 't',
3589 3589 (sblock.fs_ntrak * sblock.fs_nsect) - sblock.fs_spc,
3590 3590 sblock.fs_rotdelay);
3591 3591 (void) fprintf(stdout, "nrpos=%d,maxcontig=%d,mtb=%c ",
3592 3592 sblock.fs_nrpos, sblock.fs_maxcontig,
3593 3593 ((sblock.fs_magic == MTB_UFS_MAGIC) ? 'y' : 'n'));
3594 3594 (void) fprintf(stdout, "%s %lld\n", fsys,
3595 3595 fsbtodb(&sblock, sblock.fs_size));
3596 3596
3597 3597 bzero((char *)&sblock, sizeof (sblock));
3598 3598 }
3599 3599
3600 3600 /* number ************************************************************* */
3601 3601 /* */
3602 3602 /* Convert a numeric string arg to binary */
3603 3603 /* */
3604 3604 /* Args: d_value - default value, if have parse error */
3605 3605 /* param - the name of the argument, for error messages */
3606 3606 /* flags - parser state and what's allowed in the arg */
3607 3607 /* Global arg: string - pointer to command arg */
3608 3608 /* */
3609 3609 /* Valid forms: 123 | 123k | 123*123 | 123x123 */
3610 3610 /* */
3611 3611 /* Return: converted number */
3612 3612 /* */
3613 3613 /* ******************************************************************** */
3614 3614
3615 3615 static uint64_t
3616 3616 number(uint64_t d_value, char *param, int flags)
3617 3617 {
3618 3618 char *cs;
3619 3619 uint64_t n, t;
3620 3620 uint64_t cut = BIG / 10; /* limit to avoid overflow */
3621 3621 int minus = 0;
3622 3622
3623 3623 cs = string;
3624 3624 if (*cs == '-') {
3625 3625 minus = 1;
3626 3626 cs += 1;
3627 3627 }
3628 3628 if ((*cs < '0') || (*cs > '9')) {
3629 3629 goto bail_out;
3630 3630 }
3631 3631 n = 0;
3632 3632 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
3633 3633 n = n*10 + *cs++ - '0';
3634 3634 }
3635 3635 if (minus)
3636 3636 n = -n;
3637 3637 for (;;) {
3638 3638 switch (*cs++) {
3639 3639 case 'k':
3640 3640 if (flags & ALLOW_END_ONLY)
3641 3641 goto bail_out;
3642 3642 if (n > (BIG / 1024))
3643 3643 goto overflow;
3644 3644 n *= 1024;
3645 3645 continue;
3646 3646
3647 3647 case '*':
3648 3648 case 'x':
3649 3649 if (flags & ALLOW_END_ONLY)
3650 3650 goto bail_out;
3651 3651 string = cs;
3652 3652 t = number(d_value, param, flags);
3653 3653 if (n > (BIG / t))
3654 3654 goto overflow;
3655 3655 n *= t;
3656 3656 cs = string + 1; /* adjust for -- below */
3657 3657
3658 3658 /* recursion has read rest of expression */
3659 3659 /* FALLTHROUGH */
3660 3660
3661 3661 case ',':
3662 3662 case '\0':
3663 3663 cs--;
3664 3664 string = cs;
3665 3665 return (n);
3666 3666
3667 3667 case '%':
3668 3668 if (flags & ALLOW_END_ONLY)
3669 3669 goto bail_out;
3670 3670 if (flags & ALLOW_PERCENT) {
3671 3671 flags &= ~ALLOW_PERCENT;
3672 3672 flags |= ALLOW_END_ONLY;
3673 3673 continue;
3674 3674 }
3675 3675 goto bail_out;
3676 3676
3677 3677 case 'm':
3678 3678 if (flags & ALLOW_END_ONLY)
3679 3679 goto bail_out;
3680 3680 if (flags & ALLOW_MS1) {
3681 3681 flags &= ~ALLOW_MS1;
3682 3682 flags |= ALLOW_MS2;
3683 3683 continue;
3684 3684 }
3685 3685 goto bail_out;
3686 3686
3687 3687 case 's':
3688 3688 if (flags & ALLOW_END_ONLY)
3689 3689 goto bail_out;
3690 3690 if (flags & ALLOW_MS2) {
3691 3691 flags &= ~ALLOW_MS2;
3692 3692 flags |= ALLOW_END_ONLY;
3693 3693 continue;
3694 3694 }
3695 3695 goto bail_out;
3696 3696
3697 3697 case '0': case '1': case '2': case '3': case '4':
3698 3698 case '5': case '6': case '7': case '8': case '9':
3699 3699 overflow:
3700 3700 (void) fprintf(stderr,
3701 3701 gettext("mkfs: value for %s overflowed\n"),
3702 3702 param);
3703 3703 while ((*cs != '\0') && (*cs != ','))
3704 3704 cs++;
3705 3705 string = cs;
3706 3706 return (BIG);
3707 3707
3708 3708 default:
3709 3709 bail_out:
3710 3710 (void) fprintf(stderr, gettext(
3711 3711 "mkfs: bad numeric arg for %s: \"%s\"\n"),
3712 3712 param, string);
3713 3713 while ((*cs != '\0') && (*cs != ','))
3714 3714 cs++;
3715 3715 string = cs;
3716 3716 if (d_value != NO_DEFAULT) {
3717 3717 (void) fprintf(stderr,
3718 3718 gettext("mkfs: %s reset to default %lld\n"),
3719 3719 param, d_value);
3720 3720 return (d_value);
3721 3721 }
3722 3722 lockexit(2);
3723 3723
3724 3724 }
3725 3725 } /* never gets here */
3726 3726 }
3727 3727
3728 3728 /* match ************************************************************** */
3729 3729 /* */
3730 3730 /* Compare two text strings for equality */
3731 3731 /* */
3732 3732 /* Arg: s - pointer to string to match with a command arg */
3733 3733 /* Global arg: string - pointer to command arg */
3734 3734 /* */
3735 3735 /* Return: 1 if match, 0 if no match */
3736 3736 /* If match, also reset `string' to point to the text */
3737 3737 /* that follows the matching text. */
3738 3738 /* */
3739 3739 /* ******************************************************************** */
3740 3740
3741 3741 static int
3742 3742 match(char *s)
3743 3743 {
3744 3744 char *cs;
3745 3745
3746 3746 cs = string;
3747 3747 while (*cs++ == *s) {
3748 3748 if (*s++ == '\0') {
3749 3749 goto true;
3750 3750 }
3751 3751 }
3752 3752 if (*s != '\0') {
3753 3753 return (0);
3754 3754 }
3755 3755
3756 3756 true:
3757 3757 cs--;
3758 3758 string = cs;
3759 3759 return (1);
3760 3760 }
3761 3761
3762 3762 /*
3763 3763 * GROWFS ROUTINES
3764 3764 */
3765 3765
3766 3766 /* ARGSUSED */
3767 3767 void
3768 3768 lockexit(int exitstatus)
3769 3769 {
3770 3770 if (Pflag) {
3771 3771 /* the probe mode neither changes nor locks the filesystem */
3772 3772 exit(exitstatus);
3773 3773 }
3774 3774
3775 3775 /*
3776 3776 * flush the dirty cylinder group
3777 3777 */
3778 3778 if (inlockexit == 0) {
3779 3779 inlockexit = 1;
3780 3780 flcg();
3781 3781 }
3782 3782
3783 3783 if (aio_inited) {
3784 3784 flush_writes();
3785 3785 }
3786 3786
3787 3787 /*
3788 3788 * make sure the file system is unlocked before exiting
3789 3789 */
3790 3790 if ((inlockexit == 1) && (!isbad)) {
3791 3791 inlockexit = 2;
3792 3792 ulockfs();
3793 3793 /*
3794 3794 * if logging was enabled, then re-enable it
3795 3795 */
3796 3796 if (waslog) {
3797 3797 if (rl_log_control(fsys, _FIOLOGENABLE) != RL_SUCCESS) {
3798 3798 (void) fprintf(stderr, gettext(
3799 3799 "failed to re-enable logging\n"));
3800 3800 }
3801 3801 }
3802 3802 } else if (grow) {
3803 3803 if (isbad) {
3804 3804 (void) fprintf(stderr, gettext(
3805 3805 "Filesystem is currently inconsistent. It "
3806 3806 "must be repaired with fsck(1M)\nbefore being "
3807 3807 "used. Use the following command to "
3808 3808 "do this:\n\n\tfsck %s\n\n"), fsys);
3809 3809
3810 3810 if (ismounted) {
3811 3811 (void) fprintf(stderr, gettext(
3812 3812 "You will be told that the filesystem "
3813 3813 "is already mounted, and asked if you\n"
3814 3814 "wish to continue. Answer `yes' to "
3815 3815 "this question.\n\n"));
3816 3816 }
3817 3817
3818 3818 (void) fprintf(stderr, gettext(
3819 3819 "One problem should be reported, that the summary "
3820 3820 "information is bad.\nYou will then be asked if it "
3821 3821 "should be salvaged. Answer `yes' to\nthis "
3822 3822 "question.\n\n"));
3823 3823 }
3824 3824
3825 3825 if (ismounted) {
3826 3826 /*
3827 3827 * In theory, there's no way to get here without
3828 3828 * isbad also being set, but be robust in the
3829 3829 * face of future code changes.
3830 3830 */
3831 3831 (void) fprintf(stderr, gettext(
3832 3832 "The filesystem is currently mounted "
3833 3833 "read-only and write-locked. "));
3834 3834 if (isbad) {
3835 3835 (void) fprintf(stderr, gettext(
3836 3836 "After\nrunning fsck, unlock the "
3837 3837 "filesystem and "));
3838 3838 } else {
3839 3839 (void) fprintf(stderr, gettext(
3840 3840 "Unlock the filesystem\nand "));
3841 3841 }
3842 3842
3843 3843 (void) fprintf(stderr, gettext(
3844 3844 "re-enable writing with\nthe following "
3845 3845 "command:\n\n\tlockfs -u %s\n\n"), directory);
3846 3846 }
3847 3847 }
3848 3848
3849 3849 exit(exitstatus);
3850 3850 }
3851 3851
3852 3852 void
3853 3853 randomgeneration()
3854 3854 {
3855 3855 int i;
3856 3856 struct dinode *dp;
3857 3857
3858 3858 /*
3859 3859 * always perform fsirand(1) function... newfs will notice that
3860 3860 * the inodes have been randomized and will not call fsirand itself
3861 3861 */
3862 3862 for (i = 0, dp = zino; i < sblock.fs_inopb; ++i, ++dp)
3863 3863 IRANDOMIZE(&dp->di_ic);
3864 3864 }
3865 3865
3866 3866 /*
3867 3867 * Check the size of the summary information.
3868 3868 * Fields in sblock are not changed in this function.
3869 3869 *
3870 3870 * For an 8K filesystem block, the maximum number of cylinder groups is 16384.
3871 3871 * MAXCSBUFS {32} * 8K {FS block size}
3872 3872 * divided by (sizeof csum) {16}
3873 3873 *
3874 3874 * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32,
3875 3875 * this is the only place where it's referenced.
3876 3876 */
3877 3877 void
3878 3878 checksummarysize()
3879 3879 {
3880 3880 diskaddr_t dmax;
3881 3881 diskaddr_t dmin;
3882 3882 int64_t cg0frags;
3883 3883 int64_t cg0blocks;
3884 3884 int64_t maxncg;
3885 3885 int64_t maxfrags;
3886 3886 uint64_t fs_size;
3887 3887 uint64_t maxfs_blocks; /* filesystem blocks for max filesystem size */
3888 3888
3889 3889 /*
3890 3890 * compute the maximum summary info size
3891 3891 */
3892 3892 dmin = cgdmin(&sblock, 0);
3893 3893 dmax = cgbase(&sblock, 0) + sblock.fs_fpg;
3894 3894 fs_size = (grow) ? grow_fs_size : sblock.fs_size;
3895 3895 if (dmax > fs_size)
3896 3896 dmax = fs_size;
3897 3897 cg0frags = dmax - dmin;
3898 3898 cg0blocks = cg0frags / sblock.fs_frag;
3899 3899 cg0frags = cg0blocks * sblock.fs_frag;
3900 3900 maxncg = (longlong_t)cg0blocks *
3901 3901 (longlong_t)(sblock.fs_bsize / sizeof (struct csum));
3902 3902
3903 3903 maxfs_blocks = FS_MAX;
3904 3904
3905 3905 if (maxncg > ((longlong_t)maxfs_blocks / (longlong_t)sblock.fs_fpg) + 1)
3906 3906 maxncg = ((longlong_t)maxfs_blocks /
3907 3907 (longlong_t)sblock.fs_fpg) + 1;
3908 3908
3909 3909 maxfrags = maxncg * (longlong_t)sblock.fs_fpg;
3910 3910
3911 3911 if (maxfrags > maxfs_blocks)
3912 3912 maxfrags = maxfs_blocks;
3913 3913
3914 3914
3915 3915 /*
3916 3916 * remember for later processing in extendsummaryinfo()
3917 3917 */
3918 3918 if (test)
3919 3919 grow_sifrag = dmin + (cg0blocks * sblock.fs_frag);
3920 3920 if (testfrags == 0)
3921 3921 testfrags = cg0frags;
3922 3922 if (testforce)
3923 3923 if (testfrags > cg0frags) {
3924 3924 (void) fprintf(stderr,
3925 3925 gettext("Too many test frags (%lld); "
3926 3926 "try %lld\n"), testfrags, cg0frags);
3927 3927 lockexit(32);
3928 3928 }
3929 3929
3930 3930 /*
3931 3931 * if summary info is too large (too many cg's) tell the user and exit
3932 3932 */
3933 3933 if ((longlong_t)sblock.fs_size > maxfrags) {
3934 3934 (void) fprintf(stderr, gettext(
3935 3935 "Too many cylinder groups with %llu sectors;\n try "
3936 3936 "increasing cgsize, or decreasing fssize to %llu\n"),
3937 3937 fsbtodb(&sblock, (uint64_t)sblock.fs_size),
3938 3938 fsbtodb(&sblock, (uint64_t)maxfrags));
3939 3939 lockexit(32);
3940 3940 }
3941 3941 }
3942 3942
3943 3943 /*
3944 3944 * checksblock() has two uses:
3945 3945 * - One is to sanity test the superblock and is used when newfs(1M)
3946 3946 * is invoked with the "-N" option. If any discrepancy was found,
3947 3947 * just return whatever error was found and do not exit.
3948 3948 * - the other use of it is in places where you expect the superblock
3949 3949 * to be sane, and if it isn't, then we exit.
3950 3950 * Which of the above two actions to take is indicated with the second argument.
3951 3951 */
3952 3952
3953 3953 int
3954 3954 checksblock(struct fs sb, int proceed)
3955 3955 {
3956 3956 int err = 0;
3957 3957 char *errmsg;
3958 3958
3959 3959 if ((sb.fs_magic != FS_MAGIC) && (sb.fs_magic != MTB_UFS_MAGIC)) {
3960 3960 err = 1;
3961 3961 errmsg = gettext("Bad superblock; magic number wrong\n");
3962 3962 } else if ((sb.fs_magic == FS_MAGIC &&
3963 3963 (sb.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
3964 3964 sb.fs_version != UFS_VERSION_MIN)) ||
3965 3965 (sb.fs_magic == MTB_UFS_MAGIC &&
3966 3966 (sb.fs_version > MTB_UFS_VERSION_1 ||
3967 3967 sb.fs_version < MTB_UFS_VERSION_MIN))) {
3968 3968 err = 2;
3969 3969 errmsg = gettext("Unrecognized version of UFS\n");
3970 3970 } else if (sb.fs_ncg < 1) {
3971 3971 err = 3;
3972 3972 errmsg = gettext("Bad superblock; ncg out of range\n");
3973 3973 } else if (sb.fs_cpg < 1) {
3974 3974 err = 4;
3975 3975 errmsg = gettext("Bad superblock; cpg out of range\n");
3976 3976 } else if (sb.fs_ncg * sb.fs_cpg < sb.fs_ncyl ||
3977 3977 (sb.fs_ncg - 1) * sb.fs_cpg >= sb.fs_ncyl) {
3978 3978 err = 5;
3979 3979 errmsg = gettext("Bad superblock; ncyl out of range\n");
3980 3980 } else if (sb.fs_sbsize <= 0 || sb.fs_sbsize > sb.fs_bsize) {
3981 3981 err = 6;
3982 3982 errmsg = gettext("Bad superblock; superblock size out of "
3983 3983 "range\n");
3984 3984 }
3985 3985
3986 3986 if (proceed) {
3987 3987 if (err) dprintf(("%s", errmsg));
3988 3988 return (err);
3989 3989 }
3990 3990
3991 3991 if (err) {
3992 3992 fprintf(stderr, "%s", errmsg);
3993 3993 lockexit(32);
3994 3994 }
3995 3995 return (32);
3996 3996 }
3997 3997
3998 3998 /*
3999 3999 * Roll the embedded log, if any, and set up the global variables
4000 4000 * islog, islogok and isufslog.
4001 4001 */
4002 4002 static void
4003 4003 logsetup(char *devstr)
4004 4004 {
4005 4005 void *buf, *ud_buf;
4006 4006 extent_block_t *ebp;
4007 4007 ml_unit_t *ul;
4008 4008 ml_odunit_t *ud;
4009 4009
4010 4010 /*
4011 4011 * Does the superblock indicate that we are supposed to have a log ?
4012 4012 */
4013 4013 if (sblock.fs_logbno == 0) {
4014 4014 /*
4015 4015 * No log present, nothing to do.
4016 4016 */
4017 4017 islogok = 0;
4018 4018 islog = 0;
4019 4019 isufslog = 0;
4020 4020 return;
4021 4021 } else {
4022 4022 /*
4023 4023 * There's a log in a yet unknown state, attempt to roll it.
4024 4024 */
4025 4025 islog = 1;
4026 4026 islogok = 0;
4027 4027 isufslog = 0;
4028 4028
4029 4029 /*
4030 4030 * We failed to roll the log, bail out.
4031 4031 */
4032 4032 if (rl_roll_log(devstr) != RL_SUCCESS)
4033 4033 return;
4034 4034
4035 4035 isufslog = 1;
4036 4036
4037 4037 /* log is not okay; check the fs */
4038 4038 if ((FSOKAY != (sblock.fs_state + sblock.fs_time)) ||
4039 4039 (sblock.fs_clean != FSLOG))
4040 4040 return;
4041 4041
4042 4042 /* get the log allocation block */
4043 4043 buf = (void *)malloc(DEV_BSIZE);
4044 4044 if (buf == (void *) NULL)
4045 4045 return;
4046 4046
4047 4047 ud_buf = (void *)malloc(DEV_BSIZE);
4048 4048 if (ud_buf == (void *) NULL) {
4049 4049 free(buf);
4050 4050 return;
4051 4051 }
4052 4052
4053 4053 rdfs((diskaddr_t)logbtodb(&sblock, sblock.fs_logbno),
4054 4054 DEV_BSIZE, buf);
4055 4055 ebp = (extent_block_t *)buf;
4056 4056
4057 4057 /* log allocation block is not okay; check the fs */
4058 4058 if (ebp->type != LUFS_EXTENTS) {
4059 4059 free(buf);
4060 4060 free(ud_buf);
4061 4061 return;
4062 4062 }
4063 4063
4064 4064 /* get the log state block(s) */
4065 4065 rdfs((diskaddr_t)logbtodb(&sblock, ebp->extents[0].pbno),
4066 4066 DEV_BSIZE, ud_buf);
4067 4067 ud = (ml_odunit_t *)ud_buf;
4068 4068 ul = (ml_unit_t *)malloc(sizeof (*ul));
4069 4069 ul->un_ondisk = *ud;
4070 4070
4071 4071 /* log state is okay */
4072 4072 if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
4073 4073 (ul->un_version == LUFS_VERSION_LATEST) &&
4074 4074 (ul->un_badlog == 0))
4075 4075 islogok = 1;
4076 4076 free(ud_buf);
4077 4077 free(buf);
4078 4078 free(ul);
4079 4079 }
4080 4080 }
4081 4081
4082 4082 void
4083 4083 growinit(char *devstr)
4084 4084 {
4085 4085 int i;
4086 4086 char buf[DEV_BSIZE];
4087 4087
4088 4088 /*
4089 4089 * Read and verify the superblock
4090 4090 */
4091 4091 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
4092 4092 (void) checksblock(sblock, 0);
4093 4093 if (sblock.fs_postblformat != FS_DYNAMICPOSTBLFMT) {
4094 4094 (void) fprintf(stderr,
4095 4095 gettext("old file system format; can't growfs\n"));
4096 4096 lockexit(32);
4097 4097 }
4098 4098
4099 4099 /*
4100 4100 * can't shrink a file system
4101 4101 */
4102 4102 grow_fssize = fsbtodb(&sblock, (uint64_t)sblock.fs_size);
4103 4103 if (fssize_db < grow_fssize) {
4104 4104 (void) fprintf(stderr,
4105 4105 gettext("%lld sectors < current size of %lld sectors\n"),
4106 4106 fssize_db, grow_fssize);
4107 4107 lockexit(32);
4108 4108 }
4109 4109
4110 4110 /*
4111 4111 * can't grow a system to over a terabyte unless it was set up
4112 4112 * as an MTB UFS file system.
4113 4113 */
4114 4114 if (mtb == 'y' && sblock.fs_magic != MTB_UFS_MAGIC) {
4115 4115 if (fssize_db >= SECTORS_PER_TERABYTE) {
4116 4116 (void) fprintf(stderr, gettext(
4117 4117 "File system was not set up with the multi-terabyte format.\n"));
4118 4118 (void) fprintf(stderr, gettext(
4119 4119 "Its size cannot be increased to a terabyte or more.\n"));
4120 4120 } else {
4121 4121 (void) fprintf(stderr, gettext(
4122 4122 "Cannot convert file system to multi-terabyte format.\n"));
4123 4123 }
4124 4124 lockexit(32);
4125 4125 }
4126 4126
4127 4127 logsetup(devstr);
4128 4128
4129 4129 /*
4130 4130 * can't growfs when logging device has errors
4131 4131 */
4132 4132 if ((islog && !islogok) ||
4133 4133 ((FSOKAY == (sblock.fs_state + sblock.fs_time)) &&
4134 4134 (sblock.fs_clean == FSLOG && !islog))) {
4135 4135 (void) fprintf(stderr,
4136 4136 gettext("logging device has errors; can't growfs\n"));
4137 4137 lockexit(32);
4138 4138 }
4139 4139
4140 4140 /*
4141 4141 * disable ufs logging for growing
4142 4142 */
4143 4143 if (isufslog) {
4144 4144 if (rl_log_control(devstr, _FIOLOGDISABLE) != RL_SUCCESS) {
4145 4145 (void) fprintf(stderr, gettext(
4146 4146 "failed to disable logging\n"));
4147 4147 lockexit(32);
4148 4148 }
4149 4149 islog = 0;
4150 4150 waslog = 1;
4151 4151 }
4152 4152
4153 4153 /*
4154 4154 * if mounted write lock the file system to be grown
4155 4155 */
4156 4156 if (ismounted)
4157 4157 wlockfs();
4158 4158
4159 4159 /*
4160 4160 * refresh dynamic superblock state - disabling logging will have
4161 4161 * changed the amount of free space available in the file system
4162 4162 */
4163 4163 rdfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
4164 4164
4165 4165 /*
4166 4166 * make sure device is big enough
4167 4167 */
4168 4168 rdfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
4169 4169 wtfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
4170 4170
4171 4171 /*
4172 4172 * read current summary information
4173 4173 */
4174 4174 grow_fscs = read_summaryinfo(&sblock);
4175 4175
4176 4176 /*
4177 4177 * save some current size related fields from the superblock
4178 4178 * These are used in extendsummaryinfo()
4179 4179 */
4180 4180 grow_fs_size = sblock.fs_size;
4181 4181 grow_fs_ncg = sblock.fs_ncg;
4182 4182 grow_fs_csaddr = (diskaddr_t)sblock.fs_csaddr;
4183 4183 grow_fs_cssize = sblock.fs_cssize;
4184 4184
4185 4185 /*
4186 4186 * save and reset the clean flag
4187 4187 */
4188 4188 if (FSOKAY == (sblock.fs_state + sblock.fs_time))
4189 4189 grow_fs_clean = sblock.fs_clean;
4190 4190 else
4191 4191 grow_fs_clean = FSBAD;
4192 4192 sblock.fs_clean = FSBAD;
4193 4193 sblock.fs_state = FSOKAY - sblock.fs_time;
4194 4194 isbad = 1;
4195 4195 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
4196 4196 }
4197 4197
4198 4198 void
4199 4199 checkdev(char *rdev, char *bdev)
4200 4200 {
4201 4201 struct stat64 statarea;
4202 4202
4203 4203 if (stat64(bdev, &statarea) < 0) {
4204 4204 (void) fprintf(stderr, gettext("can't check mount point; "));
4205 4205 (void) fprintf(stderr, gettext("can't stat %s\n"), bdev);
4206 4206 lockexit(32);
4207 4207 }
4208 4208 if ((statarea.st_mode & S_IFMT) != S_IFBLK) {
4209 4209 (void) fprintf(stderr, gettext(
4210 4210 "can't check mount point; %s is not a block device\n"),
4211 4211 bdev);
4212 4212 lockexit(32);
4213 4213 }
4214 4214 if (stat64(rdev, &statarea) < 0) {
4215 4215 (void) fprintf(stderr, gettext("can't stat %s\n"), rdev);
4216 4216 lockexit(32);
4217 4217 }
4218 4218 if ((statarea.st_mode & S_IFMT) != S_IFCHR) {
4219 4219 (void) fprintf(stderr,
4220 4220 gettext("%s is not a character device\n"), rdev);
4221 4221 lockexit(32);
4222 4222 }
4223 4223 }
4224 4224
4225 4225 void
4226 4226 checkmount(struct mnttab *mntp, char *bdevname)
4227 4227 {
4228 4228 struct stat64 statdir;
4229 4229 struct stat64 statdev;
4230 4230
4231 4231 if (strcmp(bdevname, mntp->mnt_special) == 0) {
4232 4232 if (stat64(mntp->mnt_mountp, &statdir) == -1) {
4233 4233 (void) fprintf(stderr, gettext("can't stat %s\n"),
4234 4234 mntp->mnt_mountp);
4235 4235 lockexit(32);
4236 4236 }
4237 4237 if (stat64(mntp->mnt_special, &statdev) == -1) {
4238 4238 (void) fprintf(stderr, gettext("can't stat %s\n"),
4239 4239 mntp->mnt_special);
4240 4240 lockexit(32);
4241 4241 }
4242 4242 if (statdir.st_dev != statdev.st_rdev) {
4243 4243 (void) fprintf(stderr, gettext(
4244 4244 "%s is not mounted on %s; mnttab(4) wrong\n"),
4245 4245 mntp->mnt_special, mntp->mnt_mountp);
4246 4246 lockexit(32);
4247 4247 }
4248 4248 ismounted = 1;
4249 4249 if (directory) {
4250 4250 if (strcmp(mntp->mnt_mountp, directory) != 0) {
4251 4251 (void) fprintf(stderr,
4252 4252 gettext("%s is mounted on %s, not %s\n"),
4253 4253 bdevname, mntp->mnt_mountp, directory);
4254 4254 lockexit(32);
4255 4255 }
4256 4256 } else {
4257 4257 if (grow)
4258 4258 (void) fprintf(stderr, gettext(
4259 4259 "%s is mounted on %s; can't growfs\n"),
4260 4260 bdevname, mntp->mnt_mountp);
4261 4261 else
4262 4262 (void) fprintf(stderr,
4263 4263 gettext("%s is mounted, can't mkfs\n"),
4264 4264 bdevname);
4265 4265 lockexit(32);
4266 4266 }
4267 4267 }
4268 4268 }
4269 4269
4270 4270 struct dinode *dibuf = 0;
4271 4271 diskaddr_t difrag = 0;
4272 4272
4273 4273 struct dinode *
4274 4274 gdinode(ino_t ino)
4275 4275 {
4276 4276 /*
4277 4277 * read the block of inodes containing inode number ino
4278 4278 */
4279 4279 if (dibuf == 0)
4280 4280 dibuf = (struct dinode *)malloc((unsigned)sblock.fs_bsize);
4281 4281 if (itod(&sblock, ino) != difrag) {
4282 4282 difrag = itod(&sblock, ino);
4283 4283 rdfs(fsbtodb(&sblock, (uint64_t)difrag), (int)sblock.fs_bsize,
4284 4284 (char *)dibuf);
4285 4285 }
4286 4286 return (dibuf + (ino % INOPB(&sblock)));
4287 4287 }
4288 4288
4289 4289 /*
4290 4290 * structure that manages the frags we need for extended summary info
4291 4291 * These frags can be:
4292 4292 * free
4293 4293 * data block
4294 4294 * alloc block
4295 4295 */
4296 4296 struct csfrag {
4297 4297 struct csfrag *next; /* next entry */
4298 4298 daddr32_t ofrag; /* old frag */
4299 4299 daddr32_t nfrag; /* new frag */
4300 4300 long cylno; /* cylno of nfrag */
4301 4301 long frags; /* number of frags */
4302 4302 long size; /* size in bytes */
4303 4303 ino_t ino; /* inode number */
4304 4304 long fixed; /* Boolean - Already fixed? */
4305 4305 };
4306 4306 struct csfrag *csfrag; /* state unknown */
4307 4307 struct csfrag *csfragino; /* frags belonging to an inode */
4308 4308 struct csfrag *csfragfree; /* frags that are free */
4309 4309
4310 4310 daddr32_t maxcsfrag = 0; /* maximum in range */
4311 4311 daddr32_t mincsfrag = 0x7fffffff; /* minimum in range */
4312 4312
4313 4313 int
4314 4314 csfraginrange(daddr32_t frag)
4315 4315 {
4316 4316 return ((frag >= mincsfrag) && (frag <= maxcsfrag));
4317 4317 }
4318 4318
4319 4319 struct csfrag *
4320 4320 findcsfrag(daddr32_t frag, struct csfrag **cfap)
4321 4321 {
4322 4322 struct csfrag *cfp;
4323 4323
4324 4324 if (!csfraginrange(frag))
4325 4325 return (NULL);
4326 4326
4327 4327 for (cfp = *cfap; cfp; cfp = cfp->next)
4328 4328 if (cfp->ofrag == frag)
4329 4329 return (cfp);
4330 4330 return (NULL);
4331 4331 }
4332 4332
4333 4333 void
4334 4334 checkindirect(ino_t ino, daddr32_t *fragsp, daddr32_t frag, int level)
4335 4335 {
4336 4336 int i;
4337 4337 int ne = sblock.fs_bsize / sizeof (daddr32_t);
4338 4338 daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)];
4339 4339
4340 4340 if (frag == 0)
4341 4341 return;
4342 4342
4343 4343 rdfs(fsbtodb(&sblock, frag), (int)sblock.fs_bsize,
4344 4344 (char *)fsb);
4345 4345
4346 4346 checkdirect(ino, fragsp, fsb, sblock.fs_bsize / sizeof (daddr32_t));
4347 4347
4348 4348 if (level)
4349 4349 for (i = 0; i < ne && *fragsp; ++i)
4350 4350 checkindirect(ino, fragsp, fsb[i], level-1);
4351 4351 }
4352 4352
4353 4353 void
4354 4354 addcsfrag(ino_t ino, daddr32_t frag, struct csfrag **cfap)
4355 4355 {
4356 4356 struct csfrag *cfp, *curr, *prev;
4357 4357
4358 4358 /*
4359 4359 * establish a range for faster checking in csfraginrange()
4360 4360 */
4361 4361 if (frag > maxcsfrag)
4362 4362 maxcsfrag = frag;
4363 4363 if (frag < mincsfrag)
4364 4364 mincsfrag = frag;
4365 4365
4366 4366 /*
4367 4367 * if this frag belongs to an inode and is not the start of a block
4368 4368 * then see if it is part of a frag range for this inode
4369 4369 */
4370 4370 if (ino && (frag % sblock.fs_frag))
4371 4371 for (cfp = *cfap; cfp; cfp = cfp->next) {
4372 4372 if (ino != cfp->ino)
4373 4373 continue;
4374 4374 if (frag != cfp->ofrag + cfp->frags)
4375 4375 continue;
4376 4376 cfp->frags++;
4377 4377 cfp->size += sblock.fs_fsize;
4378 4378 return;
4379 4379 }
4380 4380 /*
4381 4381 * allocate a csfrag entry and insert it in an increasing order into the
4382 4382 * specified list
4383 4383 */
4384 4384 cfp = (struct csfrag *)calloc(1, sizeof (struct csfrag));
4385 4385 cfp->ino = ino;
4386 4386 cfp->ofrag = frag;
4387 4387 cfp->frags = 1;
4388 4388 cfp->size = sblock.fs_fsize;
4389 4389 for (prev = NULL, curr = *cfap; curr != NULL;
4390 4390 prev = curr, curr = curr->next) {
4391 4391 if (frag < curr->ofrag) {
4392 4392 cfp->next = curr;
4393 4393 if (prev)
4394 4394 prev->next = cfp; /* middle element */
4395 4395 else
4396 4396 *cfap = cfp; /* first element */
4397 4397 break;
4398 4398 }
4399 4399 if (curr->next == NULL) {
4400 4400 curr->next = cfp; /* last element */
4401 4401 break;
4402 4402 }
4403 4403 }
4404 4404 if (*cfap == NULL) /* will happen only once */
4405 4405 *cfap = cfp;
4406 4406 }
4407 4407
4408 4408 void
4409 4409 delcsfrag(daddr32_t frag, struct csfrag **cfap)
4410 4410 {
4411 4411 struct csfrag *cfp;
4412 4412 struct csfrag **cfpp;
4413 4413
4414 4414 /*
4415 4415 * free up entry whose beginning frag matches
4416 4416 */
4417 4417 for (cfpp = cfap; *cfpp; cfpp = &(*cfpp)->next) {
4418 4418 if (frag == (*cfpp)->ofrag) {
4419 4419 cfp = *cfpp;
4420 4420 *cfpp = (*cfpp)->next;
4421 4421 free((char *)cfp);
4422 4422 return;
4423 4423 }
4424 4424 }
4425 4425 }
4426 4426
4427 4427 /*
4428 4428 * See whether any of the direct blocks in the array pointed by "db" and of
4429 4429 * length "ne" are within the range of frags needed to extend the cylinder
4430 4430 * summary. If so, remove those frags from the "as-yet-unclassified" list
4431 4431 * (csfrag) and add them to the "owned-by-inode" list (csfragino).
4432 4432 * For each such frag found, decrement the frag count pointed to by fragsp.
4433 4433 * "ino" is the inode that contains (either directly or indirectly) the frags
4434 4434 * being checked.
4435 4435 */
4436 4436 void
4437 4437 checkdirect(ino_t ino, daddr32_t *fragsp, daddr32_t *db, int ne)
4438 4438 {
4439 4439 int i;
4440 4440 int j;
4441 4441 int found;
4442 4442 diskaddr_t frag;
4443 4443
4444 4444 /*
4445 4445 * scan for allocation within the new summary info range
4446 4446 */
4447 4447 for (i = 0; i < ne && *fragsp; ++i) {
4448 4448 if ((frag = *db++) != 0) {
4449 4449 found = 0;
4450 4450 for (j = 0; j < sblock.fs_frag && *fragsp; ++j) {
4451 4451 if (found || (found = csfraginrange(frag))) {
4452 4452 addcsfrag(ino, frag, &csfragino);
4453 4453 delcsfrag(frag, &csfrag);
4454 4454 }
4455 4455 ++frag;
4456 4456 --(*fragsp);
4457 4457 }
4458 4458 }
4459 4459 }
4460 4460 }
4461 4461
4462 4462 void
4463 4463 findcsfragino()
4464 4464 {
4465 4465 int i;
4466 4466 int j;
4467 4467 daddr32_t frags;
4468 4468 struct dinode *dp;
4469 4469
4470 4470 /*
4471 4471 * scan all old inodes looking for allocations in the new
4472 4472 * summary info range. Move the affected frag from the
4473 4473 * generic csfrag list onto the `owned-by-inode' list csfragino.
4474 4474 */
4475 4475 for (i = UFSROOTINO; i < grow_fs_ncg*sblock.fs_ipg && csfrag; ++i) {
4476 4476 dp = gdinode((ino_t)i);
4477 4477 switch (dp->di_mode & IFMT) {
4478 4478 case IFSHAD :
4479 4479 case IFLNK :
4480 4480 case IFDIR :
4481 4481 case IFREG : break;
4482 4482 default : continue;
4483 4483 }
4484 4484
4485 4485 frags = dbtofsb(&sblock, dp->di_blocks);
4486 4486
4487 4487 checkdirect((ino_t)i, &frags, &dp->di_db[0], NDADDR+NIADDR);
4488 4488 for (j = 0; j < NIADDR && frags; ++j) {
4489 4489 /* Negate the block if its an fallocate'd block */
4490 4490 if (dp->di_ib[j] < 0 && dp->di_ib[j] != UFS_HOLE)
4491 4491 checkindirect((ino_t)i, &frags,
4492 4492 -(dp->di_ib[j]), j);
4493 4493 else
4494 4494 checkindirect((ino_t)i, &frags,
4495 4495 dp->di_ib[j], j);
4496 4496 }
4497 4497 }
4498 4498 }
4499 4499
4500 4500 void
4501 4501 fixindirect(daddr32_t frag, int level)
4502 4502 {
4503 4503 int i;
4504 4504 int ne = sblock.fs_bsize / sizeof (daddr32_t);
4505 4505 daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)];
4506 4506
4507 4507 if (frag == 0)
4508 4508 return;
4509 4509
4510 4510 rdfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
4511 4511 (char *)fsb);
4512 4512
4513 4513 fixdirect((caddr_t)fsb, frag, fsb, ne);
4514 4514
4515 4515 if (level)
4516 4516 for (i = 0; i < ne; ++i)
4517 4517 fixindirect(fsb[i], level-1);
4518 4518 }
4519 4519
4520 4520 void
4521 4521 fixdirect(caddr_t bp, daddr32_t frag, daddr32_t *db, int ne)
4522 4522 {
4523 4523 int i;
4524 4524 struct csfrag *cfp;
4525 4525
4526 4526 for (i = 0; i < ne; ++i, ++db) {
4527 4527 if (*db == 0)
4528 4528 continue;
4529 4529 if ((cfp = findcsfrag(*db, &csfragino)) == NULL)
4530 4530 continue;
4531 4531 *db = cfp->nfrag;
4532 4532 cfp->fixed = 1;
4533 4533 wtfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
4534 4534 bp);
4535 4535 }
4536 4536 }
4537 4537
4538 4538 void
4539 4539 fixcsfragino()
4540 4540 {
4541 4541 int i;
4542 4542 struct dinode *dp;
4543 4543 struct csfrag *cfp;
4544 4544
4545 4545 for (cfp = csfragino; cfp; cfp = cfp->next) {
4546 4546 if (cfp->fixed)
4547 4547 continue;
4548 4548 dp = gdinode((ino_t)cfp->ino);
4549 4549 fixdirect((caddr_t)dibuf, difrag, dp->di_db, NDADDR+NIADDR);
4550 4550 for (i = 0; i < NIADDR; ++i)
4551 4551 fixindirect(dp->di_ib[i], i);
4552 4552 }
4553 4553 }
4554 4554
4555 4555 /*
4556 4556 * Read the cylinders summary information specified by settings in the
4557 4557 * passed 'fs' structure into a new allocated array of csum structures.
4558 4558 * The caller is responsible for freeing the returned array.
4559 4559 * Return a pointer to an array of csum structures.
4560 4560 */
4561 4561 static struct csum *
4562 4562 read_summaryinfo(struct fs *fsp)
4563 4563 {
4564 4564 struct csum *csp;
4565 4565 int i;
4566 4566
4567 4567 if ((csp = malloc((size_t)fsp->fs_cssize)) == NULL) {
4568 4568 (void) fprintf(stderr, gettext("cannot create csum list,"
4569 4569 " not enough memory\n"));
4570 4570 exit(32);
4571 4571 }
4572 4572
4573 4573 for (i = 0; i < fsp->fs_cssize; i += fsp->fs_bsize) {
4574 4574 rdfs(fsbtodb(fsp,
4575 4575 (uint64_t)(fsp->fs_csaddr + numfrags(fsp, i))),
4576 4576 (int)(fsp->fs_cssize - i < fsp->fs_bsize ?
4577 4577 fsp->fs_cssize - i : fsp->fs_bsize), ((caddr_t)csp) + i);
4578 4578 }
4579 4579
4580 4580 return (csp);
4581 4581 }
4582 4582
4583 4583 /*
4584 4584 * Check the allocation of fragments that are to be made part of a csum block.
4585 4585 * A fragment is allocated if it is either in the csfragfree list or, it is
4586 4586 * in the csfragino list and has new frags associated with it.
4587 4587 * Return the number of allocated fragments.
4588 4588 */
4589 4589 int64_t
4590 4590 checkfragallocated(daddr32_t frag)
4591 4591 {
4592 4592 struct csfrag *cfp;
4593 4593 /*
4594 4594 * Since the lists are sorted we can break the search if the asked
4595 4595 * frag is smaller then the one in the list.
4596 4596 */
4597 4597 for (cfp = csfragfree; cfp != NULL && frag >= cfp->ofrag;
4598 4598 cfp = cfp->next) {
4599 4599 if (frag == cfp->ofrag)
4600 4600 return (1);
4601 4601 }
4602 4602 for (cfp = csfragino; cfp != NULL && frag >= cfp->ofrag;
4603 4603 cfp = cfp->next) {
4604 4604 if (frag == cfp->ofrag && cfp->nfrag != 0)
4605 4605 return (cfp->frags);
4606 4606 }
4607 4607
4608 4608 return (0);
4609 4609 }
4610 4610
4611 4611 /*
4612 4612 * Figure out how much the filesystem can be grown. The limiting factor is
4613 4613 * the available free space needed to extend the cg summary info block.
4614 4614 * The free space is determined in three steps:
4615 4615 * - Try to extend the cg summary block to the required size.
4616 4616 * - Find free blocks in last cg.
4617 4617 * - Find free space in the last already allocated fragment of the summary info
4618 4618 * block, and use it for additional csum structures.
4619 4619 * Return the maximum size of the new filesystem or 0 if it can't be grown.
4620 4620 * Please note that this function leaves the global list pointers csfrag,
4621 4621 * csfragfree, and csfragino initialized, and the caller is responsible for
4622 4622 * freeing the lists.
4623 4623 */
4624 4624 diskaddr_t
4625 4625 probe_summaryinfo()
4626 4626 {
4627 4627 /* fragments by which the csum block can be extended. */
4628 4628 int64_t growth_csum_frags = 0;
4629 4629 /* fragments by which the filesystem can be extended. */
4630 4630 int64_t growth_fs_frags = 0;
4631 4631 int64_t new_fs_cssize; /* size of csum blk in the new FS */
4632 4632 int64_t new_fs_ncg; /* number of cg in the new FS */
4633 4633 int64_t spare_csum;
4634 4634 daddr32_t oldfrag_daddr;
4635 4635 daddr32_t newfrag_daddr;
4636 4636 daddr32_t daddr;
4637 4637 int i;
4638 4638
4639 4639 /*
4640 4640 * read and verify the superblock
4641 4641 */
4642 4642 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
4643 4643 (void) checksblock(sblock, 0);
4644 4644
4645 4645 /*
4646 4646 * check how much we can extend the cg summary info block
4647 4647 */
4648 4648
4649 4649 /*
4650 4650 * read current summary information
4651 4651 */
4652 4652 fscs = read_summaryinfo(&sblock);
4653 4653
4654 4654 /*
4655 4655 * build list of frags needed for cg summary info block extension
4656 4656 */
4657 4657 oldfrag_daddr = howmany(sblock.fs_cssize, sblock.fs_fsize) +
4658 4658 sblock.fs_csaddr;
4659 4659 new_fs_ncg = howmany(dbtofsb(&sblock, fssize_db), sblock.fs_fpg);
4660 4660 new_fs_cssize = fragroundup(&sblock, new_fs_ncg * sizeof (struct csum));
4661 4661 newfrag_daddr = howmany(new_fs_cssize, sblock.fs_fsize) +
4662 4662 sblock.fs_csaddr;
4663 4663 /*
4664 4664 * add all of the frags that are required to grow the cyl summary to the
4665 4665 * csfrag list, which is the generic/unknown list, since at this point
4666 4666 * we don't yet know the state of those frags.
4667 4667 */
4668 4668 for (daddr = oldfrag_daddr; daddr < newfrag_daddr; daddr++)
4669 4669 addcsfrag((ino_t)0, daddr, &csfrag);
4670 4670
4671 4671 /*
4672 4672 * filter free fragments and allocate them. Note that the free frags
4673 4673 * must be allocated first otherwise they could be grabbed by
4674 4674 * alloccsfragino() for data frags.
4675 4675 */
4676 4676 findcsfragfree();
4677 4677 alloccsfragfree();
4678 4678
4679 4679 /*
4680 4680 * filter fragments owned by inodes and allocate them
4681 4681 */
4682 4682 grow_fs_ncg = sblock.fs_ncg; /* findcsfragino() needs this glob. var. */
4683 4683 findcsfragino();
4684 4684 alloccsfragino();
4685 4685
4686 4686 if (notenoughspace()) {
4687 4687 /*
4688 4688 * check how many consecutive fragments could be allocated
4689 4689 * in both lists.
4690 4690 */
4691 4691 int64_t tmp_frags;
4692 4692 for (daddr = oldfrag_daddr; daddr < newfrag_daddr;
4693 4693 daddr += tmp_frags) {
4694 4694 if ((tmp_frags = checkfragallocated(daddr)) > 0)
4695 4695 growth_csum_frags += tmp_frags;
4696 4696 else
4697 4697 break;
4698 4698 }
4699 4699 } else {
4700 4700 /*
4701 4701 * We have all we need for the new desired size,
4702 4702 * so clean up and report back.
4703 4703 */
4704 4704 return (fssize_db);
4705 4705 }
4706 4706
4707 4707 /*
4708 4708 * given the number of fragments by which the csum block can be grown
4709 4709 * compute by how many new fragments the FS can be increased.
4710 4710 * It is the number of csum instances per fragment multiplied by
4711 4711 * `growth_csum_frags' and the number of fragments per cylinder group.
4712 4712 */
4713 4713 growth_fs_frags = howmany(sblock.fs_fsize, sizeof (struct csum)) *
4714 4714 growth_csum_frags * sblock.fs_fpg;
4715 4715
4716 4716 /*
4717 4717 * compute free fragments in the last cylinder group
4718 4718 */
4719 4719 rdcg(sblock.fs_ncg - 1);
4720 4720 growth_fs_frags += sblock.fs_fpg - acg.cg_ndblk;
4721 4721
4722 4722 /*
4723 4723 * compute how many csum instances are unused in the old csum block.
4724 4724 * For each unused csum instance the FS can be grown by one cylinder
4725 4725 * group without extending the csum block.
4726 4726 */
4727 4727 spare_csum = howmany(sblock.fs_cssize, sizeof (struct csum)) -
4728 4728 sblock.fs_ncg;
4729 4729 if (spare_csum > 0)
4730 4730 growth_fs_frags += spare_csum * sblock.fs_fpg;
4731 4731
4732 4732 /*
4733 4733 * recalculate the new filesystem size in sectors, shorten it by
4734 4734 * the requested size `fssize_db' if necessary.
4735 4735 */
4736 4736 if (growth_fs_frags > 0) {
4737 4737 diskaddr_t sect;
4738 4738 sect = (sblock.fs_size + growth_fs_frags) * sblock.fs_nspf;
4739 4739 return ((sect > fssize_db) ? fssize_db : sect);
4740 4740 }
4741 4741
4742 4742 return (0);
4743 4743 }
4744 4744
4745 4745 void
4746 4746 extendsummaryinfo()
4747 4747 {
4748 4748 int64_t i;
4749 4749 int localtest = test;
4750 4750 int64_t frags;
4751 4751 daddr32_t oldfrag;
4752 4752 daddr32_t newfrag;
4753 4753
4754 4754 /*
4755 4755 * if no-write (-N), don't bother
4756 4756 */
4757 4757 if (Nflag)
4758 4758 return;
4759 4759
4760 4760 again:
4761 4761 flcg();
4762 4762 /*
4763 4763 * summary info did not change size -- do nothing unless in test mode
4764 4764 */
4765 4765 if (grow_fs_cssize == sblock.fs_cssize)
4766 4766 if (!localtest)
4767 4767 return;
4768 4768
4769 4769 /*
4770 4770 * build list of frags needed for additional summary information
4771 4771 */
4772 4772 oldfrag = howmany(grow_fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
4773 4773 newfrag = howmany(sblock.fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
4774 4774 /*
4775 4775 * add all of the frags that are required to grow the cyl summary to the
4776 4776 * csfrag list, which is the generic/unknown list, since at this point
4777 4777 * we don't yet know the state of those frags.
4778 4778 */
4779 4779 for (i = oldfrag, frags = 0; i < newfrag; ++i, ++frags)
4780 4780 addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
4781 4781 /*
4782 4782 * reduce the number of data blocks in the file system (fs_dsize) by
4783 4783 * the number of frags that need to be added to the cyl summary
4784 4784 */
4785 4785 sblock.fs_dsize -= (newfrag - oldfrag);
4786 4786
4787 4787 /*
4788 4788 * In test mode, we move more data than necessary from
4789 4789 * cylinder group 0. The lookup/allocate/move code can be
4790 4790 * better stressed without having to create HUGE file systems.
4791 4791 */
4792 4792 if (localtest)
4793 4793 for (i = newfrag; i < grow_sifrag; ++i) {
4794 4794 if (frags >= testfrags)
4795 4795 break;
4796 4796 frags++;
4797 4797 addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
4798 4798 }
4799 4799
4800 4800 /*
4801 4801 * move frags to free or inode lists, depending on owner
4802 4802 */
4803 4803 findcsfragfree();
4804 4804 findcsfragino();
4805 4805
4806 4806 /*
4807 4807 * if not all frags can be located, file system must be inconsistent
4808 4808 */
4809 4809 if (csfrag) {
4810 4810 isbad = 1; /* should already be set, but make sure */
4811 4811 lockexit(32);
4812 4812 }
4813 4813
4814 4814 /*
4815 4815 * allocate the free frags. Note that the free frags must be allocated
4816 4816 * first otherwise they could be grabbed by alloccsfragino() for data
4817 4817 * frags.
4818 4818 */
4819 4819 alloccsfragfree();
4820 4820 /*
4821 4821 * allocate extra space for inode frags
4822 4822 */
4823 4823 alloccsfragino();
4824 4824
4825 4825 /*
4826 4826 * not enough space
4827 4827 */
4828 4828 if (notenoughspace()) {
4829 4829 unalloccsfragfree();
4830 4830 unalloccsfragino();
4831 4831 if (localtest && !testforce) {
4832 4832 localtest = 0;
4833 4833 goto again;
4834 4834 }
4835 4835 (void) fprintf(stderr, gettext("Not enough free space\n"));
4836 4836 lockexit(NOTENOUGHSPACE);
4837 4837 }
4838 4838
4839 4839 /*
4840 4840 * copy the data from old frags to new frags
4841 4841 */
4842 4842 copycsfragino();
4843 4843
4844 4844 /*
4845 4845 * fix the inodes to point to the new frags
4846 4846 */
4847 4847 fixcsfragino();
4848 4848
4849 4849 /*
4850 4850 * We may have moved more frags than we needed. Free them.
4851 4851 */
4852 4852 rdcg((long)0);
4853 4853 for (i = newfrag; i <= maxcsfrag; ++i)
4854 4854 setbit(cg_blksfree(&acg), i-cgbase(&sblock, 0));
4855 4855 wtcg();
4856 4856
4857 4857 flcg();
4858 4858 }
4859 4859
4860 4860 /*
4861 4861 * Check if all fragments in the `csfragino' list were reallocated.
4862 4862 */
4863 4863 int
4864 4864 notenoughspace()
4865 4865 {
4866 4866 struct csfrag *cfp;
4867 4867
4868 4868 /*
4869 4869 * If any element in the csfragino array has a "new frag location"
4870 4870 * of 0, the allocfrags() function was unsuccessful in allocating
4871 4871 * space for moving the frag represented by this array element.
4872 4872 */
4873 4873 for (cfp = csfragino; cfp; cfp = cfp->next)
4874 4874 if (cfp->nfrag == 0)
4875 4875 return (1);
4876 4876 return (0);
4877 4877 }
4878 4878
4879 4879 void
4880 4880 unalloccsfragino()
4881 4881 {
4882 4882 struct csfrag *cfp;
4883 4883
4884 4884 while ((cfp = csfragino) != NULL) {
4885 4885 if (cfp->nfrag)
4886 4886 freefrags(cfp->nfrag, cfp->frags, cfp->cylno);
4887 4887 delcsfrag(cfp->ofrag, &csfragino);
4888 4888 }
4889 4889 }
4890 4890
4891 4891 void
4892 4892 unalloccsfragfree()
4893 4893 {
4894 4894 struct csfrag *cfp;
4895 4895
4896 4896 while ((cfp = csfragfree) != NULL) {
4897 4897 freefrags(cfp->ofrag, cfp->frags, cfp->cylno);
4898 4898 delcsfrag(cfp->ofrag, &csfragfree);
4899 4899 }
4900 4900 }
4901 4901
4902 4902 /*
4903 4903 * For each frag in the "as-yet-unclassified" list (csfrag), see if
4904 4904 * it's free (i.e., its bit is set in the free frag bit map). If so,
4905 4905 * move it from the "as-yet-unclassified" list to the csfragfree list.
4906 4906 */
4907 4907 void
4908 4908 findcsfragfree()
4909 4909 {
4910 4910 struct csfrag *cfp;
4911 4911 struct csfrag *cfpnext;
4912 4912
4913 4913 /*
4914 4914 * move free frags onto the free-frag list
4915 4915 */
4916 4916 rdcg((long)0);
4917 4917 for (cfp = csfrag; cfp; cfp = cfpnext) {
4918 4918 cfpnext = cfp->next;
4919 4919 if (isset(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0))) {
4920 4920 addcsfrag(cfp->ino, cfp->ofrag, &csfragfree);
4921 4921 delcsfrag(cfp->ofrag, &csfrag);
4922 4922 }
4923 4923 }
4924 4924 }
4925 4925
4926 4926 void
4927 4927 copycsfragino()
4928 4928 {
4929 4929 struct csfrag *cfp;
4930 4930 char buf[MAXBSIZE];
4931 4931
4932 4932 /*
4933 4933 * copy data from old frags to newly allocated frags
4934 4934 */
4935 4935 for (cfp = csfragino; cfp; cfp = cfp->next) {
4936 4936 rdfs(fsbtodb(&sblock, (uint64_t)cfp->ofrag), (int)cfp->size,
4937 4937 buf);
4938 4938 wtfs(fsbtodb(&sblock, (uint64_t)cfp->nfrag), (int)cfp->size,
4939 4939 buf);
4940 4940 }
4941 4941 }
4942 4942
4943 4943 long curcylno = -1;
4944 4944 int cylnodirty = 0;
4945 4945
4946 4946 void
4947 4947 rdcg(long cylno)
4948 4948 {
4949 4949 if (cylno != curcylno) {
4950 4950 flcg();
4951 4951 curcylno = cylno;
4952 4952 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
4953 4953 (int)sblock.fs_cgsize, (char *)&acg);
4954 4954 }
4955 4955 }
4956 4956
4957 4957 void
4958 4958 flcg()
4959 4959 {
4960 4960 if (cylnodirty) {
4961 4961 if (debug && Pflag) {
4962 4962 (void) fprintf(stderr,
4963 4963 "Assert: cylnodirty set in probe mode\n");
4964 4964 return;
4965 4965 }
4966 4966 resetallocinfo();
4967 4967 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
4968 4968 (int)sblock.fs_cgsize, (char *)&acg);
4969 4969 cylnodirty = 0;
4970 4970 }
4971 4971 curcylno = -1;
4972 4972 }
4973 4973
4974 4974 void
4975 4975 wtcg()
4976 4976 {
4977 4977 if (!Pflag) {
4978 4978 /* probe mode should never write to disk */
4979 4979 cylnodirty = 1;
4980 4980 }
4981 4981 }
4982 4982
4983 4983 void
4984 4984 allocfrags(long frags, daddr32_t *fragp, long *cylnop)
4985 4985 {
4986 4986 int i;
4987 4987 int j;
4988 4988 long bits;
4989 4989 long bit;
4990 4990
4991 4991 /*
4992 4992 * Allocate a free-frag range in an old cylinder group
4993 4993 */
4994 4994 for (i = 0, *fragp = 0; i < grow_fs_ncg; ++i) {
4995 4995 if (((fscs+i)->cs_nffree < frags) && ((fscs+i)->cs_nbfree == 0))
4996 4996 continue;
4997 4997 rdcg((long)i);
4998 4998 bit = bits = 0;
4999 4999 while (findfreerange(&bit, &bits)) {
5000 5000 if (frags <= bits) {
5001 5001 for (j = 0; j < frags; ++j)
5002 5002 clrbit(cg_blksfree(&acg), bit+j);
5003 5003 wtcg();
5004 5004 *cylnop = i;
5005 5005 *fragp = bit + cgbase(&sblock, i);
5006 5006 return;
5007 5007 }
5008 5008 bit += bits;
5009 5009 }
5010 5010 }
5011 5011 }
5012 5012
5013 5013 /*
5014 5014 * Allocate space for frags that need to be moved in order to free up space for
5015 5015 * expanding the cylinder summary info.
5016 5016 * For each frag that needs to be moved (each frag or range of frags in
5017 5017 * the csfragino list), allocate a new location and store the frag number
5018 5018 * of that new location in the nfrag field of the csfrag struct.
5019 5019 * If a new frag can't be allocated for any element in the csfragino list,
5020 5020 * set the new frag number for that element to 0 and return immediately.
5021 5021 * The notenoughspace() function will detect this condition.
5022 5022 */
5023 5023 void
5024 5024 alloccsfragino()
5025 5025 {
5026 5026 struct csfrag *cfp;
5027 5027
5028 5028 /*
5029 5029 * allocate space for inode frag ranges
5030 5030 */
5031 5031 for (cfp = csfragino; cfp; cfp = cfp->next) {
5032 5032 allocfrags(cfp->frags, &cfp->nfrag, &cfp->cylno);
5033 5033 if (cfp->nfrag == 0)
5034 5034 break;
5035 5035 }
5036 5036 }
5037 5037
5038 5038 void
5039 5039 alloccsfragfree()
5040 5040 {
5041 5041 struct csfrag *cfp;
5042 5042
5043 5043 /*
5044 5044 * allocate the free frags needed for extended summary info
5045 5045 */
5046 5046 rdcg((long)0);
5047 5047
5048 5048 for (cfp = csfragfree; cfp; cfp = cfp->next)
5049 5049 clrbit(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0));
5050 5050
5051 5051 wtcg();
5052 5052 }
5053 5053
5054 5054 void
5055 5055 freefrags(daddr32_t frag, long frags, long cylno)
5056 5056 {
5057 5057 int i;
5058 5058
5059 5059 /*
5060 5060 * free frags
5061 5061 */
5062 5062 rdcg(cylno);
5063 5063 for (i = 0; i < frags; ++i) {
5064 5064 setbit(cg_blksfree(&acg), (frag+i) - cgbase(&sblock, cylno));
5065 5065 }
5066 5066 wtcg();
5067 5067 }
5068 5068
5069 5069 int
5070 5070 findfreerange(long *bitp, long *bitsp)
5071 5071 {
5072 5072 long bit;
5073 5073
5074 5074 /*
5075 5075 * find a range of free bits in a cylinder group bit map
5076 5076 */
5077 5077 for (bit = *bitp, *bitsp = 0; bit < acg.cg_ndblk; ++bit)
5078 5078 if (isset(cg_blksfree(&acg), bit))
5079 5079 break;
5080 5080
5081 5081 if (bit >= acg.cg_ndblk)
5082 5082 return (0);
5083 5083
5084 5084 *bitp = bit;
5085 5085 *bitsp = 1;
5086 5086 for (++bit; bit < acg.cg_ndblk; ++bit, ++(*bitsp)) {
5087 5087 if ((bit % sblock.fs_frag) == 0)
5088 5088 break;
5089 5089 if (isclr(cg_blksfree(&acg), bit))
5090 5090 break;
5091 5091 }
5092 5092 return (1);
5093 5093 }
5094 5094
5095 5095 void
5096 5096 resetallocinfo()
5097 5097 {
5098 5098 long cno;
5099 5099 long bit;
5100 5100 long bits;
5101 5101
5102 5102 /*
5103 5103 * Compute the free blocks/frags info and update the appropriate
5104 5104 * inmemory superblock, summary info, and cylinder group fields
5105 5105 */
5106 5106 sblock.fs_cstotal.cs_nffree -= acg.cg_cs.cs_nffree;
5107 5107 sblock.fs_cstotal.cs_nbfree -= acg.cg_cs.cs_nbfree;
5108 5108
5109 5109 acg.cg_cs.cs_nffree = 0;
5110 5110 acg.cg_cs.cs_nbfree = 0;
5111 5111
5112 5112 bzero((caddr_t)acg.cg_frsum, sizeof (acg.cg_frsum));
5113 5113 bzero((caddr_t)cg_blktot(&acg), (int)(acg.cg_iusedoff-acg.cg_btotoff));
5114 5114
5115 5115 bit = bits = 0;
5116 5116 while (findfreerange(&bit, &bits)) {
5117 5117 if (bits == sblock.fs_frag) {
5118 5118 acg.cg_cs.cs_nbfree++;
5119 5119 cno = cbtocylno(&sblock, bit);
5120 5120 cg_blktot(&acg)[cno]++;
5121 5121 cg_blks(&sblock, &acg, cno)[cbtorpos(&sblock, bit)]++;
5122 5122 } else {
5123 5123 acg.cg_cs.cs_nffree += bits;
5124 5124 acg.cg_frsum[bits]++;
5125 5125 }
5126 5126 bit += bits;
5127 5127 }
5128 5128
5129 5129 *(fscs + acg.cg_cgx) = acg.cg_cs;
5130 5130
5131 5131 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
5132 5132 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
5133 5133 }
5134 5134
5135 5135 void
5136 5136 extendcg(long cylno)
5137 5137 {
5138 5138 int i;
5139 5139 diskaddr_t dupper;
5140 5140 diskaddr_t cbase;
5141 5141 diskaddr_t dmax;
5142 5142
5143 5143 /*
5144 5144 * extend the cylinder group at the end of the old file system
5145 5145 * if it was partially allocated becase of lack of space
5146 5146 */
5147 5147 flcg();
5148 5148 rdcg(cylno);
5149 5149
5150 5150 dupper = acg.cg_ndblk;
5151 5151 if (cylno == sblock.fs_ncg - 1)
5152 5152 acg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
5153 5153 else
5154 5154 acg.cg_ncyl = sblock.fs_cpg;
5155 5155 cbase = cgbase(&sblock, cylno);
5156 5156 dmax = cbase + sblock.fs_fpg;
5157 5157 if (dmax > sblock.fs_size)
5158 5158 dmax = sblock.fs_size;
5159 5159 acg.cg_ndblk = dmax - cbase;
5160 5160
5161 5161 for (i = dupper; i < acg.cg_ndblk; ++i)
5162 5162 setbit(cg_blksfree(&acg), i);
5163 5163
5164 5164 sblock.fs_dsize += (acg.cg_ndblk - dupper);
5165 5165
5166 5166 wtcg();
5167 5167 flcg();
5168 5168 }
5169 5169
5170 5170 struct lockfs lockfs;
5171 5171 int lockfd;
5172 5172 int islocked;
5173 5173 int lockfskey;
5174 5174 char lockfscomment[128];
5175 5175
5176 5176 void
5177 5177 ulockfs()
5178 5178 {
5179 5179 /*
5180 5180 * if the file system was locked, unlock it before exiting
5181 5181 */
5182 5182 if (islocked == 0)
5183 5183 return;
5184 5184
5185 5185 /*
5186 5186 * first, check if the lock held
5187 5187 */
5188 5188 lockfs.lf_flags = LOCKFS_MOD;
5189 5189 if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
5190 5190 perror(directory);
5191 5191 lockexit(32);
5192 5192 }
5193 5193
5194 5194 if (LOCKFS_IS_MOD(&lockfs)) {
5195 5195 (void) fprintf(stderr,
5196 5196 gettext("FILE SYSTEM CHANGED DURING GROWFS!\n"));
5197 5197 (void) fprintf(stderr,
5198 5198 gettext(" See lockfs(1), umount(1), and fsck(1)\n"));
5199 5199 lockexit(32);
5200 5200 }
5201 5201 /*
5202 5202 * unlock the file system
5203 5203 */
5204 5204 lockfs.lf_lock = LOCKFS_ULOCK;
5205 5205 lockfs.lf_flags = 0;
5206 5206 lockfs.lf_key = lockfskey;
5207 5207 clockfs();
5208 5208 if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
5209 5209 perror(directory);
5210 5210 lockexit(32);
5211 5211 }
5212 5212 }
5213 5213
5214 5214 void
5215 5215 wlockfs()
5216 5216 {
5217 5217
5218 5218 /*
5219 5219 * if no-write (-N), don't bother
5220 5220 */
5221 5221 if (Nflag)
5222 5222 return;
5223 5223 /*
5224 5224 * open the mountpoint, and write lock the file system
5225 5225 */
5226 5226 if ((lockfd = open64(directory, O_RDONLY)) == -1) {
5227 5227 perror(directory);
5228 5228 lockexit(32);
5229 5229 }
5230 5230
5231 5231 /*
5232 5232 * check if it is already locked
5233 5233 */
5234 5234 if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
5235 5235 perror(directory);
5236 5236 lockexit(32);
5237 5237 }
5238 5238
5239 5239 if (lockfs.lf_lock != LOCKFS_WLOCK) {
5240 5240 lockfs.lf_lock = LOCKFS_WLOCK;
5241 5241 lockfs.lf_flags = 0;
5242 5242 lockfs.lf_key = 0;
5243 5243 clockfs();
5244 5244 if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
5245 5245 perror(directory);
5246 5246 lockexit(32);
5247 5247 }
5248 5248 }
5249 5249 islocked = 1;
5250 5250 lockfskey = lockfs.lf_key;
5251 5251 }
5252 5252
5253 5253 void
5254 5254 clockfs()
5255 5255 {
5256 5256 time_t t;
5257 5257 char *ct;
5258 5258
5259 5259 (void) time(&t);
5260 5260 ct = ctime(&t);
5261 5261 ct[strlen(ct)-1] = '\0';
5262 5262
5263 5263 (void) sprintf(lockfscomment, "%s -- mkfs pid %d", ct, getpid());
5264 5264 lockfs.lf_comlen = strlen(lockfscomment)+1;
5265 5265 lockfs.lf_comment = lockfscomment;
5266 5266 }
5267 5267
5268 5268 /*
5269 5269 * Write the csum records and the superblock
5270 5270 */
5271 5271 void
5272 5272 wtsb()
5273 5273 {
5274 5274 long i;
5275 5275
5276 5276 /*
5277 5277 * write summary information
5278 5278 */
5279 5279 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
5280 5280 wtfs(fsbtodb(&sblock, (uint64_t)(sblock.fs_csaddr +
5281 5281 numfrags(&sblock, i))),
5282 5282 (int)(sblock.fs_cssize - i < sblock.fs_bsize ?
5283 5283 sblock.fs_cssize - i : sblock.fs_bsize),
5284 5284 ((char *)fscs) + i);
5285 5285
5286 5286 /*
5287 5287 * write superblock
5288 5288 */
5289 5289 sblock.fs_time = mkfstime;
5290 5290 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
5291 5291 }
5292 5292
5293 5293 /*
5294 5294 * Verify that the optimization selection is reasonable, and advance
5295 5295 * the global "string" appropriately.
5296 5296 */
5297 5297 static char
5298 5298 checkopt(char *optim)
5299 5299 {
5300 5300 char opt;
5301 5301 int limit = strcspn(optim, ",");
5302 5302
5303 5303 switch (limit) {
5304 5304 case 0: /* missing indicator (have comma or nul) */
5305 5305 (void) fprintf(stderr, gettext(
5306 5306 "mkfs: missing optimization flag reset to `t' (time)\n"));
5307 5307 opt = 't';
5308 5308 break;
5309 5309
5310 5310 case 1: /* single-character indicator */
5311 5311 opt = *optim;
5312 5312 if ((opt != 's') && (opt != 't')) {
5313 5313 (void) fprintf(stderr, gettext(
5314 5314 "mkfs: bad optimization value `%c' reset to `t' (time)\n"),
5315 5315 opt);
5316 5316 opt = 't';
5317 5317 }
5318 5318 break;
5319 5319
5320 5320 default: /* multi-character indicator */
5321 5321 (void) fprintf(stderr, gettext(
5322 5322 "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"),
5323 5323 limit, limit, optim);
5324 5324 opt = 't';
5325 5325 break;
5326 5326 }
5327 5327
5328 5328 string += limit;
5329 5329
5330 5330 return (opt);
5331 5331 }
5332 5332
5333 5333 /*
5334 5334 * Verify that the mtb selection is reasonable, and advance
5335 5335 * the global "string" appropriately.
5336 5336 */
5337 5337 static char
5338 5338 checkmtb(char *mtbarg)
5339 5339 {
5340 5340 char mtbc;
5341 5341 int limit = strcspn(mtbarg, ",");
5342 5342
5343 5343 switch (limit) {
5344 5344 case 0: /* missing indicator (have comma or nul) */
5345 5345 (void) fprintf(stderr, gettext(
5346 5346 "mkfs: missing mtb flag reset to `n' (no mtb support)\n"));
5347 5347 mtbc = 'n';
5348 5348 break;
5349 5349
5350 5350 case 1: /* single-character indicator */
5351 5351 mtbc = tolower(*mtbarg);
5352 5352 if ((mtbc != 'y') && (mtbc != 'n')) {
5353 5353 (void) fprintf(stderr, gettext(
5354 5354 "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"),
5355 5355 mtbc);
5356 5356 mtbc = 'n';
5357 5357 }
5358 5358 break;
5359 5359
5360 5360 default: /* multi-character indicator */
5361 5361 (void) fprintf(stderr, gettext(
5362 5362 "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"),
5363 5363 limit, limit, mtbarg);
5364 5364 opt = 'n';
5365 5365 break;
5366 5366 }
5367 5367
5368 5368 string += limit;
5369 5369
5370 5370 return (mtbc);
5371 5371 }
5372 5372
5373 5373 /*
5374 5374 * Verify that a value is in a range. If it is not, resets it to
5375 5375 * its default value if one is supplied, exits otherwise.
5376 5376 *
5377 5377 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5378 5378 */
5379 5379 static void
5380 5380 range_check(long *varp, char *name, long minimum, long maximum,
5381 5381 long def_val, int user_supplied)
5382 5382 {
5383 5383 dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n",
5384 5384 name, *varp, minimum, maximum, def_val));
5385 5385
5386 5386 if ((*varp < minimum) || (*varp > maximum)) {
5387 5387 if (user_supplied != RC_DEFAULT) {
5388 5388 (void) fprintf(stderr, gettext(
5389 5389 "mkfs: bad value for %s: %ld must be between %ld and %ld\n"),
5390 5390 name, *varp, minimum, maximum);
5391 5391 }
5392 5392 if (def_val != NO_DEFAULT) {
5393 5393 if (user_supplied) {
5394 5394 (void) fprintf(stderr,
5395 5395 gettext("mkfs: %s reset to default %ld\n"),
5396 5396 name, def_val);
5397 5397 }
5398 5398 *varp = def_val;
5399 5399 dprintf(("DeBuG %s : %ld\n", name, *varp));
5400 5400 return;
5401 5401 }
5402 5402 lockexit(2);
5403 5403 /*NOTREACHED*/
5404 5404 }
5405 5405 }
5406 5406
5407 5407 /*
5408 5408 * Verify that a value is in a range. If it is not, resets it to
5409 5409 * its default value if one is supplied, exits otherwise.
5410 5410 *
5411 5411 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5412 5412 */
5413 5413 static void
5414 5414 range_check_64(uint64_t *varp, char *name, uint64_t minimum, uint64_t maximum,
5415 5415 uint64_t def_val, int user_supplied)
5416 5416 {
5417 5417 if ((*varp < minimum) || (*varp > maximum)) {
5418 5418 if (user_supplied != RC_DEFAULT) {
5419 5419 (void) fprintf(stderr, gettext(
5420 5420 "mkfs: bad value for %s: %lld must be between %lld and %lld\n"),
5421 5421 name, *varp, minimum, maximum);
5422 5422 }
5423 5423 if (def_val != NO_DEFAULT) {
5424 5424 if (user_supplied) {
5425 5425 (void) fprintf(stderr,
5426 5426 gettext("mkfs: %s reset to default %lld\n"),
5427 5427 name, def_val);
5428 5428 }
5429 5429 *varp = def_val;
5430 5430 return;
5431 5431 }
5432 5432 lockexit(2);
5433 5433 /*NOTREACHED*/
5434 5434 }
5435 5435 }
5436 5436
5437 5437 /*
5438 5438 * Blocks SIGINT from delivery. Returns the previous mask in the
5439 5439 * buffer provided, so that mask may be later restored.
5440 5440 */
5441 5441 static void
5442 5442 block_sigint(sigset_t *old_mask)
5443 5443 {
5444 5444 sigset_t block_mask;
5445 5445
5446 5446 if (sigemptyset(&block_mask) < 0) {
5447 5447 fprintf(stderr, gettext("Could not clear signal mask\n"));
5448 5448 lockexit(3);
5449 5449 }
5450 5450 if (sigaddset(&block_mask, SIGINT) < 0) {
5451 5451 fprintf(stderr, gettext("Could not set signal mask\n"));
5452 5452 lockexit(3);
5453 5453 }
5454 5454 if (sigprocmask(SIG_BLOCK, &block_mask, old_mask) < 0) {
5455 5455 fprintf(stderr, gettext("Could not block SIGINT\n"));
5456 5456 lockexit(3);
5457 5457 }
5458 5458 }
5459 5459
5460 5460 /*
5461 5461 * Restores the signal mask that was in force before a call
5462 5462 * to block_sigint(). This may actually still have SIGINT blocked,
5463 5463 * if we've been recursively invoked.
5464 5464 */
5465 5465 static void
5466 5466 unblock_sigint(sigset_t *old_mask)
5467 5467 {
5468 5468 if (sigprocmask(SIG_UNBLOCK, old_mask, (sigset_t *)NULL) < 0) {
5469 5469 fprintf(stderr, gettext("Could not restore signal mask\n"));
5470 5470 lockexit(3);
5471 5471 }
5472 5472 }
5473 5473
5474 5474 /*
5475 5475 * Attempt to be somewhat graceful about being interrupted, rather than
5476 5476 * just silently leaving the filesystem in an unusable state.
5477 5477 *
5478 5478 * The kernel has blocked SIGINT upon entry, so we don't have to worry
5479 5479 * about recursion if the user starts pounding on the keyboard.
5480 5480 */
5481 5481 static void
5482 5482 recover_from_sigint(int signum)
5483 5483 {
5484 5484 if (fso > -1) {
5485 5485 if ((Nflag != 0) || confirm_abort()) {
5486 5486 lockexit(4);
5487 5487 }
5488 5488 }
5489 5489 }
5490 5490
5491 5491 static int
5492 5492 confirm_abort(void)
5493 5493 {
5494 5494 char line[80];
5495 5495
5496 5496 printf(gettext("\n\nAborting at this point will leave the filesystem "
5497 5497 "in an inconsistent\nstate. If you do choose to stop, "
5498 5498 "you will be given instructions on how to\nrecover "
5499 5499 "the filesystem. Do you wish to cancel the filesystem "
5500 5500 "grow\noperation (y/n)?"));
5501 5501 if (getaline(stdin, line, sizeof (line)) == EOF)
5502 5502 line[0] = 'y';
5503 5503
5504 5504 printf("\n");
5505 5505 if (line[0] == 'y' || line[0] == 'Y')
5506 5506 return (1);
5507 5507 else {
5508 5508 return (0);
5509 5509 }
5510 5510 }
5511 5511
5512 5512 static int
5513 5513 getaline(FILE *fp, char *loc, int maxlen)
5514 5514 {
5515 5515 int n;
5516 5516 char *p, *lastloc;
5517 5517
5518 5518 p = loc;
5519 5519 lastloc = &p[maxlen-1];
5520 5520 while ((n = getc(fp)) != '\n') {
5521 5521 if (n == EOF)
5522 5522 return (EOF);
5523 5523 if (!isspace(n) && p < lastloc)
5524 5524 *p++ = n;
5525 5525 }
5526 5526 *p = 0;
5527 5527 return (p - loc);
5528 5528 }
5529 5529
5530 5530 /*
5531 5531 * Calculate the maximum value of cylinders-per-group for a file
5532 5532 * system with the characteristics:
5533 5533 *
5534 5534 * bsize - file system block size
5535 5535 * fragsize - frag size
5536 5536 * nbpi - number of bytes of disk space per inode
5537 5537 * nrpos - number of rotational positions
5538 5538 * spc - sectors per cylinder
5539 5539 *
5540 5540 * These five characteristic are not adjustable (by this function).
5541 5541 * The only attribute of the file system which IS adjusted by this
5542 5542 * function in order to maximize cylinders-per-group is the proportion
5543 5543 * of the cylinder group overhead block used for the inode map. The
5544 5544 * inode map cannot occupy more than one-third of the cylinder group
5545 5545 * overhead block, but it's OK for it to occupy less than one-third
5546 5546 * of the overhead block.
5547 5547 *
5548 5548 * The setting of nbpi determines one possible value for the maximum
5549 5549 * size of a cylinder group. It does so because it determines the total
5550 5550 * number of inodes in the file system (file system size is fixed, and
5551 5551 * nbpi is fixed, so the total number of inodes is fixed too). The
5552 5552 * cylinder group has to be small enough so that the number of inodes
5553 5553 * in the cylinder group is less than or equal to the number of bits
5554 5554 * in one-third (or whatever proportion is assumed) of a file system
5555 5555 * block. The details of the calculation are:
5556 5556 *
5557 5557 * The macro MAXIpG_B(bsize, inode_divisor) determines the maximum
5558 5558 * number of inodes that can be in a cylinder group, given the
5559 5559 * proportion of the cylinder group overhead block used for the
5560 5560 * inode bitmaps (an inode_divisor of 3 means that 1/3 of the
5561 5561 * block is used for inode bitmaps; an inode_divisor of 12 means
5562 5562 * that 1/12 of the block is used for inode bitmaps.)
5563 5563 *
5564 5564 * Once the number of inodes per cylinder group is known, the
5565 5565 * maximum value of cylinders-per-group (determined by nbpi)
5566 5566 * is calculated by the formula
5567 5567 *
5568 5568 * maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder)
5569 5569 *
5570 5570 * = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE)
5571 5571 *
5572 5572 * (Interestingly, the size of the file system never enters
5573 5573 * into this calculation.)
5574 5574 *
5575 5575 * Another possible value for the maximum cylinder group size is determined
5576 5576 * by frag_size and nrpos. The frags in the cylinder group must be
5577 5577 * representable in the frag bitmaps in the cylinder overhead block and the
5578 5578 * rotational positions for each cylinder must be represented in the
5579 5579 * rotational position tables. The calculation of the maximum cpg
5580 5580 * value, given the frag and nrpos vales, is:
5581 5581 *
5582 5582 * maxcpg_given_fragsize =
5583 5583 * (available space in the overhead block) / (size of per-cylinder data)
5584 5584 *
5585 5585 * The available space in the overhead block =
5586 5586 * bsize - sizeof (struct cg) - space_used_for_inode_bitmaps
5587 5587 *
5588 5588 * The size of the per-cylinder data is:
5589 5589 * sizeof(long) # for the "blocks avail per cylinder" field
5590 5590 * + nrpos * sizeof(short) # for the rotational position table entry
5591 5591 * + frags-per-cylinder/NBBY # number of bytes to represent this
5592 5592 * # cylinder in the frag bitmap
5593 5593 *
5594 5594 * The two calculated maximum values of cylinder-per-group will typically
5595 5595 * turn out to be different, since they are derived from two different
5596 5596 * constraints. Usually, maxcpg_given_nbpi is much bigger than
5597 5597 * maxcpg_given_fragsize. But they can be brought together by
5598 5598 * adjusting the proportion of the overhead block dedicated to
5599 5599 * the inode bitmaps. Decreasing the proportion of the cylinder
5600 5600 * group overhead block used for inode maps will decrease
5601 5601 * maxcpg_given_nbpi and increase maxcpg_given_fragsize.
5602 5602 *
5603 5603 * This function calculates the initial values of maxcpg_given_nbpi
5604 5604 * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead
5605 5605 * block is used for inode bitmaps. Then it decreases the proportion
5606 5606 * of the cg overhead block used for inode bitmaps (by increasing
5607 5607 * the value of inode_divisor) until maxcpg_given_nbpi and
5608 5608 * maxcpg_given_fragsize are the same, or stop changing, or
5609 5609 * maxcpg_given_nbpi is less than maxcpg_given_fragsize.
5610 5610 *
5611 5611 * The loop terminates when any of the following occur:
5612 5612 * * maxcpg_given_fragsize is greater than or equal to
5613 5613 * maxcpg_given_nbpi
5614 5614 * * neither maxcpg_given_fragsize nor maxcpg_given_nbpi
5615 5615 * change in the expected direction
5616 5616 *
5617 5617 * The loop is guaranteed to terminate because it only continues
5618 5618 * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching
5619 5619 * each other. As soon they cross each other, or neither one changes
5620 5620 * in the direction of the other, or one of them moves in the wrong
5621 5621 * direction, the loop completes.
5622 5622 */
5623 5623
5624 5624 static long
5625 5625 compute_maxcpg(long bsize, long fragsize, long nbpi, long nrpos, long spc)
5626 5626 {
5627 5627 int maxcpg_given_nbpi; /* in cylinders */
5628 5628 int maxcpg_given_fragsize; /* in cylinders */
5629 5629 int spf; /* sectors per frag */
5630 5630 int inode_divisor;
5631 5631 int old_max_given_frag = 0;
5632 5632 int old_max_given_nbpi = INT_MAX;
5633 5633
5634 5634 spf = fragsize / DEV_BSIZE;
5635 5635 inode_divisor = 3;
5636 5636
5637 5637 while (1) {
5638 5638 maxcpg_given_nbpi =
5639 5639 (((int64_t)(MAXIpG_B(bsize, inode_divisor))) * nbpi) /
5640 5640 (DEV_BSIZE * ((int64_t)spc));
5641 5641 maxcpg_given_fragsize =
5642 5642 (bsize - (sizeof (struct cg)) - (bsize / inode_divisor)) /
5643 5643 (sizeof (long) + nrpos * sizeof (short) +
5644 5644 (spc / spf) / NBBY);
5645 5645
5646 5646 if (maxcpg_given_fragsize >= maxcpg_given_nbpi)
5647 5647 return (maxcpg_given_nbpi);
5648 5648
5649 5649 /*
5650 5650 * If neither value moves toward the other, return the
5651 5651 * least of the old values (we use the old instead of the
5652 5652 * new because: if the old is the same as the new, it
5653 5653 * doesn't matter which ones we use. If one of the
5654 5654 * values changed, but in the wrong direction, the
5655 5655 * new values are suspect. Better use the old. This
5656 5656 * shouldn't happen, but it's best to check.
5657 5657 */
5658 5658
5659 5659 if (!(maxcpg_given_nbpi < old_max_given_nbpi) &&
5660 5660 !(maxcpg_given_fragsize > old_max_given_frag))
5661 5661 return (MIN(old_max_given_nbpi, old_max_given_frag));
5662 5662
5663 5663 /*
5664 5664 * This is probably impossible, but if one of the maxcpg
5665 5665 * values moved in the "right" direction and one moved
5666 5666 * in the "wrong" direction (that is, the two values moved
5667 5667 * in the same direction), the previous conditional won't
5668 5668 * recognize that the values aren't converging (since at
5669 5669 * least one value moved in the "right" direction, the
5670 5670 * last conditional says "keep going").
5671 5671 *
5672 5672 * Just to make absolutely certain that the loop terminates,
5673 5673 * check for one of the values moving in the "wrong" direction
5674 5674 * and terminate the loop if it happens.
5675 5675 */
5676 5676
5677 5677 if (maxcpg_given_nbpi > old_max_given_nbpi ||
5678 5678 maxcpg_given_fragsize < old_max_given_frag)
5679 5679 return (MIN(old_max_given_nbpi, old_max_given_frag));
5680 5680
5681 5681 old_max_given_nbpi = maxcpg_given_nbpi;
5682 5682 old_max_given_frag = maxcpg_given_fragsize;
5683 5683
5684 5684 inode_divisor++;
5685 5685 }
5686 5686 }
5687 5687
5688 5688 static int
5689 5689 in_64bit_mode(void)
5690 5690 {
5691 5691 /* cmd must be an absolute path, for security */
5692 5692 char *cmd = "/usr/bin/isainfo -b";
5693 5693 char buf[BUFSIZ];
5694 5694 FILE *ptr;
5695 5695 int retval = 0;
5696 5696
5697 5697 putenv("IFS= \t");
5698 5698 if ((ptr = popen(cmd, "r")) != NULL) {
5699 5699 if (fgets(buf, BUFSIZ, ptr) != NULL &&
5700 5700 strncmp(buf, "64", 2) == 0)
5701 5701 retval = 1;
5702 5702 (void) pclose(ptr);
5703 5703 }
5704 5704 return (retval);
5705 5705 }
5706 5706
5707 5707 /*
5708 5708 * validate_size
5709 5709 *
5710 5710 * Return 1 if the device appears to be at least "size" sectors long.
5711 5711 * Return 0 if it's shorter or we can't read it.
5712 5712 */
5713 5713
5714 5714 static int
5715 5715 validate_size(int fd, diskaddr_t size)
5716 5716 {
5717 5717 char buf[DEV_BSIZE];
5718 5718 int rc;
5719 5719
5720 5720 if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) ||
5721 5721 (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)
5722 5722 rc = 0;
5723 5723 else
5724 5724 rc = 1;
5725 5725 return (rc);
5726 5726 }
5727 5727
5728 5728 /*
5729 5729 * Print every field of the calculated superblock, along with
5730 5730 * its value. To make parsing easier on the caller, the value
5731 5731 * is printed first, then the name. Additionally, there's only
5732 5732 * one name/value pair per line. All values are reported in
5733 5733 * hexadecimal (with the traditional 0x prefix), as that's slightly
5734 5734 * easier for humans to read. Not that they're expected to, but
5735 5735 * debugging happens.
5736 5736 */
5737 5737 static void
5738 5738 dump_sblock(void)
5739 5739 {
5740 5740 int row, column, pending, written;
5741 5741 caddr_t source;
5742 5742
5743 5743 if (Rflag) {
5744 5744 pending = sizeof (sblock);
5745 5745 source = (caddr_t)&sblock;
5746 5746 do {
5747 5747 written = write(fileno(stdout), source, pending);
5748 5748 pending -= written;
5749 5749 source += written;
5750 5750 } while ((pending > 0) && (written > 0));
5751 5751
5752 5752 if (written < 0) {
5753 5753 perror(gettext("Binary dump of superblock failed"));
5754 5754 lockexit(1);
5755 5755 }
5756 5756 return;
5757 5757 } else {
5758 5758 printf("0x%x sblock.fs_link\n", sblock.fs_link);
5759 5759 printf("0x%x sblock.fs_rolled\n", sblock.fs_rolled);
5760 5760 printf("0x%x sblock.fs_sblkno\n", sblock.fs_sblkno);
5761 5761 printf("0x%x sblock.fs_cblkno\n", sblock.fs_cblkno);
5762 5762 printf("0x%x sblock.fs_iblkno\n", sblock.fs_iblkno);
5763 5763 printf("0x%x sblock.fs_dblkno\n", sblock.fs_dblkno);
5764 5764 printf("0x%x sblock.fs_cgoffset\n", sblock.fs_cgoffset);
5765 5765 printf("0x%x sblock.fs_cgmask\n", sblock.fs_cgmask);
5766 5766 printf("0x%x sblock.fs_time\n", sblock.fs_time);
5767 5767 printf("0x%x sblock.fs_size\n", sblock.fs_size);
5768 5768 printf("0x%x sblock.fs_dsize\n", sblock.fs_dsize);
5769 5769 printf("0x%x sblock.fs_ncg\n", sblock.fs_ncg);
5770 5770 printf("0x%x sblock.fs_bsize\n", sblock.fs_bsize);
5771 5771 printf("0x%x sblock.fs_fsize\n", sblock.fs_fsize);
5772 5772 printf("0x%x sblock.fs_frag\n", sblock.fs_frag);
5773 5773 printf("0x%x sblock.fs_minfree\n", sblock.fs_minfree);
5774 5774 printf("0x%x sblock.fs_rotdelay\n", sblock.fs_rotdelay);
5775 5775 printf("0x%x sblock.fs_rps\n", sblock.fs_rps);
5776 5776 printf("0x%x sblock.fs_bmask\n", sblock.fs_bmask);
5777 5777 printf("0x%x sblock.fs_fmask\n", sblock.fs_fmask);
5778 5778 printf("0x%x sblock.fs_bshift\n", sblock.fs_bshift);
5779 5779 printf("0x%x sblock.fs_fshift\n", sblock.fs_fshift);
5780 5780 printf("0x%x sblock.fs_maxcontig\n", sblock.fs_maxcontig);
5781 5781 printf("0x%x sblock.fs_maxbpg\n", sblock.fs_maxbpg);
5782 5782 printf("0x%x sblock.fs_fragshift\n", sblock.fs_fragshift);
5783 5783 printf("0x%x sblock.fs_fsbtodb\n", sblock.fs_fsbtodb);
5784 5784 printf("0x%x sblock.fs_sbsize\n", sblock.fs_sbsize);
5785 5785 printf("0x%x sblock.fs_csmask\n", sblock.fs_csmask);
5786 5786 printf("0x%x sblock.fs_csshift\n", sblock.fs_csshift);
5787 5787 printf("0x%x sblock.fs_nindir\n", sblock.fs_nindir);
5788 5788 printf("0x%x sblock.fs_inopb\n", sblock.fs_inopb);
5789 5789 printf("0x%x sblock.fs_nspf\n", sblock.fs_nspf);
5790 5790 printf("0x%x sblock.fs_optim\n", sblock.fs_optim);
5791 5791 #ifdef _LITTLE_ENDIAN
5792 5792 printf("0x%x sblock.fs_state\n", sblock.fs_state);
5793 5793 #else
5794 5794 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5795 5795 #endif
5796 5796 printf("0x%x sblock.fs_si\n", sblock.fs_si);
5797 5797 printf("0x%x sblock.fs_trackskew\n", sblock.fs_trackskew);
5798 5798 printf("0x%x sblock.fs_id[0]\n", sblock.fs_id[0]);
5799 5799 printf("0x%x sblock.fs_id[1]\n", sblock.fs_id[1]);
5800 5800 printf("0x%x sblock.fs_csaddr\n", sblock.fs_csaddr);
5801 5801 printf("0x%x sblock.fs_cssize\n", sblock.fs_cssize);
5802 5802 printf("0x%x sblock.fs_cgsize\n", sblock.fs_cgsize);
5803 5803 printf("0x%x sblock.fs_ntrak\n", sblock.fs_ntrak);
5804 5804 printf("0x%x sblock.fs_nsect\n", sblock.fs_nsect);
5805 5805 printf("0x%x sblock.fs_spc\n", sblock.fs_spc);
5806 5806 printf("0x%x sblock.fs_ncyl\n", sblock.fs_ncyl);
5807 5807 printf("0x%x sblock.fs_cpg\n", sblock.fs_cpg);
5808 5808 printf("0x%x sblock.fs_ipg\n", sblock.fs_ipg);
5809 5809 printf("0x%x sblock.fs_fpg\n", sblock.fs_fpg);
5810 5810 printf("0x%x sblock.fs_cstotal\n", sblock.fs_cstotal);
5811 5811 printf("0x%x sblock.fs_fmod\n", sblock.fs_fmod);
5812 5812 printf("0x%x sblock.fs_clean\n", sblock.fs_clean);
5813 5813 printf("0x%x sblock.fs_ronly\n", sblock.fs_ronly);
5814 5814 printf("0x%x sblock.fs_flags\n", sblock.fs_flags);
5815 5815 printf("0x%x sblock.fs_fsmnt\n", sblock.fs_fsmnt);
5816 5816 printf("0x%x sblock.fs_cgrotor\n", sblock.fs_cgrotor);
5817 5817 printf("0x%x sblock.fs_u.fs_csp\n", sblock.fs_u.fs_csp);
5818 5818 printf("0x%x sblock.fs_cpc\n", sblock.fs_cpc);
5819 5819
5820 5820 /*
5821 5821 * No macros are defined for the dimensions of the
5822 5822 * opostbl array.
5823 5823 */
5824 5824 for (row = 0; row < 16; row++) {
5825 5825 for (column = 0; column < 8; column++) {
5826 5826 printf("0x%x sblock.fs_opostbl[%d][%d]\n",
5827 5827 sblock.fs_opostbl[row][column],
5828 5828 row, column);
5829 5829 }
5830 5830 }
5831 5831
5832 5832 /*
5833 5833 * Ditto the size of sparecon.
5834 5834 */
5835 5835 for (row = 0; row < 51; row++) {
5836 5836 printf("0x%x sblock.fs_sparecon[%d]\n",
5837 5837 sblock.fs_sparecon[row], row);
5838 5838 }
5839 5839
5840 5840 printf("0x%x sblock.fs_version\n", sblock.fs_version);
5841 5841 printf("0x%x sblock.fs_logbno\n", sblock.fs_logbno);
5842 5842 printf("0x%x sblock.fs_reclaim\n", sblock.fs_reclaim);
5843 5843 printf("0x%x sblock.fs_sparecon2\n", sblock.fs_sparecon2);
5844 5844 #ifdef _LITTLE_ENDIAN
5845 5845 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5846 5846 #else
5847 5847 printf("0x%x sblock.fs_state\n", sblock.fs_state);
5848 5848 #endif
5849 5849 printf("0x%llx sblock.fs_qbmask\n", sblock.fs_qbmask);
5850 5850 printf("0x%llx sblock.fs_qfmask\n", sblock.fs_qfmask);
5851 5851 printf("0x%x sblock.fs_postblformat\n", sblock.fs_postblformat);
5852 5852 printf("0x%x sblock.fs_nrpos\n", sblock.fs_nrpos);
5853 5853 printf("0x%x sblock.fs_postbloff\n", sblock.fs_postbloff);
5854 5854 printf("0x%x sblock.fs_rotbloff\n", sblock.fs_rotbloff);
5855 5855 printf("0x%x sblock.fs_magic\n", sblock.fs_magic);
5856 5856
5857 5857 /*
5858 5858 * fs_space isn't of much use in this context, so we'll
5859 5859 * just ignore it for now.
5860 5860 */
5861 5861 }
5862 5862 }
↓ open down ↓ |
3026 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX