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