1 1.137 andvar /* $NetBSD: mkfs.c,v 1.137 2024/05/10 20:36:34 andvar Exp $ */ 2 1.71 agc 3 1.71 agc /* 4 1.71 agc * Copyright (c) 1980, 1989, 1993 5 1.71 agc * The Regents of the University of California. All rights reserved. 6 1.71 agc * 7 1.71 agc * Redistribution and use in source and binary forms, with or without 8 1.71 agc * modification, are permitted provided that the following conditions 9 1.71 agc * are met: 10 1.71 agc * 1. Redistributions of source code must retain the above copyright 11 1.71 agc * notice, this list of conditions and the following disclaimer. 12 1.71 agc * 2. Redistributions in binary form must reproduce the above copyright 13 1.71 agc * notice, this list of conditions and the following disclaimer in the 14 1.71 agc * documentation and/or other materials provided with the distribution. 15 1.71 agc * 3. Neither the name of the University nor the names of its contributors 16 1.71 agc * may be used to endorse or promote products derived from this software 17 1.71 agc * without specific prior written permission. 18 1.71 agc * 19 1.71 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.71 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.71 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.71 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.71 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.71 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.71 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.71 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.71 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.71 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.71 agc * SUCH DAMAGE. 30 1.71 agc */ 31 1.19 cgd 32 1.1 cgd /* 33 1.68 fvdl * Copyright (c) 2002 Networks Associates Technology, Inc. 34 1.68 fvdl * All rights reserved. 35 1.68 fvdl * 36 1.68 fvdl * This software was developed for the FreeBSD Project by Marshall 37 1.68 fvdl * Kirk McKusick and Network Associates Laboratories, the Security 38 1.68 fvdl * Research Division of Network Associates, Inc. under DARPA/SPAWAR 39 1.68 fvdl * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 40 1.68 fvdl * research program 41 1.68 fvdl * 42 1.1 cgd * Redistribution and use in source and binary forms, with or without 43 1.1 cgd * modification, are permitted provided that the following conditions 44 1.1 cgd * are met: 45 1.1 cgd * 1. Redistributions of source code must retain the above copyright 46 1.1 cgd * notice, this list of conditions and the following disclaimer. 47 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 cgd * notice, this list of conditions and the following disclaimer in the 49 1.1 cgd * documentation and/or other materials provided with the distribution. 50 1.1 cgd * 3. All advertising materials mentioning features or use of this software 51 1.1 cgd * must display the following acknowledgement: 52 1.1 cgd * This product includes software developed by the University of 53 1.1 cgd * California, Berkeley and its contributors. 54 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 55 1.1 cgd * may be used to endorse or promote products derived from this software 56 1.1 cgd * without specific prior written permission. 57 1.1 cgd * 58 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 1.1 cgd * SUCH DAMAGE. 69 1.1 cgd */ 70 1.1 cgd 71 1.26 christos #include <sys/cdefs.h> 72 1.1 cgd #ifndef lint 73 1.19 cgd #if 0 74 1.27 lukem static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 75 1.19 cgd #else 76 1.137 andvar __RCSID("$NetBSD: mkfs.c,v 1.137 2024/05/10 20:36:34 andvar Exp $"); 77 1.19 cgd #endif 78 1.1 cgd #endif /* not lint */ 79 1.1 cgd 80 1.1 cgd #include <sys/param.h> 81 1.60 simonb #include <sys/mman.h> 82 1.1 cgd #include <sys/time.h> 83 1.1 cgd #include <sys/resource.h> 84 1.9 mycroft #include <ufs/ufs/dinode.h> 85 1.9 mycroft #include <ufs/ufs/dir.h> 86 1.30 bouyer #include <ufs/ufs/ufs_bswap.h> 87 1.109 bouyer #include <ufs/ufs/quota2.h> 88 1.9 mycroft #include <ufs/ffs/fs.h> 89 1.30 bouyer #include <ufs/ffs/ffs_extern.h> 90 1.98 dsl #include <sys/ioctl.h> 91 1.1 cgd #include <sys/disklabel.h> 92 1.9 mycroft 93 1.60 simonb #include <err.h> 94 1.57 lukem #include <errno.h> 95 1.14 cgd #include <string.h> 96 1.14 cgd #include <unistd.h> 97 1.26 christos #include <stdlib.h> 98 1.80 dsl #include <stddef.h> 99 1.14 cgd 100 1.9 mycroft #ifndef STANDALONE 101 1.9 mycroft #include <stdio.h> 102 1.9 mycroft #endif 103 1.40 simonb 104 1.40 simonb #include "extern.h" 105 1.1 cgd 106 1.68 fvdl union dinode { 107 1.68 fvdl struct ufs1_dinode dp1; 108 1.68 fvdl struct ufs2_dinode dp2; 109 1.68 fvdl }; 110 1.68 fvdl 111 1.133 chs static void initcg(uint32_t, const struct timeval *); 112 1.70 atatat static int fsinit(const struct timeval *, mode_t, uid_t, gid_t); 113 1.124 christos union Buffer; 114 1.124 christos static int makedir(union Buffer *, struct direct *, int); 115 1.39 simonb static daddr_t alloc(int, int); 116 1.68 fvdl static void iput(union dinode *, ino_t); 117 1.39 simonb static void rdfs(daddr_t, int, void *); 118 1.39 simonb static void wtfs(daddr_t, int, void *); 119 1.39 simonb static int isblock(struct fs *, unsigned char *, int); 120 1.39 simonb static void clrblock(struct fs *, unsigned char *, int); 121 1.39 simonb static void setblock(struct fs *, unsigned char *, int); 122 1.68 fvdl static int ilog2(int); 123 1.80 dsl static void zap_old_sblock(int); 124 1.61 lukem #ifdef MFS 125 1.60 simonb static void *mkfs_malloc(size_t size); 126 1.61 lukem #endif 127 1.27 lukem 128 1.1 cgd /* 129 1.1 cgd * make file system for cylinder-group style file systems 130 1.1 cgd */ 131 1.60 simonb #define UMASK 0755 132 1.1 cgd 133 1.1 cgd union { 134 1.1 cgd struct fs fs; 135 1.122 martin char data[SBLOCKSIZE]; 136 1.123 christos } *fsun; 137 1.123 christos #define sblock fsun->fs 138 1.73 dsl 139 1.123 christos union Buffer { 140 1.122 martin struct quota2_header q2h; 141 1.122 martin char data[MAXBSIZE]; 142 1.123 christos }; 143 1.122 martin 144 1.73 dsl struct csum *fscs_0; /* first block of cylinder summaries */ 145 1.73 dsl struct csum *fscs_next; /* place for next summary */ 146 1.73 dsl struct csum *fscs_end; /* end of summary buffer */ 147 1.73 dsl struct csum *fscs_reset; /* place for next summary after write */ 148 1.73 dsl uint fs_csaddr; /* fragment number to write to */ 149 1.1 cgd 150 1.1 cgd union { 151 1.1 cgd struct cg cg; 152 1.1 cgd char pad[MAXBSIZE]; 153 1.123 christos } *cgun; 154 1.123 christos #define acg cgun->cg 155 1.1 cgd 156 1.68 fvdl #define DIP(dp, field) \ 157 1.68 fvdl ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ 158 1.68 fvdl (dp)->dp1.di_##field : (dp)->dp2.di_##field) 159 1.68 fvdl 160 1.111 tsutsui #define EXT2FS_SBOFF 1024 /* XXX: SBOFF in <ufs/ext2fs/ext2fs.h> */ 161 1.111 tsutsui 162 1.68 fvdl char *iobuf; 163 1.87 dsl int iobufsize; /* size to end of 2nd inode block */ 164 1.87 dsl int iobuf_memsize; /* Actual buffer size */ 165 1.1 cgd 166 1.1 cgd int fsi, fso; 167 1.1 cgd 168 1.108 pooka static void 169 1.108 pooka fserr(int num) 170 1.108 pooka { 171 1.108 pooka #ifdef GARBAGE 172 1.108 pooka extern int Gflag; 173 1.108 pooka 174 1.108 pooka if (Gflag) 175 1.108 pooka return; 176 1.108 pooka #endif 177 1.108 pooka exit(num); 178 1.108 pooka } 179 1.108 pooka 180 1.26 christos void 181 1.101 christos mkfs(const char *fsys, int fi, int fo, 182 1.60 simonb mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 183 1.1 cgd { 184 1.105 lukem uint fragsperinodeblk, ncg, u; 185 1.74 dsl uint cgzero; 186 1.74 dsl uint64_t inodeblks, cgall; 187 1.133 chs uint32_t cylno; 188 1.133 chs int i, csfrags; 189 1.96 dsl int inodes_per_cg; 190 1.70 atatat struct timeval tv; 191 1.52 lukem long long sizepb; 192 1.98 dsl int len, col, delta, fld_width, max_cols; 193 1.98 dsl struct winsize winsize; 194 1.1 cgd 195 1.1 cgd #ifndef STANDALONE 196 1.70 atatat gettimeofday(&tv, NULL); 197 1.1 cgd #endif 198 1.61 lukem #ifdef MFS 199 1.86 dsl if (mfs && !Nflag) { 200 1.104 jnemeth if ((membase = mkfs_malloc(fssize * sectorsize)) == NULL) 201 1.1 cgd exit(12); 202 1.1 cgd } 203 1.61 lukem #endif 204 1.129 jdolecek if ((fsun = aligned_alloc(DEV_BSIZE, sizeof(*fsun))) == NULL) 205 1.123 christos exit(12); 206 1.129 jdolecek memset(fsun, 0, sizeof(*fsun)); 207 1.129 jdolecek if ((cgun = aligned_alloc(DEV_BSIZE, sizeof(*cgun))) == NULL) 208 1.123 christos exit(12); 209 1.129 jdolecek memset(cgun, 0, sizeof(*cgun)); 210 1.123 christos 211 1.1 cgd fsi = fi; 212 1.1 cgd fso = fo; 213 1.68 fvdl if (Oflag == 0) { 214 1.68 fvdl sblock.fs_old_inodefmt = FS_42INODEFMT; 215 1.9 mycroft sblock.fs_maxsymlinklen = 0; 216 1.68 fvdl sblock.fs_old_flags = 0; 217 1.9 mycroft } else { 218 1.68 fvdl sblock.fs_old_inodefmt = FS_44INODEFMT; 219 1.113 dholland sblock.fs_maxsymlinklen = (Oflag == 1 ? UFS1_MAXSYMLINKLEN : 220 1.113 dholland UFS2_MAXSYMLINKLEN); 221 1.68 fvdl sblock.fs_old_flags = FS_FLAGS_UPDATED; 222 1.88 dbj if (isappleufs) 223 1.88 dbj sblock.fs_old_flags = 0; 224 1.68 fvdl sblock.fs_flags = 0; 225 1.9 mycroft } 226 1.65 dbj 227 1.1 cgd /* 228 1.55 lukem * collect and verify the filesystem density info 229 1.55 lukem */ 230 1.55 lukem sblock.fs_avgfilesize = avgfilesize; 231 1.55 lukem sblock.fs_avgfpdir = avgfpdir; 232 1.72 dsl if (sblock.fs_avgfilesize <= 0) { 233 1.55 lukem printf("illegal expected average file size %d\n", 234 1.72 dsl sblock.fs_avgfilesize); 235 1.108 pooka fserr(14); 236 1.72 dsl } 237 1.72 dsl if (sblock.fs_avgfpdir <= 0) { 238 1.55 lukem printf("illegal expected number of files per directory %d\n", 239 1.72 dsl sblock.fs_avgfpdir); 240 1.108 pooka fserr(15); 241 1.72 dsl } 242 1.1 cgd /* 243 1.1 cgd * collect and verify the block and fragment sizes 244 1.1 cgd */ 245 1.1 cgd sblock.fs_bsize = bsize; 246 1.1 cgd sblock.fs_fsize = fsize; 247 1.103 tsutsui if (!powerof2(sblock.fs_bsize)) { 248 1.1 cgd printf("block size must be a power of 2, not %d\n", 249 1.1 cgd sblock.fs_bsize); 250 1.108 pooka fserr(16); 251 1.1 cgd } 252 1.103 tsutsui if (!powerof2(sblock.fs_fsize)) { 253 1.1 cgd printf("fragment size must be a power of 2, not %d\n", 254 1.1 cgd sblock.fs_fsize); 255 1.108 pooka fserr(17); 256 1.1 cgd } 257 1.1 cgd if (sblock.fs_fsize < sectorsize) { 258 1.1 cgd printf("fragment size %d is too small, minimum is %d\n", 259 1.1 cgd sblock.fs_fsize, sectorsize); 260 1.108 pooka fserr(18); 261 1.1 cgd } 262 1.1 cgd if (sblock.fs_bsize < MINBSIZE) { 263 1.1 cgd printf("block size %d is too small, minimum is %d\n", 264 1.1 cgd sblock.fs_bsize, MINBSIZE); 265 1.108 pooka fserr(19); 266 1.58 lukem } 267 1.58 lukem if (sblock.fs_bsize > MAXBSIZE) { 268 1.58 lukem printf("block size %d is too large, maximum is %d\n", 269 1.58 lukem sblock.fs_bsize, MAXBSIZE); 270 1.108 pooka fserr(19); 271 1.1 cgd } 272 1.1 cgd if (sblock.fs_bsize < sblock.fs_fsize) { 273 1.1 cgd printf("block size (%d) cannot be smaller than fragment size (%d)\n", 274 1.1 cgd sblock.fs_bsize, sblock.fs_fsize); 275 1.108 pooka fserr(20); 276 1.1 cgd } 277 1.68 fvdl 278 1.103 tsutsui if (maxbsize < bsize || !powerof2(maxbsize)) { 279 1.68 fvdl sblock.fs_maxbsize = sblock.fs_bsize; 280 1.68 fvdl } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) { 281 1.68 fvdl sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize; 282 1.68 fvdl } else { 283 1.68 fvdl sblock.fs_maxbsize = maxbsize; 284 1.68 fvdl } 285 1.68 fvdl sblock.fs_maxcontig = maxcontig; 286 1.68 fvdl if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) { 287 1.68 fvdl sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize; 288 1.98 dsl if (verbosity > 0) 289 1.98 dsl printf("Maxcontig raised to %d\n", sblock.fs_maxbsize); 290 1.68 fvdl } 291 1.68 fvdl if (sblock.fs_maxcontig > 1) 292 1.68 fvdl sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG); 293 1.68 fvdl 294 1.1 cgd sblock.fs_bmask = ~(sblock.fs_bsize - 1); 295 1.1 cgd sblock.fs_fmask = ~(sblock.fs_fsize - 1); 296 1.9 mycroft sblock.fs_qbmask = ~sblock.fs_bmask; 297 1.9 mycroft sblock.fs_qfmask = ~sblock.fs_fmask; 298 1.1 cgd for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 299 1.1 cgd sblock.fs_bshift++; 300 1.1 cgd for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 301 1.1 cgd sblock.fs_fshift++; 302 1.119 dholland sblock.fs_frag = ffs_numfrags(&sblock, sblock.fs_bsize); 303 1.1 cgd for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 304 1.1 cgd sblock.fs_fragshift++; 305 1.1 cgd if (sblock.fs_frag > MAXFRAG) { 306 1.30 bouyer printf("fragment size %d is too small, " 307 1.30 bouyer "minimum with block size %d is %d\n", 308 1.1 cgd sblock.fs_fsize, sblock.fs_bsize, 309 1.1 cgd sblock.fs_bsize / MAXFRAG); 310 1.108 pooka fserr(21); 311 1.1 cgd } 312 1.68 fvdl sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); 313 1.117 dholland sblock.fs_size = FFS_DBTOFSB(&sblock, fssize); 314 1.68 fvdl if (Oflag <= 1) { 315 1.105 lukem if ((uint64_t)sblock.fs_size >= 1ull << 31) { 316 1.72 dsl printf("Too many fragments (0x%" PRIx64 317 1.106 lukem ") for a FFSv1 filesystem\n", sblock.fs_size); 318 1.108 pooka fserr(22); 319 1.72 dsl } 320 1.68 fvdl sblock.fs_magic = FS_UFS1_MAGIC; 321 1.68 fvdl sblock.fs_sblockloc = SBLOCK_UFS1; 322 1.68 fvdl sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t); 323 1.68 fvdl sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); 324 1.68 fvdl sblock.fs_old_cgoffset = 0; 325 1.68 fvdl sblock.fs_old_cgmask = 0xffffffff; 326 1.68 fvdl sblock.fs_old_size = sblock.fs_size; 327 1.68 fvdl sblock.fs_old_rotdelay = 0; 328 1.68 fvdl sblock.fs_old_rps = 60; 329 1.68 fvdl sblock.fs_old_nspf = sblock.fs_fsize / sectorsize; 330 1.68 fvdl sblock.fs_old_cpg = 1; 331 1.68 fvdl sblock.fs_old_interleave = 1; 332 1.68 fvdl sblock.fs_old_trackskew = 0; 333 1.68 fvdl sblock.fs_old_cpc = 0; 334 1.72 dsl sblock.fs_old_postblformat = FS_DYNAMICPOSTBLFMT; 335 1.68 fvdl sblock.fs_old_nrpos = 1; 336 1.68 fvdl } else { 337 1.68 fvdl sblock.fs_magic = FS_UFS2_MAGIC; 338 1.68 fvdl sblock.fs_sblockloc = SBLOCK_UFS2; 339 1.68 fvdl sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); 340 1.68 fvdl sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); 341 1.68 fvdl } 342 1.68 fvdl 343 1.1 cgd sblock.fs_sblkno = 344 1.68 fvdl roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize), 345 1.68 fvdl sblock.fs_frag); 346 1.1 cgd sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 347 1.68 fvdl roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag)); 348 1.1 cgd sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 349 1.113 dholland sblock.fs_maxfilesize = sblock.fs_bsize * UFS_NDADDR - 1; 350 1.113 dholland for (sizepb = sblock.fs_bsize, i = 0; i < UFS_NIADDR; i++) { 351 1.116 dholland sizepb *= FFS_NINDIR(&sblock); 352 1.9 mycroft sblock.fs_maxfilesize += sizepb; 353 1.9 mycroft } 354 1.68 fvdl 355 1.1 cgd /* 356 1.68 fvdl * Calculate the number of blocks to put into each cylinder group. 357 1.68 fvdl * 358 1.74 dsl * The cylinder group size is limited because the data structure 359 1.74 dsl * must fit into a single block. 360 1.74 dsl * We try to have as few cylinder groups as possible, with a proviso 361 1.74 dsl * that we create at least MINCYLGRPS (==4) except for small 362 1.74 dsl * filesystems. 363 1.68 fvdl * 364 1.74 dsl * This algorithm works out how many blocks of inodes would be 365 1.74 dsl * needed to fill the entire volume at the specified density. 366 1.74 dsl * It then looks at how big the 'cylinder block' would have to 367 1.74 dsl * be and, assuming that it is linearly related to the number 368 1.74 dsl * of inodes and blocks how many cylinder groups are needed to 369 1.74 dsl * keep the cylinder block below the filesystem block size. 370 1.74 dsl * 371 1.74 dsl * The cylinder groups are then all created with the average size. 372 1.74 dsl * 373 1.74 dsl * Space taken by the red tape on cylinder groups other than the 374 1.74 dsl * first is ignored. 375 1.68 fvdl */ 376 1.74 dsl 377 1.74 dsl /* There must be space for 1 inode block and 2 data blocks */ 378 1.74 dsl if (sblock.fs_size < sblock.fs_iblkno + 3 * sblock.fs_frag) { 379 1.74 dsl printf("Filesystem size %lld < minimum size of %d\n", 380 1.74 dsl (long long)sblock.fs_size, sblock.fs_iblkno + 3 * sblock.fs_frag); 381 1.108 pooka fserr(23); 382 1.1 cgd } 383 1.81 dsl if (num_inodes != 0) 384 1.116 dholland inodeblks = howmany(num_inodes, FFS_INOPB(&sblock)); 385 1.81 dsl else { 386 1.81 dsl /* 387 1.81 dsl * Calculate 'per inode block' so we can allocate less than 388 1.81 dsl * 1 fragment per inode - useful for /dev. 389 1.81 dsl */ 390 1.119 dholland fragsperinodeblk = MAX(ffs_numfrags(&sblock, 391 1.116 dholland (uint64_t)density * FFS_INOPB(&sblock)), 1); 392 1.81 dsl inodeblks = (sblock.fs_size - sblock.fs_iblkno) / 393 1.81 dsl (sblock.fs_frag + fragsperinodeblk); 394 1.81 dsl } 395 1.74 dsl if (inodeblks == 0) 396 1.74 dsl inodeblks = 1; 397 1.81 dsl /* Ensure that there are at least 2 data blocks (or we fail below) */ 398 1.105 lukem if (inodeblks > (uint64_t)(sblock.fs_size - sblock.fs_iblkno)/sblock.fs_frag - 2) 399 1.81 dsl inodeblks = (sblock.fs_size-sblock.fs_iblkno)/sblock.fs_frag-2; 400 1.74 dsl /* Even UFS2 limits number of inodes to 2^31 (fs_ipg is int32_t) */ 401 1.116 dholland if (inodeblks * FFS_INOPB(&sblock) >= 1ull << 31) 402 1.116 dholland inodeblks = ((1ull << 31) - NBBY) / FFS_INOPB(&sblock); 403 1.74 dsl /* 404 1.74 dsl * See what would happen if we tried to use 1 cylinder group. 405 1.74 dsl * Assume space linear, so work out number of cylinder groups needed. 406 1.68 fvdl */ 407 1.74 dsl cgzero = CGSIZE_IF(&sblock, 0, 0); 408 1.116 dholland cgall = CGSIZE_IF(&sblock, inodeblks * FFS_INOPB(&sblock), sblock.fs_size); 409 1.96 dsl ncg = howmany(cgall - cgzero, sblock.fs_bsize - cgzero); 410 1.74 dsl if (ncg < MINCYLGRPS) { 411 1.74 dsl /* 412 1.74 dsl * We would like to allocate MINCLYGRPS cylinder groups, 413 1.131 msaitoh * but for small file systems (especially ones with a lot 414 1.74 dsl * of inodes) this is not desirable (or possible). 415 1.74 dsl */ 416 1.105 lukem u = sblock.fs_size / 2 / (sblock.fs_iblkno + 417 1.74 dsl inodeblks * sblock.fs_frag); 418 1.105 lukem if (u > ncg) 419 1.105 lukem ncg = u; 420 1.74 dsl if (ncg > MINCYLGRPS) 421 1.74 dsl ncg = MINCYLGRPS; 422 1.74 dsl if (ncg > inodeblks) 423 1.74 dsl ncg = inodeblks; 424 1.68 fvdl } 425 1.68 fvdl /* 426 1.74 dsl * Put an equal number of blocks in each cylinder group. 427 1.74 dsl * Round up so we don't have more fragments in the last CG than 428 1.74 dsl * the earlier ones (does that matter?), but kill a block if the 429 1.74 dsl * CGSIZE becomes too big (only happens if there are a lot of CGs). 430 1.68 fvdl */ 431 1.74 dsl sblock.fs_fpg = roundup(howmany(sblock.fs_size, ncg), sblock.fs_frag); 432 1.96 dsl /* Round up the fragments/group so the bitmap bytes are full */ 433 1.96 dsl sblock.fs_fpg = roundup(sblock.fs_fpg, NBBY); 434 1.116 dholland inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); 435 1.96 dsl 436 1.96 dsl i = CGSIZE_IF(&sblock, inodes_per_cg, sblock.fs_fpg); 437 1.96 dsl if (i > sblock.fs_bsize) { 438 1.74 dsl sblock.fs_fpg -= (i - sblock.fs_bsize) * NBBY; 439 1.96 dsl /* ... and recalculate how many cylinder groups we now need */ 440 1.96 dsl ncg = howmany(sblock.fs_size, sblock.fs_fpg); 441 1.116 dholland inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); 442 1.96 dsl } 443 1.96 dsl sblock.fs_ipg = inodes_per_cg; 444 1.74 dsl /* Sanity check on our sums... */ 445 1.105 lukem if ((int)CGSIZE(&sblock) > sblock.fs_bsize) { 446 1.74 dsl printf("CGSIZE miscalculated %d > %d\n", 447 1.74 dsl (int)CGSIZE(&sblock), sblock.fs_bsize); 448 1.108 pooka fserr(24); 449 1.74 dsl } 450 1.96 dsl 451 1.116 dholland sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / FFS_INOPF(&sblock); 452 1.74 dsl /* Check that the last cylinder group has enough space for the inodes */ 453 1.74 dsl i = sblock.fs_size - sblock.fs_fpg * (ncg - 1ull); 454 1.96 dsl if (i < sblock.fs_dblkno) { 455 1.74 dsl /* 456 1.74 dsl * Since we make all the cylinder groups the same size, the 457 1.74 dsl * last will only be small if there are a large number of 458 1.74 dsl * cylinder groups. If we pull even a fragment from each 459 1.74 dsl * of the other groups then the last CG will be overfull. 460 1.74 dsl * So we just kill the last CG. 461 1.74 dsl */ 462 1.74 dsl ncg--; 463 1.74 dsl sblock.fs_size -= i; 464 1.74 dsl } 465 1.74 dsl sblock.fs_ncg = ncg; 466 1.74 dsl 467 1.119 dholland sblock.fs_cgsize = ffs_fragroundup(&sblock, CGSIZE(&sblock)); 468 1.68 fvdl if (Oflag <= 1) { 469 1.68 fvdl sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf; 470 1.68 fvdl sblock.fs_old_nsect = sblock.fs_old_spc; 471 1.68 fvdl sblock.fs_old_npsect = sblock.fs_old_spc; 472 1.68 fvdl sblock.fs_old_ncyl = sblock.fs_ncg; 473 1.1 cgd } 474 1.68 fvdl 475 1.1 cgd /* 476 1.73 dsl * Cylinder group summary information for each cylinder is written 477 1.73 dsl * into the first cylinder group. 478 1.73 dsl * Write this fragment by fragment, but doing the first CG last 479 1.73 dsl * (after we've taken stuff off for the structure itself and the 480 1.73 dsl * root directory. 481 1.1 cgd */ 482 1.1 cgd sblock.fs_csaddr = cgdmin(&sblock, 0); 483 1.1 cgd sblock.fs_cssize = 484 1.119 dholland ffs_fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 485 1.73 dsl if (512 % sizeof *fscs_0) 486 1.73 dsl errx(1, "cylinder group summary doesn't fit in sectors"); 487 1.87 dsl fscs_0 = mmap(0, 2 * sblock.fs_fsize, PROT_READ|PROT_WRITE, 488 1.87 dsl MAP_ANON|MAP_PRIVATE, -1, 0); 489 1.104 jnemeth if (fscs_0 == MAP_FAILED) 490 1.44 lukem exit(39); 491 1.87 dsl memset(fscs_0, 0, 2 * sblock.fs_fsize); 492 1.73 dsl fs_csaddr = sblock.fs_csaddr; 493 1.73 dsl fscs_next = fscs_0; 494 1.73 dsl fscs_end = (void *)((char *)fscs_0 + 2 * sblock.fs_fsize); 495 1.73 dsl fscs_reset = (void *)((char *)fscs_0 + sblock.fs_fsize); 496 1.73 dsl /* 497 1.73 dsl * fill in remaining fields of the super block 498 1.73 dsl */ 499 1.119 dholland sblock.fs_sbsize = ffs_fragroundup(&sblock, sizeof(struct fs)); 500 1.68 fvdl if (sblock.fs_sbsize > SBLOCKSIZE) 501 1.68 fvdl sblock.fs_sbsize = SBLOCKSIZE; 502 1.1 cgd sblock.fs_minfree = minfree; 503 1.1 cgd sblock.fs_maxcontig = maxcontig; 504 1.1 cgd sblock.fs_maxbpg = maxbpg; 505 1.1 cgd sblock.fs_optim = opt; 506 1.1 cgd sblock.fs_cgrotor = 0; 507 1.68 fvdl sblock.fs_pendingblocks = 0; 508 1.68 fvdl sblock.fs_pendinginodes = 0; 509 1.1 cgd sblock.fs_cstotal.cs_ndir = 0; 510 1.1 cgd sblock.fs_cstotal.cs_nbfree = 0; 511 1.1 cgd sblock.fs_cstotal.cs_nifree = 0; 512 1.1 cgd sblock.fs_cstotal.cs_nffree = 0; 513 1.1 cgd sblock.fs_fmod = 0; 514 1.68 fvdl sblock.fs_ronly = 0; 515 1.68 fvdl sblock.fs_state = 0; 516 1.21 mycroft sblock.fs_clean = FS_ISCLEAN; 517 1.1 cgd sblock.fs_ronly = 0; 518 1.70 atatat sblock.fs_id[0] = (long)tv.tv_sec; /* XXXfvdl huh? */ 519 1.78 itojun sblock.fs_id[1] = arc4random() & INT32_MAX; 520 1.68 fvdl sblock.fs_fsmnt[0] = '\0'; 521 1.68 fvdl csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); 522 1.68 fvdl sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - 523 1.68 fvdl sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); 524 1.68 fvdl sblock.fs_cstotal.cs_nbfree = 525 1.120 dholland ffs_fragstoblks(&sblock, sblock.fs_dsize) - 526 1.68 fvdl howmany(csfrags, sblock.fs_frag); 527 1.68 fvdl sblock.fs_cstotal.cs_nffree = 528 1.120 dholland ffs_fragnum(&sblock, sblock.fs_size) + 529 1.120 dholland (ffs_fragnum(&sblock, csfrags) > 0 ? 530 1.120 dholland sblock.fs_frag - ffs_fragnum(&sblock, csfrags) : 0); 531 1.113 dholland sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO; 532 1.68 fvdl sblock.fs_cstotal.cs_ndir = 0; 533 1.68 fvdl sblock.fs_dsize -= csfrags; 534 1.70 atatat sblock.fs_time = tv.tv_sec; 535 1.68 fvdl if (Oflag <= 1) { 536 1.70 atatat sblock.fs_old_time = tv.tv_sec; 537 1.68 fvdl sblock.fs_old_dsize = sblock.fs_dsize; 538 1.68 fvdl sblock.fs_old_csaddr = sblock.fs_csaddr; 539 1.68 fvdl sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; 540 1.68 fvdl sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; 541 1.68 fvdl sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; 542 1.68 fvdl sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; 543 1.68 fvdl } 544 1.109 bouyer /* add quota data in superblock */ 545 1.109 bouyer if (quotas) { 546 1.109 bouyer sblock.fs_flags |= FS_DOQUOTA2; 547 1.109 bouyer sblock.fs_quota_magic = Q2_HEAD_MAGIC; 548 1.109 bouyer sblock.fs_quota_flags = quotas; 549 1.109 bouyer } 550 1.1 cgd /* 551 1.1 cgd * Dump out summary information about file system. 552 1.1 cgd */ 553 1.98 dsl if (verbosity > 0) { 554 1.60 simonb #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 555 1.68 fvdl printf("%s: %.1fMB (%lld sectors) block size %d, " 556 1.68 fvdl "fragment size %d\n", 557 1.68 fvdl fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 558 1.117 dholland (long long)FFS_FSBTODB(&sblock, sblock.fs_size), 559 1.68 fvdl sblock.fs_bsize, sblock.fs_fsize); 560 1.68 fvdl printf("\tusing %d cylinder groups of %.2fMB, %d blks, " 561 1.68 fvdl "%d inodes.\n", 562 1.68 fvdl sblock.fs_ncg, 563 1.9 mycroft (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 564 1.68 fvdl sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); 565 1.9 mycroft #undef B2MBFACTOR 566 1.1 cgd } 567 1.68 fvdl 568 1.68 fvdl /* 569 1.68 fvdl * allocate space for superblock, cylinder group map, and 570 1.68 fvdl * two sets of inode blocks. 571 1.68 fvdl */ 572 1.68 fvdl if (sblock.fs_bsize < SBLOCKSIZE) 573 1.68 fvdl iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; 574 1.68 fvdl else 575 1.68 fvdl iobufsize = 4 * sblock.fs_bsize; 576 1.87 dsl iobuf_memsize = iobufsize; 577 1.87 dsl if (!mfs && sblock.fs_magic == FS_UFS1_MAGIC) { 578 1.87 dsl /* A larger buffer so we can write multiple inode blks */ 579 1.87 dsl iobuf_memsize += 14 * sblock.fs_bsize; 580 1.87 dsl } 581 1.87 dsl for (;;) { 582 1.87 dsl iobuf = mmap(0, iobuf_memsize, PROT_READ|PROT_WRITE, 583 1.87 dsl MAP_ANON|MAP_PRIVATE, -1, 0); 584 1.104 jnemeth if (iobuf != MAP_FAILED) 585 1.87 dsl break; 586 1.87 dsl if (iobuf_memsize != iobufsize) { 587 1.87 dsl /* Try again with the smaller size */ 588 1.87 dsl iobuf_memsize = iobufsize; 589 1.87 dsl continue; 590 1.87 dsl } 591 1.68 fvdl printf("Cannot allocate I/O buffer\n"); 592 1.68 fvdl exit(38); 593 1.68 fvdl } 594 1.87 dsl memset(iobuf, 0, iobuf_memsize); 595 1.80 dsl 596 1.80 dsl /* 597 1.80 dsl * We now start writing to the filesystem 598 1.80 dsl */ 599 1.80 dsl 600 1.97 dsl if (!Nflag) { 601 1.97 dsl /* 602 1.97 dsl * Validate the given file system size. 603 1.97 dsl * Verify that its last block can actually be accessed. 604 1.97 dsl * Convert to file system fragment sized units. 605 1.97 dsl */ 606 1.97 dsl if (fssize <= 0) { 607 1.97 dsl printf("preposterous size %lld\n", (long long)fssize); 608 1.108 pooka fserr(13); 609 1.97 dsl } 610 1.97 dsl wtfs(fssize - 1, sectorsize, iobuf); 611 1.80 dsl 612 1.97 dsl /* 613 1.97 dsl * Ensure there is nothing that looks like a filesystem 614 1.137 andvar * superblock anywhere other than where ours will be. 615 1.97 dsl * If fsck finds the wrong one all hell breaks loose! 616 1.97 dsl */ 617 1.97 dsl for (i = 0; ; i++) { 618 1.97 dsl static const int sblocklist[] = SBLOCKSEARCH; 619 1.97 dsl int sblkoff = sblocklist[i]; 620 1.97 dsl int sz; 621 1.97 dsl if (sblkoff == -1) 622 1.97 dsl break; 623 1.97 dsl /* Remove main superblock */ 624 1.97 dsl zap_old_sblock(sblkoff); 625 1.97 dsl /* and all possible locations for the first alternate */ 626 1.97 dsl sblkoff += SBLOCKSIZE; 627 1.97 dsl for (sz = SBLOCKSIZE; sz <= 0x10000; sz <<= 1) 628 1.97 dsl zap_old_sblock(roundup(sblkoff, sz)); 629 1.97 dsl } 630 1.111 tsutsui /* 631 1.111 tsutsui * Also zap possible Ext2fs magic leftover to prevent 632 1.111 tsutsui * kernel vfs_mountroot() and bootloaders from mis-recognizing 633 1.111 tsutsui * this file system as Ext2fs. 634 1.111 tsutsui */ 635 1.111 tsutsui zap_old_sblock(EXT2FS_SBOFF); 636 1.80 dsl 637 1.128 rin #ifndef NO_APPLE_UFS 638 1.97 dsl if (isappleufs) { 639 1.129 jdolecek struct appleufslabel appleufs __aligned(DEV_BSIZE); 640 1.97 dsl ffs_appleufs_set(&appleufs, appleufs_volname, 641 1.97 dsl tv.tv_sec, 0); 642 1.97 dsl wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, 643 1.97 dsl APPLEUFS_LABEL_SIZE, &appleufs); 644 1.107 mlelstv } else if (APPLEUFS_LABEL_SIZE % sectorsize == 0) { 645 1.97 dsl struct appleufslabel appleufs; 646 1.97 dsl /* Look for & zap any existing valid apple ufs labels */ 647 1.97 dsl rdfs(APPLEUFS_LABEL_OFFSET/sectorsize, 648 1.97 dsl APPLEUFS_LABEL_SIZE, &appleufs); 649 1.97 dsl if (ffs_appleufs_validate(fsys, &appleufs, NULL) == 0) { 650 1.97 dsl memset(&appleufs, 0, sizeof(appleufs)); 651 1.97 dsl wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, 652 1.97 dsl APPLEUFS_LABEL_SIZE, &appleufs); 653 1.97 dsl } 654 1.85 dbj } 655 1.128 rin #endif 656 1.80 dsl } 657 1.80 dsl 658 1.36 wrstuden /* 659 1.68 fvdl * Make a copy of the superblock into the buffer that we will be 660 1.68 fvdl * writing out in each cylinder group. 661 1.1 cgd */ 662 1.76 dsl memcpy(iobuf, &sblock, sizeof sblock); 663 1.68 fvdl if (needswap) 664 1.76 dsl ffs_sb_swap(&sblock, (struct fs *)iobuf); 665 1.88 dbj if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) 666 1.88 dbj memset(iobuf + offsetof(struct fs, fs_old_postbl_start), 667 1.88 dbj 0xff, 256); 668 1.68 fvdl 669 1.98 dsl if (verbosity >= 3) 670 1.94 dsl printf("super-block backups (for fsck_ffs -b #) at:\n"); 671 1.98 dsl /* If we are printing more than one line of numbers, line up columns */ 672 1.98 dsl fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, 673 1.117 dholland (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, sblock.fs_ncg-1))); 674 1.98 dsl /* Get terminal width */ 675 1.136 mrg if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 && 676 1.136 mrg winsize.ws_col != 0) 677 1.98 dsl max_cols = winsize.ws_col; 678 1.98 dsl else 679 1.98 dsl max_cols = 80; 680 1.98 dsl if (Nflag && verbosity == 3) 681 1.99 dsl /* Leave space to add " ..." after one row of numbers */ 682 1.98 dsl max_cols -= 4; 683 1.95 dsl #define BASE 0x10000 /* For some fixed-point maths */ 684 1.94 dsl col = 0; 685 1.98 dsl delta = verbosity > 2 ? 0 : max_cols * BASE / sblock.fs_ncg; 686 1.1 cgd for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 687 1.98 dsl fflush(stdout); 688 1.70 atatat initcg(cylno, &tv); 689 1.98 dsl if (verbosity < 2) 690 1.1 cgd continue; 691 1.98 dsl if (delta > 0) { 692 1.98 dsl if (Nflag) 693 1.98 dsl /* No point doing dots for -N */ 694 1.98 dsl break; 695 1.98 dsl /* Print dots scaled to end near RH margin */ 696 1.98 dsl for (col += delta; col > BASE; col -= BASE) 697 1.98 dsl printf("."); 698 1.98 dsl continue; 699 1.98 dsl } 700 1.98 dsl /* Print superblock numbers */ 701 1.110 joerg len = printf("%s%*" PRIu64 ",", col ? " " : "", fld_width, 702 1.117 dholland (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno))); 703 1.98 dsl col += len; 704 1.98 dsl if (col + len < max_cols) 705 1.98 dsl /* Next number fits */ 706 1.98 dsl continue; 707 1.98 dsl /* Next number won't fit, need a newline */ 708 1.98 dsl if (verbosity <= 3) { 709 1.98 dsl /* Print dots for subsequent cylinder groups */ 710 1.98 dsl delta = sblock.fs_ncg - cylno - 1; 711 1.98 dsl if (delta != 0) { 712 1.98 dsl if (Nflag) { 713 1.98 dsl printf(" ..."); 714 1.98 dsl break; 715 1.95 dsl } 716 1.98 dsl delta = max_cols * BASE / delta; 717 1.95 dsl } 718 1.94 dsl } 719 1.98 dsl col = 0; 720 1.98 dsl printf("\n"); 721 1.1 cgd } 722 1.95 dsl #undef BASE 723 1.98 dsl if (col > 0) 724 1.1 cgd printf("\n"); 725 1.86 dsl if (Nflag) 726 1.1 cgd exit(0); 727 1.68 fvdl 728 1.1 cgd /* 729 1.1 cgd * Now construct the initial file system, 730 1.1 cgd */ 731 1.70 atatat if (fsinit(&tv, mfsmode, mfsuid, mfsgid) == 0 && mfs) 732 1.60 simonb errx(1, "Error making filesystem"); 733 1.70 atatat sblock.fs_time = tv.tv_sec; 734 1.68 fvdl if (Oflag <= 1) { 735 1.68 fvdl sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; 736 1.68 fvdl sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; 737 1.68 fvdl sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; 738 1.68 fvdl sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; 739 1.68 fvdl } 740 1.76 dsl /* 741 1.76 dsl * Write out the super-block and zeros until the first cg info 742 1.76 dsl */ 743 1.126 dholland i = cgsblock(&sblock, 0) * sblock.fs_fsize - sblock.fs_sblockloc; 744 1.127 christos if ((size_t)i < sizeof(sblock)) 745 1.127 christos errx(1, "No space for superblock"); 746 1.127 christos memcpy(iobuf, &sblock, sizeof(sblock)); 747 1.127 christos memset(iobuf + sizeof(sblock), 0, i - sizeof(sblock)); 748 1.30 bouyer if (needswap) 749 1.76 dsl ffs_sb_swap(&sblock, (struct fs *)iobuf); 750 1.132 chs if (eaflag) 751 1.132 chs ((struct fs *)iobuf)->fs_magic = FS_UFS2EA_MAGIC; 752 1.88 dbj if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) 753 1.88 dbj memset(iobuf + offsetof(struct fs, fs_old_postbl_start), 754 1.88 dbj 0xff, 256); 755 1.87 dsl wtfs(sblock.fs_sblockloc / sectorsize, i, iobuf); 756 1.34 wrstuden 757 1.73 dsl /* Write out first and last cylinder summary sectors */ 758 1.73 dsl if (needswap) 759 1.73 dsl ffs_csum_swap(fscs_0, fscs_0, sblock.fs_fsize); 760 1.117 dholland wtfs(FFS_FSBTODB(&sblock, sblock.fs_csaddr), sblock.fs_fsize, fscs_0); 761 1.73 dsl 762 1.73 dsl if (fscs_next > fscs_reset) { 763 1.73 dsl if (needswap) 764 1.73 dsl ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); 765 1.73 dsl fs_csaddr++; 766 1.117 dholland wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); 767 1.73 dsl } 768 1.34 wrstuden 769 1.87 dsl /* mfs doesn't need these permanently allocated */ 770 1.87 dsl munmap(iobuf, iobuf_memsize); 771 1.87 dsl munmap(fscs_0, 2 * sblock.fs_fsize); 772 1.1 cgd } 773 1.1 cgd 774 1.1 cgd /* 775 1.1 cgd * Initialize a cylinder group. 776 1.1 cgd */ 777 1.26 christos void 778 1.133 chs initcg(uint32_t cylno, const struct timeval *tv) 779 1.1 cgd { 780 1.68 fvdl daddr_t cbase, dmax; 781 1.133 chs uint32_t i, d, dlower, dupper, blkno, u; 782 1.68 fvdl struct ufs1_dinode *dp1; 783 1.68 fvdl struct ufs2_dinode *dp2; 784 1.68 fvdl int start; 785 1.1 cgd 786 1.1 cgd /* 787 1.1 cgd * Determine block bounds for cylinder group. 788 1.1 cgd * Allow space for super block summary information in first 789 1.1 cgd * cylinder group. 790 1.1 cgd */ 791 1.1 cgd cbase = cgbase(&sblock, cylno); 792 1.1 cgd dmax = cbase + sblock.fs_fpg; 793 1.1 cgd if (dmax > sblock.fs_size) 794 1.1 cgd dmax = sblock.fs_size; 795 1.1 cgd dlower = cgsblock(&sblock, cylno) - cbase; 796 1.1 cgd dupper = cgdmin(&sblock, cylno) - cbase; 797 1.72 dsl if (cylno == 0) { 798 1.1 cgd dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 799 1.72 dsl if (dupper >= cgstart(&sblock, cylno + 1)) { 800 1.72 dsl printf("\rToo many cylinder groups to fit summary " 801 1.72 dsl "information into first cylinder group\n"); 802 1.108 pooka fserr(40); 803 1.72 dsl } 804 1.72 dsl } 805 1.12 mycroft memset(&acg, 0, sblock.fs_cgsize); 806 1.1 cgd acg.cg_magic = CG_MAGIC; 807 1.1 cgd acg.cg_cgx = cylno; 808 1.1 cgd acg.cg_ndblk = dmax - cbase; 809 1.9 mycroft if (sblock.fs_contigsumsize > 0) 810 1.62 mycroft acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift; 811 1.68 fvdl start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 812 1.68 fvdl if (Oflag == 2) { 813 1.75 dsl acg.cg_time = tv->tv_sec; 814 1.75 dsl acg.cg_niblk = sblock.fs_ipg; 815 1.116 dholland acg.cg_initediblk = sblock.fs_ipg < 2 * FFS_INOPB(&sblock) ? 816 1.116 dholland sblock.fs_ipg : 2 * FFS_INOPB(&sblock); 817 1.68 fvdl acg.cg_iusedoff = start; 818 1.68 fvdl } else { 819 1.68 fvdl acg.cg_old_ncyl = sblock.fs_old_cpg; 820 1.88 dbj if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0 && 821 1.88 dbj (cylno == sblock.fs_ncg - 1)) 822 1.88 dbj acg.cg_old_ncyl = 823 1.88 dbj sblock.fs_old_ncyl % sblock.fs_old_cpg; 824 1.75 dsl acg.cg_old_time = tv->tv_sec; 825 1.75 dsl acg.cg_old_niblk = sblock.fs_ipg; 826 1.68 fvdl acg.cg_old_btotoff = start; 827 1.68 fvdl acg.cg_old_boff = acg.cg_old_btotoff + 828 1.68 fvdl sblock.fs_old_cpg * sizeof(int32_t); 829 1.68 fvdl acg.cg_iusedoff = acg.cg_old_boff + 830 1.68 fvdl sblock.fs_old_cpg * sizeof(u_int16_t); 831 1.68 fvdl } 832 1.68 fvdl acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); 833 1.9 mycroft if (sblock.fs_contigsumsize <= 0) { 834 1.9 mycroft acg.cg_nextfreeoff = acg.cg_freeoff + 835 1.68 fvdl howmany(sblock.fs_fpg, CHAR_BIT); 836 1.9 mycroft } else { 837 1.62 mycroft acg.cg_clustersumoff = acg.cg_freeoff + 838 1.68 fvdl howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t); 839 1.65 dbj if (isappleufs) { 840 1.65 dbj /* Apple PR2216969 gives rationale for this change. 841 1.65 dbj * I believe they were mistaken, but we need to 842 1.67 grant * duplicate it for compatibility. -- dbj (at) NetBSD.org 843 1.65 dbj */ 844 1.65 dbj acg.cg_clustersumoff += sizeof(int32_t); 845 1.65 dbj } 846 1.9 mycroft acg.cg_clustersumoff = 847 1.14 cgd roundup(acg.cg_clustersumoff, sizeof(int32_t)); 848 1.9 mycroft acg.cg_clusteroff = acg.cg_clustersumoff + 849 1.14 cgd (sblock.fs_contigsumsize + 1) * sizeof(int32_t); 850 1.62 mycroft acg.cg_nextfreeoff = acg.cg_clusteroff + 851 1.120 dholland howmany(ffs_fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); 852 1.9 mycroft } 853 1.133 chs if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { 854 1.9 mycroft printf("Panic: cylinder group too big\n"); 855 1.108 pooka fserr(37); 856 1.1 cgd } 857 1.1 cgd acg.cg_cs.cs_nifree += sblock.fs_ipg; 858 1.1 cgd if (cylno == 0) 859 1.113 dholland for (u = 0; u < UFS_ROOTINO; u++) { 860 1.105 lukem setbit(cg_inosused(&acg, 0), u); 861 1.1 cgd acg.cg_cs.cs_nifree--; 862 1.1 cgd } 863 1.1 cgd if (cylno > 0) { 864 1.1 cgd /* 865 1.1 cgd * In cylno 0, beginning space is reserved 866 1.1 cgd * for boot and super blocks. 867 1.1 cgd */ 868 1.68 fvdl for (d = 0, blkno = 0; d < dlower;) { 869 1.30 bouyer setblock(&sblock, cg_blksfree(&acg, 0), blkno); 870 1.9 mycroft if (sblock.fs_contigsumsize > 0) 871 1.30 bouyer setbit(cg_clustersfree(&acg, 0), blkno); 872 1.1 cgd acg.cg_cs.cs_nbfree++; 873 1.88 dbj if (Oflag <= 1) { 874 1.88 dbj int cn = old_cbtocylno(&sblock, d); 875 1.88 dbj old_cg_blktot(&acg, 0)[cn]++; 876 1.88 dbj old_cg_blks(&sblock, &acg, 877 1.88 dbj cn, 0)[old_cbtorpos(&sblock, d)]++; 878 1.88 dbj } 879 1.64 mycroft d += sblock.fs_frag; 880 1.64 mycroft blkno++; 881 1.1 cgd } 882 1.1 cgd } 883 1.62 mycroft if ((i = (dupper & (sblock.fs_frag - 1))) != 0) { 884 1.1 cgd acg.cg_frsum[sblock.fs_frag - i]++; 885 1.1 cgd for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 886 1.30 bouyer setbit(cg_blksfree(&acg, 0), dupper); 887 1.1 cgd acg.cg_cs.cs_nffree++; 888 1.1 cgd } 889 1.1 cgd } 890 1.64 mycroft for (d = dupper, blkno = dupper >> sblock.fs_fragshift; 891 1.68 fvdl d + sblock.fs_frag <= acg.cg_ndblk; ) { 892 1.30 bouyer setblock(&sblock, cg_blksfree(&acg, 0), blkno); 893 1.9 mycroft if (sblock.fs_contigsumsize > 0) 894 1.30 bouyer setbit(cg_clustersfree(&acg, 0), blkno); 895 1.1 cgd acg.cg_cs.cs_nbfree++; 896 1.88 dbj if (Oflag <= 1) { 897 1.88 dbj int cn = old_cbtocylno(&sblock, d); 898 1.88 dbj old_cg_blktot(&acg, 0)[cn]++; 899 1.88 dbj old_cg_blks(&sblock, &acg, 900 1.88 dbj cn, 0)[old_cbtorpos(&sblock, d)]++; 901 1.88 dbj } 902 1.1 cgd d += sblock.fs_frag; 903 1.64 mycroft blkno++; 904 1.1 cgd } 905 1.68 fvdl if (d < acg.cg_ndblk) { 906 1.68 fvdl acg.cg_frsum[acg.cg_ndblk - d]++; 907 1.68 fvdl for (; d < acg.cg_ndblk; d++) { 908 1.30 bouyer setbit(cg_blksfree(&acg, 0), d); 909 1.1 cgd acg.cg_cs.cs_nffree++; 910 1.1 cgd } 911 1.1 cgd } 912 1.9 mycroft if (sblock.fs_contigsumsize > 0) { 913 1.30 bouyer int32_t *sump = cg_clustersum(&acg, 0); 914 1.30 bouyer u_char *mapp = cg_clustersfree(&acg, 0); 915 1.9 mycroft int map = *mapp++; 916 1.9 mycroft int bit = 1; 917 1.9 mycroft int run = 0; 918 1.9 mycroft 919 1.9 mycroft for (i = 0; i < acg.cg_nclusterblks; i++) { 920 1.9 mycroft if ((map & bit) != 0) { 921 1.9 mycroft run++; 922 1.9 mycroft } else if (run != 0) { 923 1.9 mycroft if (run > sblock.fs_contigsumsize) 924 1.9 mycroft run = sblock.fs_contigsumsize; 925 1.9 mycroft sump[run]++; 926 1.9 mycroft run = 0; 927 1.9 mycroft } 928 1.68 fvdl if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { 929 1.9 mycroft bit <<= 1; 930 1.9 mycroft } else { 931 1.9 mycroft map = *mapp++; 932 1.9 mycroft bit = 1; 933 1.9 mycroft } 934 1.9 mycroft } 935 1.9 mycroft if (run != 0) { 936 1.9 mycroft if (run > sblock.fs_contigsumsize) 937 1.9 mycroft run = sblock.fs_contigsumsize; 938 1.9 mycroft sump[run]++; 939 1.9 mycroft } 940 1.9 mycroft } 941 1.73 dsl *fscs_next++ = acg.cg_cs; 942 1.73 dsl if (fscs_next == fscs_end) { 943 1.87 dsl /* write block of cylinder group summary info into cyl 0 */ 944 1.73 dsl if (needswap) 945 1.73 dsl ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); 946 1.73 dsl fs_csaddr++; 947 1.117 dholland wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); 948 1.73 dsl fscs_next = fscs_reset; 949 1.73 dsl memset(fscs_next, 0, sblock.fs_fsize); 950 1.73 dsl } 951 1.68 fvdl /* 952 1.68 fvdl * Write out the duplicate super block, the cylinder group map 953 1.68 fvdl * and two blocks worth of inodes in a single write. 954 1.68 fvdl */ 955 1.68 fvdl start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; 956 1.68 fvdl memcpy(&iobuf[start], &acg, sblock.fs_cgsize); 957 1.30 bouyer if (needswap) 958 1.68 fvdl ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock); 959 1.68 fvdl start += sblock.fs_bsize; 960 1.68 fvdl dp1 = (struct ufs1_dinode *)(&iobuf[start]); 961 1.68 fvdl dp2 = (struct ufs2_dinode *)(&iobuf[start]); 962 1.116 dholland for (i = MIN(sblock.fs_ipg, 2) * FFS_INOPB(&sblock); i != 0; i--) { 963 1.68 fvdl if (sblock.fs_magic == FS_UFS1_MAGIC) { 964 1.68 fvdl /* No need to swap, it'll stay random */ 965 1.78 itojun dp1->di_gen = arc4random() & INT32_MAX; 966 1.68 fvdl dp1++; 967 1.68 fvdl } else { 968 1.78 itojun dp2->di_gen = arc4random() & INT32_MAX; 969 1.68 fvdl dp2++; 970 1.68 fvdl } 971 1.68 fvdl } 972 1.117 dholland wtfs(FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); 973 1.68 fvdl /* 974 1.68 fvdl * For the old file system, we have to initialize all the inodes. 975 1.68 fvdl */ 976 1.87 dsl if (sblock.fs_magic != FS_UFS1_MAGIC) 977 1.87 dsl return; 978 1.87 dsl 979 1.87 dsl /* Write 'd' (usually 16 * fs_frag) file-system fragments at once */ 980 1.87 dsl d = (iobuf_memsize - start) / sblock.fs_bsize * sblock.fs_frag; 981 1.116 dholland dupper = sblock.fs_ipg / FFS_INOPF(&sblock); 982 1.87 dsl for (i = 2 * sblock.fs_frag; i < dupper; i += d) { 983 1.87 dsl if (d > dupper - i) 984 1.87 dsl d = dupper - i; 985 1.87 dsl dp1 = (struct ufs1_dinode *)(&iobuf[start]); 986 1.87 dsl do 987 1.87 dsl dp1->di_gen = arc4random() & INT32_MAX; 988 1.87 dsl while ((char *)++dp1 < &iobuf[iobuf_memsize]); 989 1.117 dholland wtfs(FFS_FSBTODB(&sblock, cgimin(&sblock, cylno) + i), 990 1.87 dsl d * sblock.fs_bsize / sblock.fs_frag, &iobuf[start]); 991 1.68 fvdl } 992 1.1 cgd } 993 1.1 cgd 994 1.1 cgd /* 995 1.1 cgd * initialize the file system 996 1.1 cgd */ 997 1.1 cgd 998 1.1 cgd #ifdef LOSTDIR 999 1.60 simonb #define PREDEFDIR 3 1000 1.1 cgd #else 1001 1.60 simonb #define PREDEFDIR 2 1002 1.1 cgd #endif 1003 1.1 cgd 1004 1.1 cgd struct direct root_dir[] = { 1005 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 1006 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 1007 1.9 mycroft #ifdef LOSTDIR 1008 1.9 mycroft { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 1009 1.9 mycroft #endif 1010 1.9 mycroft }; 1011 1.9 mycroft struct odirect { 1012 1.14 cgd u_int32_t d_ino; 1013 1.14 cgd u_int16_t d_reclen; 1014 1.14 cgd u_int16_t d_namlen; 1015 1.91 tron u_char d_name[FFS_MAXNAMLEN + 1]; 1016 1.9 mycroft } oroot_dir[] = { 1017 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), 1, "." }, 1018 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, 1019 1.1 cgd #ifdef LOSTDIR 1020 1.1 cgd { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 1021 1.1 cgd #endif 1022 1.1 cgd }; 1023 1.1 cgd #ifdef LOSTDIR 1024 1.1 cgd struct direct lost_found_dir[] = { 1025 1.9 mycroft { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 1026 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 1027 1.9 mycroft { 0, DIRBLKSIZ, 0, 0, 0 }, 1028 1.9 mycroft }; 1029 1.9 mycroft struct odirect olost_found_dir[] = { 1030 1.1 cgd { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 1031 1.113 dholland { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, 1032 1.1 cgd { 0, DIRBLKSIZ, 0, 0 }, 1033 1.1 cgd }; 1034 1.1 cgd #endif 1035 1.122 martin 1036 1.39 simonb static void copy_dir(struct direct *, struct direct *); 1037 1.1 cgd 1038 1.60 simonb int 1039 1.70 atatat fsinit(const struct timeval *tv, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 1040 1.1 cgd { 1041 1.75 dsl union dinode node; 1042 1.129 jdolecek union Buffer buf __aligned(DEV_BSIZE); 1043 1.109 bouyer int i; 1044 1.109 bouyer int qblocks = 0; 1045 1.109 bouyer int qinos = 0; 1046 1.109 bouyer uint8_t q2h_hash_shift; 1047 1.109 bouyer uint16_t q2h_hash_mask; 1048 1.26 christos #ifdef LOSTDIR 1049 1.65 dbj int dirblksiz = DIRBLKSIZ; 1050 1.65 dbj if (isappleufs) 1051 1.65 dbj dirblksiz = APPLEUFS_DIRBLKSIZ; 1052 1.109 bouyer int nextino = LOSTFOUNDINO+1; 1053 1.109 bouyer #else 1054 1.113 dholland int nextino = UFS_ROOTINO+1; 1055 1.26 christos #endif 1056 1.1 cgd 1057 1.1 cgd /* 1058 1.1 cgd * initialize the node 1059 1.1 cgd */ 1060 1.30 bouyer 1061 1.1 cgd #ifdef LOSTDIR 1062 1.1 cgd /* 1063 1.1 cgd * create the lost+found directory 1064 1.1 cgd */ 1065 1.75 dsl memset(&node, 0, sizeof(node)); 1066 1.68 fvdl if (Oflag == 0) { 1067 1.124 christos (void)makedir(&buf, (struct direct *)olost_found_dir, 2); 1068 1.65 dbj for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) 1069 1.30 bouyer copy_dir((struct direct*)&olost_found_dir[2], 1070 1.30 bouyer (struct direct*)&buf[i]); 1071 1.9 mycroft } else { 1072 1.124 christos (void)makedir(&buf, lost_found_dir, 2); 1073 1.65 dbj for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) 1074 1.30 bouyer copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); 1075 1.9 mycroft } 1076 1.68 fvdl if (sblock.fs_magic == FS_UFS1_MAGIC) { 1077 1.70 atatat node.dp1.di_atime = tv->tv_sec; 1078 1.70 atatat node.dp1.di_atimensec = tv->tv_usec * 1000; 1079 1.70 atatat node.dp1.di_mtime = tv->tv_sec; 1080 1.70 atatat node.dp1.di_mtimensec = tv->tv_usec * 1000; 1081 1.70 atatat node.dp1.di_ctime = tv->tv_sec; 1082 1.70 atatat node.dp1.di_ctimensec = tv->tv_usec * 1000; 1083 1.68 fvdl node.dp1.di_mode = IFDIR | UMASK; 1084 1.68 fvdl node.dp1.di_nlink = 2; 1085 1.68 fvdl node.dp1.di_size = sblock.fs_bsize; 1086 1.68 fvdl node.dp1.di_db[0] = alloc(node.dp1.di_size, node.dp1.di_mode); 1087 1.69 christos if (node.dp1.di_db[0] == 0) 1088 1.69 christos return (0); 1089 1.119 dholland node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, 1090 1.68 fvdl node.dp1.di_size)); 1091 1.109 bouyer qblocks += node.dp1.di_blocks; 1092 1.68 fvdl node.dp1.di_uid = geteuid(); 1093 1.68 fvdl node.dp1.di_gid = getegid(); 1094 1.117 dholland wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), node.dp1.di_size, 1095 1.68 fvdl buf); 1096 1.68 fvdl } else { 1097 1.70 atatat node.dp2.di_atime = tv->tv_sec; 1098 1.70 atatat node.dp2.di_atimensec = tv->tv_usec * 1000; 1099 1.70 atatat node.dp2.di_mtime = tv->tv_sec; 1100 1.70 atatat node.dp2.di_mtimensec = tv->tv_usec * 1000; 1101 1.70 atatat node.dp2.di_ctime = tv->tv_sec; 1102 1.70 atatat node.dp2.di_ctimensec = tv->tv_usec * 1000; 1103 1.70 atatat node.dp2.di_birthtime = tv->tv_sec; 1104 1.70 atatat node.dp2.di_birthnsec = tv->tv_usec * 1000; 1105 1.68 fvdl node.dp2.di_mode = IFDIR | UMASK; 1106 1.68 fvdl node.dp2.di_nlink = 2; 1107 1.68 fvdl node.dp2.di_size = sblock.fs_bsize; 1108 1.68 fvdl node.dp2.di_db[0] = alloc(node.dp2.di_size, node.dp2.di_mode); 1109 1.69 christos if (node.dp2.di_db[0] == 0) 1110 1.69 christos return (0); 1111 1.119 dholland node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, 1112 1.68 fvdl node.dp2.di_size)); 1113 1.109 bouyer qblocks += node.dp2.di_blocks; 1114 1.68 fvdl node.dp2.di_uid = geteuid(); 1115 1.68 fvdl node.dp2.di_gid = getegid(); 1116 1.117 dholland wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), node.dp2.di_size, 1117 1.68 fvdl buf); 1118 1.68 fvdl } 1119 1.109 bouyer qinos++; 1120 1.1 cgd iput(&node, LOSTFOUNDINO); 1121 1.1 cgd #endif 1122 1.1 cgd /* 1123 1.1 cgd * create the root directory 1124 1.1 cgd */ 1125 1.75 dsl memset(&node, 0, sizeof(node)); 1126 1.68 fvdl if (Oflag <= 1) { 1127 1.68 fvdl if (mfs) { 1128 1.68 fvdl node.dp1.di_mode = IFDIR | mfsmode; 1129 1.68 fvdl node.dp1.di_uid = mfsuid; 1130 1.68 fvdl node.dp1.di_gid = mfsgid; 1131 1.68 fvdl } else { 1132 1.68 fvdl node.dp1.di_mode = IFDIR | UMASK; 1133 1.68 fvdl node.dp1.di_uid = geteuid(); 1134 1.68 fvdl node.dp1.di_gid = getegid(); 1135 1.68 fvdl } 1136 1.68 fvdl node.dp1.di_nlink = PREDEFDIR; 1137 1.68 fvdl if (Oflag == 0) 1138 1.124 christos node.dp1.di_size = makedir(&buf, 1139 1.124 christos (struct direct *)oroot_dir, PREDEFDIR); 1140 1.68 fvdl else 1141 1.124 christos node.dp1.di_size = makedir(&buf, root_dir, PREDEFDIR); 1142 1.68 fvdl node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode); 1143 1.68 fvdl if (node.dp1.di_db[0] == 0) 1144 1.68 fvdl return (0); 1145 1.119 dholland node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, 1146 1.68 fvdl node.dp1.di_size)); 1147 1.109 bouyer qblocks += node.dp1.di_blocks; 1148 1.122 martin wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, &buf); 1149 1.60 simonb } else { 1150 1.68 fvdl if (mfs) { 1151 1.68 fvdl node.dp2.di_mode = IFDIR | mfsmode; 1152 1.68 fvdl node.dp2.di_uid = mfsuid; 1153 1.68 fvdl node.dp2.di_gid = mfsgid; 1154 1.68 fvdl } else { 1155 1.68 fvdl node.dp2.di_mode = IFDIR | UMASK; 1156 1.68 fvdl node.dp2.di_uid = geteuid(); 1157 1.68 fvdl node.dp2.di_gid = getegid(); 1158 1.68 fvdl } 1159 1.70 atatat node.dp2.di_atime = tv->tv_sec; 1160 1.70 atatat node.dp2.di_atimensec = tv->tv_usec * 1000; 1161 1.70 atatat node.dp2.di_mtime = tv->tv_sec; 1162 1.70 atatat node.dp2.di_mtimensec = tv->tv_usec * 1000; 1163 1.70 atatat node.dp2.di_ctime = tv->tv_sec; 1164 1.70 atatat node.dp2.di_ctimensec = tv->tv_usec * 1000; 1165 1.70 atatat node.dp2.di_birthtime = tv->tv_sec; 1166 1.70 atatat node.dp2.di_birthnsec = tv->tv_usec * 1000; 1167 1.68 fvdl node.dp2.di_nlink = PREDEFDIR; 1168 1.124 christos node.dp2.di_size = makedir(&buf, root_dir, PREDEFDIR); 1169 1.68 fvdl node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode); 1170 1.68 fvdl if (node.dp2.di_db[0] == 0) 1171 1.68 fvdl return (0); 1172 1.119 dholland node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, 1173 1.68 fvdl node.dp2.di_size)); 1174 1.109 bouyer qblocks += node.dp2.di_blocks; 1175 1.122 martin wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, &buf); 1176 1.68 fvdl } 1177 1.109 bouyer qinos++; 1178 1.113 dholland iput(&node, UFS_ROOTINO); 1179 1.109 bouyer /* 1180 1.109 bouyer * compute the size of the hash table 1181 1.109 bouyer * We know the smallest block size is 4k, so we can use 2k 1182 1.109 bouyer * for the hash table; as an entry is 8 bytes we can store 1183 1.109 bouyer * 256 entries. So let start q2h_hash_shift at 8 1184 1.109 bouyer */ 1185 1.109 bouyer for (q2h_hash_shift = 8; 1186 1.109 bouyer q2h_hash_shift < 15; 1187 1.109 bouyer q2h_hash_shift++) { 1188 1.109 bouyer if ((sizeof(uint64_t) << (q2h_hash_shift + 1)) + 1189 1.109 bouyer sizeof(struct quota2_header) > (u_int)sblock.fs_bsize) 1190 1.109 bouyer break; 1191 1.109 bouyer } 1192 1.109 bouyer q2h_hash_mask = (1 << q2h_hash_shift) - 1; 1193 1.109 bouyer for (i = 0; i < MAXQUOTAS; i++) { 1194 1.109 bouyer struct quota2_header *q2h; 1195 1.109 bouyer struct quota2_entry *q2e; 1196 1.109 bouyer uint64_t offset; 1197 1.109 bouyer uid_t uid = (i == USRQUOTA ? geteuid() : getegid()); 1198 1.109 bouyer 1199 1.109 bouyer if ((quotas & FS_Q2_DO_TYPE(i)) == 0) 1200 1.109 bouyer continue; 1201 1.122 martin quota2_create_blk0(sblock.fs_bsize, &buf, q2h_hash_shift, 1202 1.109 bouyer i, needswap); 1203 1.109 bouyer /* grab an entry from header for root dir */ 1204 1.122 martin q2h = &buf.q2h; 1205 1.109 bouyer offset = ufs_rw64(q2h->q2h_free, needswap); 1206 1.122 martin q2e = (void *)((char *)&buf + offset); 1207 1.109 bouyer q2h->q2h_free = q2e->q2e_next; 1208 1.109 bouyer memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e)); 1209 1.109 bouyer q2e->q2e_uid = ufs_rw32(uid, needswap); 1210 1.109 bouyer q2e->q2e_val[QL_BLOCK].q2v_cur = ufs_rw64(qblocks, needswap); 1211 1.109 bouyer q2e->q2e_val[QL_FILE].q2v_cur = ufs_rw64(qinos, needswap); 1212 1.109 bouyer /* add to the hash entry */ 1213 1.109 bouyer q2e->q2e_next = q2h->q2h_entries[uid & q2h_hash_mask]; 1214 1.109 bouyer q2h->q2h_entries[uid & q2h_hash_mask] = 1215 1.109 bouyer ufs_rw64(offset, needswap); 1216 1.109 bouyer 1217 1.109 bouyer memset(&node, 0, sizeof(node)); 1218 1.109 bouyer if (sblock.fs_magic == FS_UFS1_MAGIC) { 1219 1.109 bouyer node.dp1.di_atime = tv->tv_sec; 1220 1.109 bouyer node.dp1.di_atimensec = tv->tv_usec * 1000; 1221 1.109 bouyer node.dp1.di_mtime = tv->tv_sec; 1222 1.109 bouyer node.dp1.di_mtimensec = tv->tv_usec * 1000; 1223 1.109 bouyer node.dp1.di_ctime = tv->tv_sec; 1224 1.109 bouyer node.dp1.di_ctimensec = tv->tv_usec * 1000; 1225 1.109 bouyer node.dp1.di_mode = IFREG; 1226 1.109 bouyer node.dp1.di_nlink = 1; 1227 1.109 bouyer node.dp1.di_size = sblock.fs_bsize; 1228 1.109 bouyer node.dp1.di_db[0] = 1229 1.109 bouyer alloc(node.dp1.di_size, node.dp1.di_mode); 1230 1.109 bouyer if (node.dp1.di_db[0] == 0) 1231 1.109 bouyer return (0); 1232 1.119 dholland node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, 1233 1.109 bouyer node.dp1.di_size)); 1234 1.109 bouyer node.dp1.di_uid = geteuid(); 1235 1.109 bouyer node.dp1.di_gid = getegid(); 1236 1.117 dholland wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), 1237 1.122 martin node.dp1.di_size, &buf); 1238 1.109 bouyer } else { 1239 1.109 bouyer node.dp2.di_atime = tv->tv_sec; 1240 1.109 bouyer node.dp2.di_atimensec = tv->tv_usec * 1000; 1241 1.109 bouyer node.dp2.di_mtime = tv->tv_sec; 1242 1.109 bouyer node.dp2.di_mtimensec = tv->tv_usec * 1000; 1243 1.109 bouyer node.dp2.di_ctime = tv->tv_sec; 1244 1.109 bouyer node.dp2.di_ctimensec = tv->tv_usec * 1000; 1245 1.109 bouyer node.dp2.di_birthtime = tv->tv_sec; 1246 1.109 bouyer node.dp2.di_birthnsec = tv->tv_usec * 1000; 1247 1.109 bouyer node.dp2.di_mode = IFREG; 1248 1.109 bouyer node.dp2.di_nlink = 1; 1249 1.109 bouyer node.dp2.di_size = sblock.fs_bsize; 1250 1.109 bouyer node.dp2.di_db[0] = 1251 1.109 bouyer alloc(node.dp2.di_size, node.dp2.di_mode); 1252 1.109 bouyer if (node.dp2.di_db[0] == 0) 1253 1.109 bouyer return (0); 1254 1.119 dholland node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, 1255 1.109 bouyer node.dp2.di_size)); 1256 1.109 bouyer node.dp2.di_uid = geteuid(); 1257 1.109 bouyer node.dp2.di_gid = getegid(); 1258 1.117 dholland wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), 1259 1.122 martin node.dp2.di_size, &buf); 1260 1.109 bouyer } 1261 1.109 bouyer iput(&node, nextino); 1262 1.109 bouyer sblock.fs_quotafile[i] = nextino; 1263 1.109 bouyer nextino++; 1264 1.109 bouyer } 1265 1.60 simonb return (1); 1266 1.1 cgd } 1267 1.1 cgd 1268 1.1 cgd /* 1269 1.1 cgd * construct a set of directory entries in "buf". 1270 1.1 cgd * return size of directory. 1271 1.1 cgd */ 1272 1.26 christos int 1273 1.124 christos makedir(union Buffer *buf, struct direct *protodir, int entries) 1274 1.1 cgd { 1275 1.1 cgd char *cp; 1276 1.1 cgd int i, spcleft; 1277 1.115 dholland int dirblksiz = UFS_DIRBLKSIZ; 1278 1.65 dbj if (isappleufs) 1279 1.65 dbj dirblksiz = APPLEUFS_DIRBLKSIZ; 1280 1.1 cgd 1281 1.124 christos memset(buf, 0, dirblksiz); 1282 1.65 dbj spcleft = dirblksiz; 1283 1.124 christos for (cp = buf->data, i = 0; i < entries - 1; i++) { 1284 1.115 dholland protodir[i].d_reclen = UFS_DIRSIZ(Oflag == 0, &protodir[i], 0); 1285 1.30 bouyer copy_dir(&protodir[i], (struct direct*)cp); 1286 1.1 cgd cp += protodir[i].d_reclen; 1287 1.1 cgd spcleft -= protodir[i].d_reclen; 1288 1.1 cgd } 1289 1.1 cgd protodir[i].d_reclen = spcleft; 1290 1.30 bouyer copy_dir(&protodir[i], (struct direct*)cp); 1291 1.65 dbj return (dirblksiz); 1292 1.1 cgd } 1293 1.1 cgd 1294 1.1 cgd /* 1295 1.1 cgd * allocate a block or frag 1296 1.1 cgd */ 1297 1.1 cgd daddr_t 1298 1.39 simonb alloc(int size, int mode) 1299 1.1 cgd { 1300 1.1 cgd int i, frag; 1301 1.9 mycroft daddr_t d, blkno; 1302 1.1 cgd 1303 1.117 dholland rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1304 1.30 bouyer /* fs -> host byte order */ 1305 1.30 bouyer if (needswap) 1306 1.68 fvdl ffs_cg_swap(&acg, &acg, &sblock); 1307 1.1 cgd if (acg.cg_magic != CG_MAGIC) { 1308 1.1 cgd printf("cg 0: bad magic number\n"); 1309 1.1 cgd return (0); 1310 1.1 cgd } 1311 1.1 cgd if (acg.cg_cs.cs_nbfree == 0) { 1312 1.1 cgd printf("first cylinder group ran out of space\n"); 1313 1.1 cgd return (0); 1314 1.1 cgd } 1315 1.1 cgd for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 1316 1.62 mycroft if (isblock(&sblock, cg_blksfree(&acg, 0), 1317 1.62 mycroft d >> sblock.fs_fragshift)) 1318 1.1 cgd goto goth; 1319 1.1 cgd printf("internal error: can't find block in cyl 0\n"); 1320 1.1 cgd return (0); 1321 1.1 cgd goth: 1322 1.120 dholland blkno = ffs_fragstoblks(&sblock, d); 1323 1.30 bouyer clrblock(&sblock, cg_blksfree(&acg, 0), blkno); 1324 1.10 cgd if (sblock.fs_contigsumsize > 0) 1325 1.30 bouyer clrbit(cg_clustersfree(&acg, 0), blkno); 1326 1.1 cgd acg.cg_cs.cs_nbfree--; 1327 1.1 cgd sblock.fs_cstotal.cs_nbfree--; 1328 1.73 dsl fscs_0->cs_nbfree--; 1329 1.1 cgd if (mode & IFDIR) { 1330 1.1 cgd acg.cg_cs.cs_ndir++; 1331 1.1 cgd sblock.fs_cstotal.cs_ndir++; 1332 1.73 dsl fscs_0->cs_ndir++; 1333 1.1 cgd } 1334 1.88 dbj if (Oflag <= 1) { 1335 1.88 dbj int cn = old_cbtocylno(&sblock, d); 1336 1.88 dbj old_cg_blktot(&acg, 0)[cn]--; 1337 1.88 dbj old_cg_blks(&sblock, &acg, 1338 1.88 dbj cn, 0)[old_cbtorpos(&sblock, d)]--; 1339 1.88 dbj } 1340 1.1 cgd if (size != sblock.fs_bsize) { 1341 1.1 cgd frag = howmany(size, sblock.fs_fsize); 1342 1.73 dsl fscs_0->cs_nffree += sblock.fs_frag - frag; 1343 1.1 cgd sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 1344 1.1 cgd acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 1345 1.1 cgd acg.cg_frsum[sblock.fs_frag - frag]++; 1346 1.1 cgd for (i = frag; i < sblock.fs_frag; i++) 1347 1.30 bouyer setbit(cg_blksfree(&acg, 0), d + i); 1348 1.1 cgd } 1349 1.30 bouyer /* host -> fs byte order */ 1350 1.30 bouyer if (needswap) 1351 1.68 fvdl ffs_cg_swap(&acg, &acg, &sblock); 1352 1.117 dholland wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1353 1.1 cgd return (d); 1354 1.1 cgd } 1355 1.1 cgd 1356 1.1 cgd /* 1357 1.1 cgd * Allocate an inode on the disk 1358 1.1 cgd */ 1359 1.26 christos static void 1360 1.68 fvdl iput(union dinode *ip, ino_t ino) 1361 1.1 cgd { 1362 1.1 cgd daddr_t d; 1363 1.112 wiz int i; 1364 1.68 fvdl struct ufs1_dinode *dp1; 1365 1.68 fvdl struct ufs2_dinode *dp2; 1366 1.1 cgd 1367 1.117 dholland rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1368 1.30 bouyer /* fs -> host byte order */ 1369 1.30 bouyer if (needswap) 1370 1.68 fvdl ffs_cg_swap(&acg, &acg, &sblock); 1371 1.1 cgd if (acg.cg_magic != CG_MAGIC) { 1372 1.1 cgd printf("cg 0: bad magic number\n"); 1373 1.108 pooka fserr(31); 1374 1.1 cgd } 1375 1.1 cgd acg.cg_cs.cs_nifree--; 1376 1.30 bouyer setbit(cg_inosused(&acg, 0), ino); 1377 1.30 bouyer /* host -> fs byte order */ 1378 1.30 bouyer if (needswap) 1379 1.68 fvdl ffs_cg_swap(&acg, &acg, &sblock); 1380 1.117 dholland wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1381 1.1 cgd sblock.fs_cstotal.cs_nifree--; 1382 1.73 dsl fscs_0->cs_nifree--; 1383 1.105 lukem if (ino >= (ino_t)(sblock.fs_ipg * sblock.fs_ncg)) { 1384 1.90 christos printf("fsinit: inode value out of range (%llu).\n", 1385 1.90 christos (unsigned long long)ino); 1386 1.108 pooka fserr(32); 1387 1.1 cgd } 1388 1.117 dholland d = FFS_FSBTODB(&sblock, ino_to_fsba(&sblock, ino)); 1389 1.68 fvdl rdfs(d, sblock.fs_bsize, (char *)iobuf); 1390 1.68 fvdl if (sblock.fs_magic == FS_UFS1_MAGIC) { 1391 1.68 fvdl dp1 = (struct ufs1_dinode *)iobuf; 1392 1.75 dsl dp1 += ino_to_fsbo(&sblock, ino); 1393 1.68 fvdl if (needswap) { 1394 1.75 dsl ffs_dinode1_swap(&ip->dp1, dp1); 1395 1.68 fvdl /* ffs_dinode1_swap() doesn't swap blocks addrs */ 1396 1.121 justin for (i=0; i<UFS_NDADDR; i++) 1397 1.75 dsl dp1->di_db[i] = bswap32(ip->dp1.di_db[i]); 1398 1.121 justin for (i=0; i<UFS_NIADDR; i++) 1399 1.121 justin dp1->di_ib[i] = bswap32(ip->dp1.di_ib[i]); 1400 1.68 fvdl } else 1401 1.75 dsl *dp1 = ip->dp1; 1402 1.79 itojun dp1->di_gen = arc4random() & INT32_MAX; 1403 1.68 fvdl } else { 1404 1.68 fvdl dp2 = (struct ufs2_dinode *)iobuf; 1405 1.75 dsl dp2 += ino_to_fsbo(&sblock, ino); 1406 1.68 fvdl if (needswap) { 1407 1.75 dsl ffs_dinode2_swap(&ip->dp2, dp2); 1408 1.121 justin for (i=0; i<UFS_NDADDR; i++) 1409 1.89 dbj dp2->di_db[i] = bswap64(ip->dp2.di_db[i]); 1410 1.121 justin for (i=0; i<UFS_NIADDR; i++) 1411 1.121 justin dp2->di_ib[i] = bswap64(ip->dp2.di_ib[i]); 1412 1.68 fvdl } else 1413 1.75 dsl *dp2 = ip->dp2; 1414 1.79 itojun dp2->di_gen = arc4random() & INT32_MAX; 1415 1.68 fvdl } 1416 1.68 fvdl wtfs(d, sblock.fs_bsize, iobuf); 1417 1.1 cgd } 1418 1.1 cgd 1419 1.1 cgd /* 1420 1.1 cgd * read a block from the file system 1421 1.1 cgd */ 1422 1.26 christos void 1423 1.39 simonb rdfs(daddr_t bno, int size, void *bf) 1424 1.1 cgd { 1425 1.1 cgd int n; 1426 1.18 cgd off_t offset; 1427 1.1 cgd 1428 1.61 lukem #ifdef MFS 1429 1.1 cgd if (mfs) { 1430 1.86 dsl if (Nflag) 1431 1.86 dsl memset(bf, 0, size); 1432 1.86 dsl else 1433 1.86 dsl memmove(bf, membase + bno * sectorsize, size); 1434 1.1 cgd return; 1435 1.1 cgd } 1436 1.61 lukem #endif 1437 1.18 cgd offset = bno; 1438 1.72 dsl n = pread(fsi, bf, size, offset * sectorsize); 1439 1.9 mycroft if (n != size) { 1440 1.66 fvdl printf("rdfs: read error for sector %lld: %s\n", 1441 1.66 fvdl (long long)bno, strerror(errno)); 1442 1.1 cgd exit(34); 1443 1.1 cgd } 1444 1.1 cgd } 1445 1.1 cgd 1446 1.1 cgd /* 1447 1.1 cgd * write a block to the file system 1448 1.1 cgd */ 1449 1.26 christos void 1450 1.39 simonb wtfs(daddr_t bno, int size, void *bf) 1451 1.1 cgd { 1452 1.1 cgd int n; 1453 1.18 cgd off_t offset; 1454 1.1 cgd 1455 1.86 dsl if (Nflag) 1456 1.86 dsl return; 1457 1.61 lukem #ifdef MFS 1458 1.1 cgd if (mfs) { 1459 1.27 lukem memmove(membase + bno * sectorsize, bf, size); 1460 1.1 cgd return; 1461 1.1 cgd } 1462 1.61 lukem #endif 1463 1.18 cgd offset = bno; 1464 1.72 dsl n = pwrite(fso, bf, size, offset * sectorsize); 1465 1.9 mycroft if (n != size) { 1466 1.66 fvdl printf("wtfs: write error for sector %lld: %s\n", 1467 1.66 fvdl (long long)bno, strerror(errno)); 1468 1.1 cgd exit(36); 1469 1.1 cgd } 1470 1.1 cgd } 1471 1.1 cgd 1472 1.1 cgd /* 1473 1.1 cgd * check if a block is available 1474 1.1 cgd */ 1475 1.26 christos int 1476 1.39 simonb isblock(struct fs *fs, unsigned char *cp, int h) 1477 1.1 cgd { 1478 1.1 cgd unsigned char mask; 1479 1.1 cgd 1480 1.62 mycroft switch (fs->fs_fragshift) { 1481 1.62 mycroft case 3: 1482 1.1 cgd return (cp[h] == 0xff); 1483 1.62 mycroft case 2: 1484 1.1 cgd mask = 0x0f << ((h & 0x1) << 2); 1485 1.1 cgd return ((cp[h >> 1] & mask) == mask); 1486 1.62 mycroft case 1: 1487 1.1 cgd mask = 0x03 << ((h & 0x3) << 1); 1488 1.1 cgd return ((cp[h >> 2] & mask) == mask); 1489 1.62 mycroft case 0: 1490 1.1 cgd mask = 0x01 << (h & 0x7); 1491 1.1 cgd return ((cp[h >> 3] & mask) == mask); 1492 1.1 cgd default: 1493 1.1 cgd #ifdef STANDALONE 1494 1.62 mycroft printf("isblock bad fs_fragshift %d\n", fs->fs_fragshift); 1495 1.1 cgd #else 1496 1.62 mycroft fprintf(stderr, "isblock bad fs_fragshift %d\n", 1497 1.62 mycroft fs->fs_fragshift); 1498 1.1 cgd #endif 1499 1.1 cgd return (0); 1500 1.1 cgd } 1501 1.1 cgd } 1502 1.1 cgd 1503 1.1 cgd /* 1504 1.1 cgd * take a block out of the map 1505 1.1 cgd */ 1506 1.26 christos void 1507 1.39 simonb clrblock(struct fs *fs, unsigned char *cp, int h) 1508 1.1 cgd { 1509 1.62 mycroft switch ((fs)->fs_fragshift) { 1510 1.62 mycroft case 3: 1511 1.1 cgd cp[h] = 0; 1512 1.1 cgd return; 1513 1.62 mycroft case 2: 1514 1.1 cgd cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1515 1.1 cgd return; 1516 1.62 mycroft case 1: 1517 1.1 cgd cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1518 1.1 cgd return; 1519 1.62 mycroft case 0: 1520 1.1 cgd cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1521 1.1 cgd return; 1522 1.1 cgd default: 1523 1.1 cgd #ifdef STANDALONE 1524 1.62 mycroft printf("clrblock bad fs_fragshift %d\n", fs->fs_fragshift); 1525 1.1 cgd #else 1526 1.62 mycroft fprintf(stderr, "clrblock bad fs_fragshift %d\n", 1527 1.62 mycroft fs->fs_fragshift); 1528 1.1 cgd #endif 1529 1.1 cgd return; 1530 1.1 cgd } 1531 1.1 cgd } 1532 1.1 cgd 1533 1.1 cgd /* 1534 1.1 cgd * put a block into the map 1535 1.1 cgd */ 1536 1.26 christos void 1537 1.39 simonb setblock(struct fs *fs, unsigned char *cp, int h) 1538 1.1 cgd { 1539 1.62 mycroft switch (fs->fs_fragshift) { 1540 1.62 mycroft case 3: 1541 1.1 cgd cp[h] = 0xff; 1542 1.1 cgd return; 1543 1.62 mycroft case 2: 1544 1.1 cgd cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1545 1.1 cgd return; 1546 1.62 mycroft case 1: 1547 1.1 cgd cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1548 1.1 cgd return; 1549 1.62 mycroft case 0: 1550 1.1 cgd cp[h >> 3] |= (0x01 << (h & 0x7)); 1551 1.1 cgd return; 1552 1.1 cgd default: 1553 1.1 cgd #ifdef STANDALONE 1554 1.62 mycroft printf("setblock bad fs_frag %d\n", fs->fs_fragshift); 1555 1.1 cgd #else 1556 1.62 mycroft fprintf(stderr, "setblock bad fs_fragshift %d\n", 1557 1.62 mycroft fs->fs_fragshift); 1558 1.1 cgd #endif 1559 1.1 cgd return; 1560 1.30 bouyer } 1561 1.30 bouyer } 1562 1.30 bouyer 1563 1.30 bouyer /* copy a direntry to a buffer, in fs byte order */ 1564 1.30 bouyer static void 1565 1.39 simonb copy_dir(struct direct *dir, struct direct *dbuf) 1566 1.30 bouyer { 1567 1.115 dholland memcpy(dbuf, dir, UFS_DIRSIZ(Oflag == 0, dir, 0)); 1568 1.30 bouyer if (needswap) { 1569 1.30 bouyer dbuf->d_ino = bswap32(dir->d_ino); 1570 1.30 bouyer dbuf->d_reclen = bswap16(dir->d_reclen); 1571 1.68 fvdl if (Oflag == 0) 1572 1.30 bouyer ((struct odirect*)dbuf)->d_namlen = 1573 1.30 bouyer bswap16(((struct odirect*)dir)->d_namlen); 1574 1.1 cgd } 1575 1.36 wrstuden } 1576 1.36 wrstuden 1577 1.68 fvdl static int 1578 1.68 fvdl ilog2(int val) 1579 1.68 fvdl { 1580 1.68 fvdl u_int n; 1581 1.68 fvdl 1582 1.68 fvdl for (n = 0; n < sizeof(n) * CHAR_BIT; n++) 1583 1.68 fvdl if (1 << n == val) 1584 1.68 fvdl return (n); 1585 1.125 christos errx(1, "ilog2: %d is not a power of 2", val); 1586 1.80 dsl } 1587 1.80 dsl 1588 1.80 dsl static void 1589 1.80 dsl zap_old_sblock(int sblkoff) 1590 1.80 dsl { 1591 1.80 dsl static int cg0_data; 1592 1.129 jdolecek uint32_t oldfs[SBLOCKSIZE / 4] __aligned(DEV_BSIZE); 1593 1.80 dsl static const struct fsm { 1594 1.80 dsl uint32_t offset; 1595 1.80 dsl uint32_t magic; 1596 1.80 dsl uint32_t mask; 1597 1.80 dsl } fs_magics[] = { 1598 1.80 dsl {offsetof(struct fs, fs_magic)/4, FS_UFS1_MAGIC, ~0u}, 1599 1.80 dsl {offsetof(struct fs, fs_magic)/4, FS_UFS2_MAGIC, ~0u}, 1600 1.80 dsl {0, 0x70162, ~0u}, /* LFS_MAGIC */ 1601 1.80 dsl {14, 0xef53, 0xffff}, /* EXT2FS (little) */ 1602 1.80 dsl {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ 1603 1.102 christos {.offset = ~0u}, 1604 1.80 dsl }; 1605 1.80 dsl const struct fsm *fsm; 1606 1.81 dsl 1607 1.81 dsl if (Nflag) 1608 1.84 lukem return; 1609 1.84 lukem 1610 1.84 lukem if (sblkoff == 0) /* Why did UFS2 add support for this? sigh. */ 1611 1.81 dsl return; 1612 1.80 dsl 1613 1.80 dsl if (cg0_data == 0) 1614 1.80 dsl /* For FFSv1 this could include all the inodes. */ 1615 1.80 dsl cg0_data = cgsblock(&sblock, 0) * sblock.fs_fsize + iobufsize; 1616 1.80 dsl 1617 1.80 dsl /* Ignore anything that is beyond our filesystem */ 1618 1.80 dsl if ((sblkoff + SBLOCKSIZE)/sectorsize >= fssize) 1619 1.80 dsl return; 1620 1.80 dsl /* Zero anything inside our filesystem... */ 1621 1.80 dsl if (sblkoff >= sblock.fs_sblockloc) { 1622 1.80 dsl /* ...unless we will write that area anyway */ 1623 1.80 dsl if (sblkoff >= cg0_data) 1624 1.82 enami wtfs(sblkoff / sectorsize, 1625 1.82 enami roundup(sizeof sblock, sectorsize), iobuf); 1626 1.80 dsl return; 1627 1.80 dsl } 1628 1.80 dsl 1629 1.80 dsl /* The sector might contain boot code, so we must validate it */ 1630 1.80 dsl rdfs(sblkoff/sectorsize, sizeof oldfs, &oldfs); 1631 1.80 dsl for (fsm = fs_magics; ; fsm++) { 1632 1.80 dsl uint32_t v; 1633 1.80 dsl if (fsm->mask == 0) 1634 1.80 dsl return; 1635 1.80 dsl v = oldfs[fsm->offset]; 1636 1.80 dsl if ((v & fsm->mask) == fsm->magic || 1637 1.80 dsl (bswap32(v) & fsm->mask) == fsm->magic) 1638 1.80 dsl break; 1639 1.80 dsl } 1640 1.80 dsl 1641 1.80 dsl /* Just zap the magic number */ 1642 1.80 dsl oldfs[fsm->offset] = 0; 1643 1.80 dsl wtfs(sblkoff/sectorsize, sizeof oldfs, &oldfs); 1644 1.68 fvdl } 1645 1.68 fvdl 1646 1.60 simonb 1647 1.61 lukem #ifdef MFS 1648 1.60 simonb /* 1649 1.60 simonb * Internal version of malloc that trims the requested size if not enough 1650 1.60 simonb * memory is available. 1651 1.60 simonb */ 1652 1.60 simonb static void * 1653 1.60 simonb mkfs_malloc(size_t size) 1654 1.60 simonb { 1655 1.60 simonb u_long pgsz; 1656 1.114 mlelstv caddr_t *memory, *extra; 1657 1.114 mlelstv size_t exsize = 128 * 1024; 1658 1.60 simonb 1659 1.60 simonb if (size == 0) 1660 1.60 simonb return (NULL); 1661 1.60 simonb 1662 1.60 simonb pgsz = getpagesize() - 1; 1663 1.60 simonb size = (size + pgsz) &~ pgsz; 1664 1.114 mlelstv 1665 1.114 mlelstv /* try to map requested size */ 1666 1.104 jnemeth memory = mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1667 1.104 jnemeth -1, 0); 1668 1.114 mlelstv if (memory == MAP_FAILED) 1669 1.114 mlelstv return NULL; 1670 1.114 mlelstv 1671 1.114 mlelstv /* try to map something extra */ 1672 1.114 mlelstv extra = mmap(0, exsize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1673 1.114 mlelstv -1, 0); 1674 1.130 riastrad if (extra != MAP_FAILED) 1675 1.130 riastrad munmap(extra, exsize); 1676 1.114 mlelstv 1677 1.114 mlelstv /* if extra memory couldn't be mapped, reduce original request accordingly */ 1678 1.114 mlelstv if (extra == MAP_FAILED) { 1679 1.114 mlelstv munmap(memory, size); 1680 1.114 mlelstv size -= exsize; 1681 1.114 mlelstv memory = mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1682 1.114 mlelstv -1, 0); 1683 1.114 mlelstv if (memory == MAP_FAILED) 1684 1.114 mlelstv return NULL; 1685 1.114 mlelstv } 1686 1.114 mlelstv 1687 1.114 mlelstv return memory; 1688 1.1 cgd } 1689 1.61 lukem #endif /* MFS */ 1690