1 /* $NetBSD: lfs_accessors.h,v 1.22 2015/09/01 06:16:59 dholland Exp $ */ 2 3 /* from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp */ 4 /* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */ 5 /* from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp */ 6 7 /*- 8 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to The NetBSD Foundation 12 * by Konrad E. Schroder <perseant@hhhh.org>. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /*- 36 * Copyright (c) 1991, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 * @(#)lfs.h 8.9 (Berkeley) 5/8/95 64 */ 65 /* 66 * Copyright (c) 2002 Networks Associates Technology, Inc. 67 * All rights reserved. 68 * 69 * This software was developed for the FreeBSD Project by Marshall 70 * Kirk McKusick and Network Associates Laboratories, the Security 71 * Research Division of Network Associates, Inc. under DARPA/SPAWAR 72 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 73 * research program 74 * 75 * Copyright (c) 1982, 1989, 1993 76 * The Regents of the University of California. All rights reserved. 77 * (c) UNIX System Laboratories, Inc. 78 * All or some portions of this file are derived from material licensed 79 * to the University of California by American Telephone and Telegraph 80 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81 * the permission of UNIX System Laboratories, Inc. 82 * 83 * Redistribution and use in source and binary forms, with or without 84 * modification, are permitted provided that the following conditions 85 * are met: 86 * 1. Redistributions of source code must retain the above copyright 87 * notice, this list of conditions and the following disclaimer. 88 * 2. Redistributions in binary form must reproduce the above copyright 89 * notice, this list of conditions and the following disclaimer in the 90 * documentation and/or other materials provided with the distribution. 91 * 3. Neither the name of the University nor the names of its contributors 92 * may be used to endorse or promote products derived from this software 93 * without specific prior written permission. 94 * 95 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 98 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 105 * SUCH DAMAGE. 106 * 107 * @(#)dinode.h 8.9 (Berkeley) 3/29/95 108 */ 109 /* 110 * Copyright (c) 1982, 1986, 1989, 1993 111 * The Regents of the University of California. All rights reserved. 112 * (c) UNIX System Laboratories, Inc. 113 * All or some portions of this file are derived from material licensed 114 * to the University of California by American Telephone and Telegraph 115 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 116 * the permission of UNIX System Laboratories, Inc. 117 * 118 * Redistribution and use in source and binary forms, with or without 119 * modification, are permitted provided that the following conditions 120 * are met: 121 * 1. Redistributions of source code must retain the above copyright 122 * notice, this list of conditions and the following disclaimer. 123 * 2. Redistributions in binary form must reproduce the above copyright 124 * notice, this list of conditions and the following disclaimer in the 125 * documentation and/or other materials provided with the distribution. 126 * 3. Neither the name of the University nor the names of its contributors 127 * may be used to endorse or promote products derived from this software 128 * without specific prior written permission. 129 * 130 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 131 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 132 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 133 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 134 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 135 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 136 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 137 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 138 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 139 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 140 * SUCH DAMAGE. 141 * 142 * @(#)dir.h 8.5 (Berkeley) 4/27/95 143 */ 144 145 #ifndef _UFS_LFS_LFS_ACCESSORS_H_ 146 #define _UFS_LFS_LFS_ACCESSORS_H_ 147 148 #if defined(_KERNEL_OPT) 149 #include "opt_lfs.h" 150 #endif 151 152 #include <sys/bswap.h> 153 154 #if !defined(_KERNEL) && !defined(_STANDALONE) 155 #include <assert.h> 156 #define KASSERT assert 157 #endif 158 159 /* 160 * STRUCT_LFS is used by the libsa code to get accessors that work 161 * with struct salfs instead of struct lfs, and by the cleaner to 162 * get accessors that work with struct clfs. 163 */ 164 165 #ifndef STRUCT_LFS 166 #define STRUCT_LFS struct lfs 167 #endif 168 169 /* 170 * byte order 171 */ 172 173 /* 174 * For now at least, the bootblocks shall not be endian-independent. 175 * We can see later if it fits in the size budget. Also disable the 176 * byteswapping if LFS_EI is off. 177 * 178 * Caution: these functions "know" that bswap16/32/64 are unsigned, 179 * and if that changes will likely break silently. 180 */ 181 182 #if defined(_STANDALONE) || (defined(_KERNEL) && !defined(LFS_EI)) 183 #define LFS_SWAP_int16_t(fs, val) (val) 184 #define LFS_SWAP_int32_t(fs, val) (val) 185 #define LFS_SWAP_int64_t(fs, val) (val) 186 #define LFS_SWAP_uint16_t(fs, val) (val) 187 #define LFS_SWAP_uint32_t(fs, val) (val) 188 #define LFS_SWAP_uint64_t(fs, val) (val) 189 #else 190 #define LFS_SWAP_int16_t(fs, val) \ 191 ((fs)->lfs_dobyteswap ? (int16_t)bswap16(val) : (val)) 192 #define LFS_SWAP_int32_t(fs, val) \ 193 ((fs)->lfs_dobyteswap ? (int32_t)bswap32(val) : (val)) 194 #define LFS_SWAP_int64_t(fs, val) \ 195 ((fs)->lfs_dobyteswap ? (int64_t)bswap64(val) : (val)) 196 #define LFS_SWAP_uint16_t(fs, val) \ 197 ((fs)->lfs_dobyteswap ? bswap16(val) : (val)) 198 #define LFS_SWAP_uint32_t(fs, val) \ 199 ((fs)->lfs_dobyteswap ? bswap32(val) : (val)) 200 #define LFS_SWAP_uint64_t(fs, val) \ 201 ((fs)->lfs_dobyteswap ? bswap64(val) : (val)) 202 #endif 203 204 /* 205 * For handling directories we will need to know if the volume is 206 * little-endian. 207 */ 208 #if BYTE_ORDER == LITTLE_ENDIAN 209 #define LFS_LITTLE_ENDIAN_ONDISK(fs) (!(fs)->lfs_dobyteswap) 210 #else 211 #define LFS_LITTLE_ENDIAN_ONDISK(fs) ((fs)->lfs_dobyteswap) 212 #endif 213 214 215 /* 216 * directories 217 */ 218 219 /* 220 * The LFS_DIRSIZ macro gives the minimum record length which will hold 221 * the directory entry. This requires the amount of space in struct lfs_direct 222 * without the d_name field, plus enough space for the name with a terminating 223 * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 224 */ 225 #define LFS_DIRECTSIZ(namlen) \ 226 ((sizeof(struct lfs_direct) - (LFS_MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3)) 227 228 #if (BYTE_ORDER == LITTLE_ENDIAN) 229 #define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ 230 (((oldfmt) && !(needswap)) ? \ 231 LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) 232 #else 233 #define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ 234 (((oldfmt) && (needswap)) ? \ 235 LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) 236 #endif 237 238 #define LFS_DIRSIZ(fs, dp) LFS_DIRECTSIZ(lfs_dir_getnamlen(fs, dp)) 239 240 /* Constants for the first argument of LFS_OLDDIRSIZ */ 241 #define LFS_OLDDIRFMT 1 242 #define LFS_NEWDIRFMT 0 243 244 static __unused inline uint8_t 245 lfs_dir_gettype(const STRUCT_LFS *fs, const struct lfs_direct *dp) 246 { 247 if (fs->lfs_hasolddirfmt) { 248 return LFS_DT_UNKNOWN; 249 } 250 return dp->d_type; 251 } 252 253 static __unused inline uint8_t 254 lfs_dir_getnamlen(const STRUCT_LFS *fs, const struct lfs_direct *dp) 255 { 256 if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 257 /* low-order byte of old 16-bit namlen field */ 258 return dp->d_type; 259 } 260 return dp->d_namlen; 261 } 262 263 static __unused inline void 264 lfs_dir_settype(const STRUCT_LFS *fs, struct lfs_direct *dp, uint8_t type) 265 { 266 if (fs->lfs_hasolddirfmt) { 267 /* do nothing */ 268 return; 269 } 270 dp->d_type = type; 271 } 272 273 static __unused inline void 274 lfs_dir_setnamlen(const STRUCT_LFS *fs, struct lfs_direct *dp, uint8_t namlen) 275 { 276 if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 277 /* low-order byte of old 16-bit namlen field */ 278 dp->d_type = namlen; 279 } 280 dp->d_namlen = namlen; 281 } 282 283 /* 284 * These are called "dirt" because they ought to be cleaned up. 285 */ 286 287 static __unused inline uint8_t 288 lfs_dirt_getdottype(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) 289 { 290 if (fs->lfs_hasolddirfmt) { 291 return LFS_DT_UNKNOWN; 292 } 293 return dp->dot_type; 294 } 295 296 static __unused inline uint8_t 297 lfs_dirt_getdotnamlen(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) 298 { 299 if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 300 /* low-order byte of old 16-bit namlen field */ 301 return dp->dot_type; 302 } 303 return dp->dot_namlen; 304 } 305 306 static __unused inline uint8_t 307 lfs_dirt_getdotdottype(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) 308 { 309 if (fs->lfs_hasolddirfmt) { 310 return LFS_DT_UNKNOWN; 311 } 312 return dp->dotdot_type; 313 } 314 315 static __unused inline uint8_t 316 lfs_dirt_getdotdotnamlen(const STRUCT_LFS *fs, const struct lfs_dirtemplate *dp) 317 { 318 if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 319 /* low-order byte of old 16-bit namlen field */ 320 return dp->dotdot_type; 321 } 322 return dp->dotdot_namlen; 323 } 324 325 static __unused inline void 326 lfs_dirt_settypes(const STRUCT_LFS *fs, struct lfs_dirtemplate *dtp, 327 unsigned dt1, unsigned dt2) 328 { 329 if (fs->lfs_hasolddirfmt) { 330 /* do nothing */ 331 return; 332 } 333 dtp->dot_type = dt1; 334 dtp->dotdot_type = dt2; 335 } 336 337 static __unused inline void 338 lfs_dirt_setnamlens(const STRUCT_LFS *fs, struct lfs_dirtemplate *dtp, 339 unsigned len1, unsigned len2) 340 { 341 if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 342 /* low-order bytes of old 16-bit namlen field */ 343 dtp->dot_type = len1; 344 dtp->dotdot_type = len2; 345 /* clear the high-order bytes */ 346 dtp->dot_namlen = 0; 347 dtp->dotdot_namlen = 0; 348 return; 349 } 350 dtp->dot_namlen = len1; 351 dtp->dotdot_namlen = len2; 352 } 353 354 355 /* 356 * dinodes 357 */ 358 359 /* 360 * Maximum length of a symlink that can be stored within the inode. 361 */ 362 #define LFS32_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t)) 363 #define LFS64_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t)) 364 365 #define LFS_MAXSYMLINKLEN(fs) \ 366 ((fs)->lfs_is64 ? LFS64_MAXSYMLINKLEN : LFS32_MAXSYMLINKLEN) 367 368 #define DINOSIZE(fs) ((fs)->lfs_is64 ? sizeof(struct lfs64_dinode) : sizeof(struct lfs32_dinode)) 369 370 #define DINO_IN_BLOCK(fs, base, ix) \ 371 ((union lfs_dinode *)((char *)(base) + DINOSIZE(fs) * (ix))) 372 373 static __unused inline void 374 lfs_copy_dinode(STRUCT_LFS *fs, 375 union lfs_dinode *dst, const union lfs_dinode *src) 376 { 377 /* 378 * We can do structure assignment of the structs, but not of 379 * the whole union, as the union is the size of the (larger) 380 * 64-bit struct and on a 32-bit fs the upper half of it might 381 * be off the end of a buffer or otherwise invalid. 382 */ 383 if (fs->lfs_is64) { 384 dst->u_64 = src->u_64; 385 } else { 386 dst->u_32 = src->u_32; 387 } 388 } 389 390 #define LFS_DEF_DINO_ACCESSOR(type, type32, field) \ 391 static __unused inline type \ 392 lfs_dino_get##field(STRUCT_LFS *fs, union lfs_dinode *dip) \ 393 { \ 394 if (fs->lfs_is64) { \ 395 return LFS_SWAP_##type(fs, dip->u_64.di_##field); \ 396 } else { \ 397 return LFS_SWAP_##type32(fs, dip->u_32.di_##field); \ 398 } \ 399 } \ 400 static __unused inline void \ 401 lfs_dino_set##field(STRUCT_LFS *fs, union lfs_dinode *dip, type val) \ 402 { \ 403 if (fs->lfs_is64) { \ 404 type *p = &dip->u_64.di_##field; \ 405 (void)p; \ 406 dip->u_64.di_##field = LFS_SWAP_##type(fs, val); \ 407 } else { \ 408 type32 *p = &dip->u_32.di_##field; \ 409 (void)p; \ 410 dip->u_32.di_##field = LFS_SWAP_##type32(fs, val); \ 411 } \ 412 } \ 413 414 LFS_DEF_DINO_ACCESSOR(uint16_t, uint16_t, mode); 415 LFS_DEF_DINO_ACCESSOR(int16_t, int16_t, nlink); 416 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, inumber); 417 LFS_DEF_DINO_ACCESSOR(uint64_t, uint64_t, size); 418 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, atime); 419 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, atimensec); 420 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, mtime); 421 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, mtimensec); 422 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, ctime); 423 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, ctimensec); 424 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, flags); 425 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, blocks); 426 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, gen); 427 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, uid); 428 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, gid); 429 430 /* XXX this should be done differently (it's a fake field) */ 431 LFS_DEF_DINO_ACCESSOR(uint64_t, int32_t, rdev); 432 433 static __unused inline daddr_t 434 lfs_dino_getdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) 435 { 436 KASSERT(ix < ULFS_NDADDR); 437 if (fs->lfs_is64) { 438 return dip->u_64.di_db[ix]; 439 } else { 440 return dip->u_32.di_db[ix]; 441 } 442 } 443 444 static __unused inline daddr_t 445 lfs_dino_getib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) 446 { 447 KASSERT(ix < ULFS_NIADDR); 448 if (fs->lfs_is64) { 449 return dip->u_64.di_ib[ix]; 450 } else { 451 return dip->u_32.di_ib[ix]; 452 } 453 } 454 455 static __unused inline void 456 lfs_dino_setdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val) 457 { 458 KASSERT(ix < ULFS_NDADDR); 459 if (fs->lfs_is64) { 460 dip->u_64.di_db[ix] = val; 461 } else { 462 dip->u_32.di_db[ix] = val; 463 } 464 } 465 466 static __unused inline void 467 lfs_dino_setib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val) 468 { 469 KASSERT(ix < ULFS_NIADDR); 470 if (fs->lfs_is64) { 471 dip->u_64.di_ib[ix] = val; 472 } else { 473 dip->u_32.di_ib[ix] = val; 474 } 475 } 476 477 /* birthtime is present only in the 64-bit inode */ 478 static __unused inline void 479 lfs_dino_setbirthtime(STRUCT_LFS *fs, union lfs_dinode *dip, 480 const struct timespec *ts) 481 { 482 if (fs->lfs_is64) { 483 dip->u_64.di_birthtime = ts->tv_sec; 484 dip->u_64.di_birthnsec = ts->tv_nsec; 485 } else { 486 /* drop it on the floor */ 487 } 488 } 489 490 /* 491 * indirect blocks 492 */ 493 494 static __unused inline daddr_t 495 lfs_iblock_get(STRUCT_LFS *fs, void *block, unsigned ix) 496 { 497 if (fs->lfs_is64) { 498 // XXX re-enable these asserts after reorging this file 499 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t)); 500 return (daddr_t)(((int64_t *)block)[ix]); 501 } else { 502 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t)); 503 /* must sign-extend or UNWRITTEN gets trashed */ 504 return (daddr_t)(int64_t)(((int32_t *)block)[ix]); 505 } 506 } 507 508 static __unused inline void 509 lfs_iblock_set(STRUCT_LFS *fs, void *block, unsigned ix, daddr_t val) 510 { 511 if (fs->lfs_is64) { 512 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t)); 513 ((int64_t *)block)[ix] = val; 514 } else { 515 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t)); 516 ((int32_t *)block)[ix] = val; 517 } 518 } 519 520 /* 521 * "struct buf" associated definitions 522 */ 523 524 # define LFS_LOCK_BUF(bp) do { \ 525 if (((bp)->b_flags & B_LOCKED) == 0 && bp->b_iodone == NULL) { \ 526 mutex_enter(&lfs_lock); \ 527 ++locked_queue_count; \ 528 locked_queue_bytes += bp->b_bufsize; \ 529 mutex_exit(&lfs_lock); \ 530 } \ 531 (bp)->b_flags |= B_LOCKED; \ 532 } while (0) 533 534 # define LFS_UNLOCK_BUF(bp) do { \ 535 if (((bp)->b_flags & B_LOCKED) != 0 && bp->b_iodone == NULL) { \ 536 mutex_enter(&lfs_lock); \ 537 --locked_queue_count; \ 538 locked_queue_bytes -= bp->b_bufsize; \ 539 if (locked_queue_count < LFS_WAIT_BUFS && \ 540 locked_queue_bytes < LFS_WAIT_BYTES) \ 541 cv_broadcast(&locked_queue_cv); \ 542 mutex_exit(&lfs_lock); \ 543 } \ 544 (bp)->b_flags &= ~B_LOCKED; \ 545 } while (0) 546 547 /* 548 * "struct inode" associated definitions 549 */ 550 551 #define LFS_SET_UINO(ip, flags) do { \ 552 if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED)) \ 553 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 554 if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING)) \ 555 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 556 if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED)) \ 557 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 558 (ip)->i_flag |= (flags); \ 559 } while (0) 560 561 #define LFS_CLR_UINO(ip, flags) do { \ 562 if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED)) \ 563 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 564 if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING)) \ 565 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 566 if (((flags) & IN_MODIFIED) && ((ip)->i_flag & IN_MODIFIED)) \ 567 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 568 (ip)->i_flag &= ~(flags); \ 569 if (lfs_sb_getuinodes((ip)->i_lfs) < 0) { \ 570 panic("lfs_uinodes < 0"); \ 571 } \ 572 } while (0) 573 574 #define LFS_ITIMES(ip, acc, mod, cre) \ 575 while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \ 576 lfs_itimes(ip, acc, mod, cre) 577 578 /* 579 * On-disk and in-memory checkpoint segment usage structure. 580 */ 581 582 #define SEGUPB(fs) (lfs_sb_getsepb(fs)) 583 #define SEGTABSIZE_SU(fs) \ 584 ((lfs_sb_getnseg(fs) + SEGUPB(fs) - 1) / lfs_sb_getsepb(fs)) 585 586 #ifdef _KERNEL 587 # define SHARE_IFLOCK(F) \ 588 do { \ 589 rw_enter(&(F)->lfs_iflock, RW_READER); \ 590 } while(0) 591 # define UNSHARE_IFLOCK(F) \ 592 do { \ 593 rw_exit(&(F)->lfs_iflock); \ 594 } while(0) 595 #else /* ! _KERNEL */ 596 # define SHARE_IFLOCK(F) 597 # define UNSHARE_IFLOCK(F) 598 #endif /* ! _KERNEL */ 599 600 /* Read in the block with a specific segment usage entry from the ifile. */ 601 #define LFS_SEGENTRY(SP, F, IN, BP) do { \ 602 int _e; \ 603 SHARE_IFLOCK(F); \ 604 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 605 if ((_e = bread((F)->lfs_ivnode, \ 606 ((IN) / lfs_sb_getsepb(F)) + lfs_sb_getcleansz(F), \ 607 lfs_sb_getbsize(F), 0, &(BP))) != 0) \ 608 panic("lfs: ifile read: %d", _e); \ 609 if (lfs_sb_getversion(F) == 1) \ 610 (SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data + \ 611 ((IN) & (lfs_sb_getsepb(F) - 1))); \ 612 else \ 613 (SP) = (SEGUSE *)(BP)->b_data + ((IN) % lfs_sb_getsepb(F)); \ 614 UNSHARE_IFLOCK(F); \ 615 } while (0) 616 617 #define LFS_WRITESEGENTRY(SP, F, IN, BP) do { \ 618 if ((SP)->su_nbytes == 0) \ 619 (SP)->su_flags |= SEGUSE_EMPTY; \ 620 else \ 621 (SP)->su_flags &= ~SEGUSE_EMPTY; \ 622 (F)->lfs_suflags[(F)->lfs_activesb][(IN)] = (SP)->su_flags; \ 623 LFS_BWRITE_LOG(BP); \ 624 } while (0) 625 626 /* 627 * FINFO (file info) entries. 628 */ 629 630 /* Size of an on-disk block pointer, e.g. in an indirect block. */ 631 /* XXX: move to a more suitable location in this file */ 632 #define LFS_BLKPTRSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t)) 633 634 /* Size of an on-disk inode number. */ 635 /* XXX: move to a more suitable location in this file */ 636 #define LFS_INUMSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t)) 637 638 /* size of a FINFO, without the block pointers */ 639 #define FINFOSIZE(fs) ((fs)->lfs_is64 ? sizeof(FINFO64) : sizeof(FINFO32)) 640 641 /* Full size of the provided FINFO record, including its block pointers. */ 642 #define FINFO_FULLSIZE(fs, fip) \ 643 (FINFOSIZE(fs) + lfs_fi_getnblocks(fs, fip) * LFS_BLKPTRSIZE(fs)) 644 645 #define NEXT_FINFO(fs, fip) \ 646 ((FINFO *)((char *)(fip) + FINFO_FULLSIZE(fs, fip))) 647 648 #define LFS_DEF_FI_ACCESSOR(type, type32, field) \ 649 static __unused inline type \ 650 lfs_fi_get##field(STRUCT_LFS *fs, FINFO *fip) \ 651 { \ 652 if (fs->lfs_is64) { \ 653 return fip->u_64.fi_##field; \ 654 } else { \ 655 return fip->u_32.fi_##field; \ 656 } \ 657 } \ 658 static __unused inline void \ 659 lfs_fi_set##field(STRUCT_LFS *fs, FINFO *fip, type val) \ 660 { \ 661 if (fs->lfs_is64) { \ 662 type *p = &fip->u_64.fi_##field; \ 663 (void)p; \ 664 fip->u_64.fi_##field = val; \ 665 } else { \ 666 type32 *p = &fip->u_32.fi_##field; \ 667 (void)p; \ 668 fip->u_32.fi_##field = val; \ 669 } \ 670 } \ 671 672 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, nblocks); 673 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, version); 674 LFS_DEF_FI_ACCESSOR(uint64_t, uint32_t, ino); 675 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, lastlength); 676 677 static __unused inline daddr_t 678 lfs_fi_getblock(STRUCT_LFS *fs, FINFO *fip, unsigned index) 679 { 680 void *firstblock; 681 682 firstblock = (char *)fip + FINFOSIZE(fs); 683 KASSERT(index < lfs_fi_getnblocks(fs, fip)); 684 if (fs->lfs_is64) { 685 return ((int64_t *)firstblock)[index]; 686 } else { 687 return ((int32_t *)firstblock)[index]; 688 } 689 } 690 691 static __unused inline void 692 lfs_fi_setblock(STRUCT_LFS *fs, FINFO *fip, unsigned index, daddr_t blk) 693 { 694 void *firstblock; 695 696 firstblock = (char *)fip + FINFOSIZE(fs); 697 KASSERT(index < lfs_fi_getnblocks(fs, fip)); 698 if (fs->lfs_is64) { 699 ((int64_t *)firstblock)[index] = blk; 700 } else { 701 ((int32_t *)firstblock)[index] = blk; 702 } 703 } 704 705 /* 706 * Index file inode entries. 707 */ 708 709 /* 710 * LFSv1 compatibility code is not allowed to touch if_atime, since it 711 * may not be mapped! 712 */ 713 /* Read in the block with a specific inode from the ifile. */ 714 #define LFS_IENTRY(IP, F, IN, BP) do { \ 715 int _e; \ 716 SHARE_IFLOCK(F); \ 717 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 718 if ((_e = bread((F)->lfs_ivnode, \ 719 (IN) / lfs_sb_getifpb(F) + lfs_sb_getcleansz(F) + lfs_sb_getsegtabsz(F), \ 720 lfs_sb_getbsize(F), 0, &(BP))) != 0) \ 721 panic("lfs: ifile ino %d read %d", (int)(IN), _e); \ 722 if ((F)->lfs_is64) { \ 723 (IP) = (IFILE *)((IFILE64 *)(BP)->b_data + \ 724 (IN) % lfs_sb_getifpb(F)); \ 725 } else if (lfs_sb_getversion(F) > 1) { \ 726 (IP) = (IFILE *)((IFILE32 *)(BP)->b_data + \ 727 (IN) % lfs_sb_getifpb(F)); \ 728 } else { \ 729 (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + \ 730 (IN) % lfs_sb_getifpb(F)); \ 731 } \ 732 UNSHARE_IFLOCK(F); \ 733 } while (0) 734 #define LFS_IENTRY_NEXT(IP, F) do { \ 735 if ((F)->lfs_is64) { \ 736 (IP) = (IFILE *)((IFILE64 *)(IP) + 1); \ 737 } else if (lfs_sb_getversion(F) > 1) { \ 738 (IP) = (IFILE *)((IFILE32 *)(IP) + 1); \ 739 } else { \ 740 (IP) = (IFILE *)((IFILE_V1 *)(IP) + 1); \ 741 } \ 742 } while (0) 743 744 #define LFS_DEF_IF_ACCESSOR(type, type32, field) \ 745 static __unused inline type \ 746 lfs_if_get##field(STRUCT_LFS *fs, IFILE *ifp) \ 747 { \ 748 if (fs->lfs_is64) { \ 749 return ifp->u_64.if_##field; \ 750 } else { \ 751 return ifp->u_32.if_##field; \ 752 } \ 753 } \ 754 static __unused inline void \ 755 lfs_if_set##field(STRUCT_LFS *fs, IFILE *ifp, type val) \ 756 { \ 757 if (fs->lfs_is64) { \ 758 type *p = &ifp->u_64.if_##field; \ 759 (void)p; \ 760 ifp->u_64.if_##field = val; \ 761 } else { \ 762 type32 *p = &ifp->u_32.if_##field; \ 763 (void)p; \ 764 ifp->u_32.if_##field = val; \ 765 } \ 766 } \ 767 768 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, version); 769 LFS_DEF_IF_ACCESSOR(int64_t, int32_t, daddr); 770 LFS_DEF_IF_ACCESSOR(u_int64_t, u_int32_t, nextfree); 771 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, atime_sec); 772 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, atime_nsec); 773 774 /* 775 * Cleaner information structure. This resides in the ifile and is used 776 * to pass information from the kernel to the cleaner. 777 */ 778 779 #define CLEANSIZE_SU(fs) \ 780 ((((fs)->lfs_is64 ? sizeof(CLEANERINFO64) : sizeof(CLEANERINFO32)) + \ 781 lfs_sb_getbsize(fs) - 1) >> lfs_sb_getbshift(fs)) 782 783 #define LFS_DEF_CI_ACCESSOR(type, type32, field) \ 784 static __unused inline type \ 785 lfs_ci_get##field(STRUCT_LFS *fs, CLEANERINFO *cip) \ 786 { \ 787 if (fs->lfs_is64) { \ 788 return cip->u_64.field; \ 789 } else { \ 790 return cip->u_32.field; \ 791 } \ 792 } \ 793 static __unused inline void \ 794 lfs_ci_set##field(STRUCT_LFS *fs, CLEANERINFO *cip, type val) \ 795 { \ 796 if (fs->lfs_is64) { \ 797 type *p = &cip->u_64.field; \ 798 (void)p; \ 799 cip->u_64.field = val; \ 800 } else { \ 801 type32 *p = &cip->u_32.field; \ 802 (void)p; \ 803 cip->u_32.field = val; \ 804 } \ 805 } \ 806 807 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, clean); 808 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, dirty); 809 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, bfree); 810 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, avail); 811 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_head); 812 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_tail); 813 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, flags); 814 815 static __unused inline void 816 lfs_ci_shiftcleantodirty(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num) 817 { 818 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) - num); 819 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) + num); 820 } 821 822 static __unused inline void 823 lfs_ci_shiftdirtytoclean(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num) 824 { 825 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) - num); 826 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) + num); 827 } 828 829 /* Read in the block with the cleaner info from the ifile. */ 830 #define LFS_CLEANERINFO(CP, F, BP) do { \ 831 SHARE_IFLOCK(F); \ 832 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 833 if (bread((F)->lfs_ivnode, \ 834 (daddr_t)0, lfs_sb_getbsize(F), 0, &(BP))) \ 835 panic("lfs: ifile read"); \ 836 (CP) = (CLEANERINFO *)(BP)->b_data; \ 837 UNSHARE_IFLOCK(F); \ 838 } while (0) 839 840 /* 841 * Synchronize the Ifile cleaner info with current avail and bfree. 842 */ 843 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do { \ 844 mutex_enter(&lfs_lock); \ 845 if ((w) || lfs_ci_getbfree(fs, cip) != lfs_sb_getbfree(fs) || \ 846 lfs_ci_getavail(fs, cip) != lfs_sb_getavail(fs) - fs->lfs_ravail - \ 847 fs->lfs_favail) { \ 848 lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); \ 849 lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) - fs->lfs_ravail - \ 850 fs->lfs_favail); \ 851 if (((bp)->b_flags & B_GATHERED) == 0) { \ 852 fs->lfs_flags |= LFS_IFDIRTY; \ 853 } \ 854 mutex_exit(&lfs_lock); \ 855 (void) LFS_BWRITE_LOG(bp); /* Ifile */ \ 856 } else { \ 857 mutex_exit(&lfs_lock); \ 858 brelse(bp, 0); \ 859 } \ 860 } while (0) 861 862 /* 863 * Get the head of the inode free list. 864 * Always called with the segment lock held. 865 */ 866 #define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do { \ 867 if (lfs_sb_getversion(FS) > 1) { \ 868 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 869 lfs_sb_setfreehd(FS, lfs_ci_getfree_head(FS, CIP)); \ 870 brelse(BP, 0); \ 871 } \ 872 *(FREEP) = lfs_sb_getfreehd(FS); \ 873 } while (0) 874 875 #define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do { \ 876 lfs_sb_setfreehd(FS, VAL); \ 877 if (lfs_sb_getversion(FS) > 1) { \ 878 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 879 lfs_ci_setfree_head(FS, CIP, VAL); \ 880 LFS_BWRITE_LOG(BP); \ 881 mutex_enter(&lfs_lock); \ 882 (FS)->lfs_flags |= LFS_IFDIRTY; \ 883 mutex_exit(&lfs_lock); \ 884 } \ 885 } while (0) 886 887 #define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do { \ 888 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 889 *(FREEP) = lfs_ci_getfree_tail(FS, CIP); \ 890 brelse(BP, 0); \ 891 } while (0) 892 893 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \ 894 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 895 lfs_ci_setfree_tail(FS, CIP, VAL); \ 896 LFS_BWRITE_LOG(BP); \ 897 mutex_enter(&lfs_lock); \ 898 (FS)->lfs_flags |= LFS_IFDIRTY; \ 899 mutex_exit(&lfs_lock); \ 900 } while (0) 901 902 /* 903 * On-disk segment summary information 904 */ 905 906 #define SEGSUM_SIZE(fs) \ 907 (fs->lfs_is64 ? sizeof(SEGSUM64) : \ 908 lfs_sb_getversion(fs) > 1 ? sizeof(SEGSUM32) : sizeof(SEGSUM_V1)) 909 910 /* 911 * The SEGSUM structure is followed by FINFO structures. Get the pointer 912 * to the first FINFO. 913 * 914 * XXX this can't be a macro yet; this file needs to be resorted. 915 */ 916 #if 0 917 static __unused inline FINFO * 918 segsum_finfobase(STRUCT_LFS *fs, SEGSUM *ssp) 919 { 920 return (FINFO *)((char *)ssp + SEGSUM_SIZE(fs)); 921 } 922 #else 923 #define SEGSUM_FINFOBASE(fs, ssp) \ 924 ((FINFO *)((char *)(ssp) + SEGSUM_SIZE(fs))); 925 #endif 926 927 #define LFS_DEF_SS_ACCESSOR(type, type32, field) \ 928 static __unused inline type \ 929 lfs_ss_get##field(STRUCT_LFS *fs, SEGSUM *ssp) \ 930 { \ 931 if (fs->lfs_is64) { \ 932 return ssp->u_64.ss_##field; \ 933 } else { \ 934 return ssp->u_32.ss_##field; \ 935 } \ 936 } \ 937 static __unused inline void \ 938 lfs_ss_set##field(STRUCT_LFS *fs, SEGSUM *ssp, type val) \ 939 { \ 940 if (fs->lfs_is64) { \ 941 type *p = &ssp->u_64.ss_##field; \ 942 (void)p; \ 943 ssp->u_64.ss_##field = val; \ 944 } else { \ 945 type32 *p = &ssp->u_32.ss_##field; \ 946 (void)p; \ 947 ssp->u_32.ss_##field = val; \ 948 } \ 949 } \ 950 951 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, sumsum); 952 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, datasum); 953 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, magic); 954 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, ident); 955 LFS_DEF_SS_ACCESSOR(int64_t, int32_t, next); 956 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, nfinfo); 957 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, ninos); 958 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, flags); 959 LFS_DEF_SS_ACCESSOR(uint64_t, uint32_t, reclino); 960 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, serial); 961 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, create); 962 963 static __unused inline size_t 964 lfs_ss_getsumstart(STRUCT_LFS *fs) 965 { 966 /* These are actually all the same. */ 967 if (fs->lfs_is64) { 968 return offsetof(SEGSUM64, ss_datasum); 969 } else /* if (lfs_sb_getversion(fs) > 1) */ { 970 return offsetof(SEGSUM32, ss_datasum); 971 } /* else { 972 return offsetof(SEGSUM_V1, ss_datasum); 973 } */ 974 /* 975 * XXX ^^^ until this file is resorted lfs_sb_getversion isn't 976 * defined yet. 977 */ 978 } 979 980 static __unused inline uint32_t 981 lfs_ss_getocreate(STRUCT_LFS *fs, SEGSUM *ssp) 982 { 983 KASSERT(fs->lfs_is64 == 0); 984 /* XXX need to resort this file before we can do this */ 985 //KASSERT(lfs_sb_getversion(fs) == 1); 986 987 return ssp->u_v1.ss_create; 988 } 989 990 static __unused inline void 991 lfs_ss_setocreate(STRUCT_LFS *fs, SEGSUM *ssp, uint32_t val) 992 { 993 KASSERT(fs->lfs_is64 == 0); 994 /* XXX need to resort this file before we can do this */ 995 //KASSERT(lfs_sb_getversion(fs) == 1); 996 997 ssp->u_v1.ss_create = val; 998 } 999 1000 1001 /* 1002 * Super block. 1003 */ 1004 1005 /* 1006 * Generate accessors for the on-disk superblock fields with cpp. 1007 */ 1008 1009 #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \ 1010 static __unused inline type \ 1011 lfs_sb_get##field(STRUCT_LFS *fs) \ 1012 { \ 1013 if (fs->lfs_is64) { \ 1014 return fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1015 } else { \ 1016 return fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1017 } \ 1018 } \ 1019 static __unused inline void \ 1020 lfs_sb_set##field(STRUCT_LFS *fs, type val) \ 1021 { \ 1022 if (fs->lfs_is64) { \ 1023 fs->lfs_dlfs_u.u_64.dlfs_##field = val; \ 1024 } else { \ 1025 fs->lfs_dlfs_u.u_32.dlfs_##field = val; \ 1026 } \ 1027 } \ 1028 static __unused inline void \ 1029 lfs_sb_add##field(STRUCT_LFS *fs, type val) \ 1030 { \ 1031 if (fs->lfs_is64) { \ 1032 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1033 *p64 += val; \ 1034 } else { \ 1035 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1036 *p32 += val; \ 1037 } \ 1038 } \ 1039 static __unused inline void \ 1040 lfs_sb_sub##field(STRUCT_LFS *fs, type val) \ 1041 { \ 1042 if (fs->lfs_is64) { \ 1043 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1044 *p64 -= val; \ 1045 } else { \ 1046 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1047 *p32 -= val; \ 1048 } \ 1049 } 1050 1051 #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f) 1052 1053 #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \ 1054 static __unused inline type \ 1055 lfs_sb_get##field(STRUCT_LFS *fs) \ 1056 { \ 1057 if (fs->lfs_is64) { \ 1058 return val64; \ 1059 } else { \ 1060 return fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1061 } \ 1062 } 1063 1064 #define lfs_magic lfs_dlfs.dlfs_magic 1065 LFS_DEF_SB_ACCESSOR(u_int32_t, version); 1066 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, size); 1067 LFS_DEF_SB_ACCESSOR(u_int32_t, ssize); 1068 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, dsize); 1069 LFS_DEF_SB_ACCESSOR(u_int32_t, bsize); 1070 LFS_DEF_SB_ACCESSOR(u_int32_t, fsize); 1071 LFS_DEF_SB_ACCESSOR(u_int32_t, frag); 1072 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, freehd); 1073 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree); 1074 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, nfiles); 1075 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail); 1076 LFS_DEF_SB_ACCESSOR(int32_t, uinodes); 1077 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr); 1078 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, ifile, LFS_IFILE_INUM); 1079 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastseg); 1080 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, nextseg); 1081 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, curseg); 1082 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, offset); 1083 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastpseg); 1084 LFS_DEF_SB_ACCESSOR(u_int32_t, inopf); 1085 LFS_DEF_SB_ACCESSOR(u_int32_t, minfree); 1086 LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize); 1087 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbpseg); 1088 LFS_DEF_SB_ACCESSOR(u_int32_t, inopb); 1089 LFS_DEF_SB_ACCESSOR(u_int32_t, ifpb); 1090 LFS_DEF_SB_ACCESSOR(u_int32_t, sepb); 1091 LFS_DEF_SB_ACCESSOR(u_int32_t, nindir); 1092 LFS_DEF_SB_ACCESSOR(u_int32_t, nseg); 1093 LFS_DEF_SB_ACCESSOR(u_int32_t, nspf); 1094 LFS_DEF_SB_ACCESSOR(u_int32_t, cleansz); 1095 LFS_DEF_SB_ACCESSOR(u_int32_t, segtabsz); 1096 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segmask, 0); 1097 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segshift, 0); 1098 LFS_DEF_SB_ACCESSOR(u_int64_t, bmask); 1099 LFS_DEF_SB_ACCESSOR(u_int32_t, bshift); 1100 LFS_DEF_SB_ACCESSOR(u_int64_t, ffmask); 1101 LFS_DEF_SB_ACCESSOR(u_int32_t, ffshift); 1102 LFS_DEF_SB_ACCESSOR(u_int64_t, fbmask); 1103 LFS_DEF_SB_ACCESSOR(u_int32_t, fbshift); 1104 LFS_DEF_SB_ACCESSOR(u_int32_t, blktodb); 1105 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbtodb); 1106 LFS_DEF_SB_ACCESSOR(u_int32_t, sushift); 1107 LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen); 1108 LFS_DEF_SB_ACCESSOR(u_int32_t, cksum); 1109 LFS_DEF_SB_ACCESSOR(u_int16_t, pflags); 1110 LFS_DEF_SB_ACCESSOR(u_int32_t, nclean); 1111 LFS_DEF_SB_ACCESSOR(int32_t, dmeta); 1112 LFS_DEF_SB_ACCESSOR(u_int32_t, minfreeseg); 1113 LFS_DEF_SB_ACCESSOR(u_int32_t, sumsize); 1114 LFS_DEF_SB_ACCESSOR(u_int64_t, serial); 1115 LFS_DEF_SB_ACCESSOR(u_int32_t, ibsize); 1116 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr); 1117 LFS_DEF_SB_ACCESSOR(u_int64_t, tstamp); 1118 LFS_DEF_SB_ACCESSOR(u_int32_t, inodefmt); 1119 LFS_DEF_SB_ACCESSOR(u_int32_t, interleave); 1120 LFS_DEF_SB_ACCESSOR(u_int32_t, ident); 1121 LFS_DEF_SB_ACCESSOR(u_int32_t, resvseg); 1122 1123 /* special-case accessors */ 1124 1125 /* 1126 * the v1 otstamp field lives in what's now dlfs_inopf 1127 */ 1128 #define lfs_sb_getotstamp(fs) lfs_sb_getinopf(fs) 1129 #define lfs_sb_setotstamp(fs, val) lfs_sb_setinopf(fs, val) 1130 1131 /* 1132 * lfs_sboffs is an array 1133 */ 1134 static __unused inline int32_t 1135 lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n) 1136 { 1137 #ifdef KASSERT /* ugh */ 1138 KASSERT(n < LFS_MAXNUMSB); 1139 #endif 1140 if (fs->lfs_is64) { 1141 return fs->lfs_dlfs_u.u_64.dlfs_sboffs[n]; 1142 } else { 1143 return fs->lfs_dlfs_u.u_32.dlfs_sboffs[n]; 1144 } 1145 } 1146 static __unused inline void 1147 lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val) 1148 { 1149 #ifdef KASSERT /* ugh */ 1150 KASSERT(n < LFS_MAXNUMSB); 1151 #endif 1152 if (fs->lfs_is64) { 1153 fs->lfs_dlfs_u.u_64.dlfs_sboffs[n] = val; 1154 } else { 1155 fs->lfs_dlfs_u.u_32.dlfs_sboffs[n] = val; 1156 } 1157 } 1158 1159 /* 1160 * lfs_fsmnt is a string 1161 */ 1162 static __unused inline const char * 1163 lfs_sb_getfsmnt(STRUCT_LFS *fs) 1164 { 1165 if (fs->lfs_is64) { 1166 return fs->lfs_dlfs_u.u_64.dlfs_fsmnt; 1167 } else { 1168 return fs->lfs_dlfs_u.u_32.dlfs_fsmnt; 1169 } 1170 } 1171 1172 static __unused inline void 1173 lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str) 1174 { 1175 if (fs->lfs_is64) { 1176 (void)strncpy(fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str, 1177 sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt)); 1178 } else { 1179 (void)strncpy(fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str, 1180 sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt)); 1181 } 1182 } 1183 1184 /* Highest addressable fsb */ 1185 #define LFS_MAX_DADDR(fs) \ 1186 ((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff) 1187 1188 /* LFS_NINDIR is the number of indirects in a file system block. */ 1189 #define LFS_NINDIR(fs) (lfs_sb_getnindir(fs)) 1190 1191 /* LFS_INOPB is the number of inodes in a secondary storage block. */ 1192 #define LFS_INOPB(fs) (lfs_sb_getinopb(fs)) 1193 /* LFS_INOPF is the number of inodes in a fragment. */ 1194 #define LFS_INOPF(fs) (lfs_sb_getinopf(fs)) 1195 1196 #define lfs_blkoff(fs, loc) ((int)((loc) & lfs_sb_getbmask(fs))) 1197 #define lfs_fragoff(fs, loc) /* calculates (loc % fs->lfs_fsize) */ \ 1198 ((int)((loc) & lfs_sb_getffmask(fs))) 1199 1200 /* XXX: lowercase these as they're no longer macros */ 1201 /* Frags to diskblocks */ 1202 static __unused inline uint64_t 1203 LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b) 1204 { 1205 #if defined(_KERNEL) 1206 return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT); 1207 #else 1208 return b << lfs_sb_getfsbtodb(fs); 1209 #endif 1210 } 1211 /* Diskblocks to frags */ 1212 static __unused inline uint64_t 1213 LFS_DBTOFSB(STRUCT_LFS *fs, uint64_t b) 1214 { 1215 #if defined(_KERNEL) 1216 return b >> (lfs_sb_getffshift(fs) - DEV_BSHIFT); 1217 #else 1218 return b >> lfs_sb_getfsbtodb(fs); 1219 #endif 1220 } 1221 1222 #define lfs_lblkno(fs, loc) ((loc) >> lfs_sb_getbshift(fs)) 1223 #define lfs_lblktosize(fs, blk) ((blk) << lfs_sb_getbshift(fs)) 1224 1225 /* Frags to bytes */ 1226 static __unused inline uint64_t 1227 lfs_fsbtob(STRUCT_LFS *fs, uint64_t b) 1228 { 1229 return b << lfs_sb_getffshift(fs); 1230 } 1231 /* Bytes to frags */ 1232 static __unused inline uint64_t 1233 lfs_btofsb(STRUCT_LFS *fs, uint64_t b) 1234 { 1235 return b >> lfs_sb_getffshift(fs); 1236 } 1237 1238 #define lfs_numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \ 1239 ((loc) >> lfs_sb_getffshift(fs)) 1240 #define lfs_blkroundup(fs, size)/* calculates roundup(size, lfs_sb_getbsize(fs)) */ \ 1241 ((off_t)(((size) + lfs_sb_getbmask(fs)) & (~lfs_sb_getbmask(fs)))) 1242 #define lfs_fragroundup(fs, size)/* calculates roundup(size, fs->lfs_fsize) */ \ 1243 ((off_t)(((size) + lfs_sb_getffmask(fs)) & (~lfs_sb_getffmask(fs)))) 1244 #define lfs_fragstoblks(fs, frags)/* calculates (frags / fs->fs_frag) */ \ 1245 ((frags) >> lfs_sb_getfbshift(fs)) 1246 #define lfs_blkstofrags(fs, blks)/* calculates (blks * fs->fs_frag) */ \ 1247 ((blks) << lfs_sb_getfbshift(fs)) 1248 #define lfs_fragnum(fs, fsb) /* calculates (fsb % fs->lfs_frag) */ \ 1249 ((fsb) & ((fs)->lfs_frag - 1)) 1250 #define lfs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->lfs_frag) */ \ 1251 ((fsb) &~ ((fs)->lfs_frag - 1)) 1252 #define lfs_dblksize(fs, dp, lbn) \ 1253 (((lbn) >= ULFS_NDADDR || lfs_dino_getsize(fs, dp) >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \ 1254 ? lfs_sb_getbsize(fs) \ 1255 : (lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, dp))))) 1256 1257 #define lfs_segsize(fs) (lfs_sb_getversion(fs) == 1 ? \ 1258 lfs_lblktosize((fs), lfs_sb_getssize(fs)) : \ 1259 lfs_sb_getssize(fs)) 1260 /* XXX segtod produces a result in frags despite the 'd' */ 1261 #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg)) 1262 #define lfs_dtosn(fs, daddr) /* block address to segment number */ \ 1263 ((uint32_t)(((daddr) - lfs_sb_gets0addr(fs)) / lfs_segtod((fs), 1))) 1264 #define lfs_sntod(fs, sn) /* segment number to disk address */ \ 1265 ((daddr_t)(lfs_segtod((fs), (sn)) + lfs_sb_gets0addr(fs))) 1266 1267 /* XXX, blah. make this appear only if struct inode is defined */ 1268 #ifdef _UFS_LFS_LFS_INODE_H_ 1269 static __unused inline uint32_t 1270 lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn) 1271 { 1272 if (lbn >= ULFS_NDADDR || lfs_dino_getsize(fs, ip->i_din) >= (lbn + 1) << lfs_sb_getbshift(fs)) { 1273 return lfs_sb_getbsize(fs); 1274 } else { 1275 return lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, ip->i_din))); 1276 } 1277 } 1278 #endif 1279 1280 /* 1281 * union lfs_blocks 1282 */ 1283 1284 static __unused inline void 1285 lfs_blocks_fromvoid(STRUCT_LFS *fs, union lfs_blocks *bp, void *p) 1286 { 1287 if (fs->lfs_is64) { 1288 bp->b64 = p; 1289 } else { 1290 bp->b32 = p; 1291 } 1292 } 1293 1294 static __unused inline void 1295 lfs_blocks_fromfinfo(STRUCT_LFS *fs, union lfs_blocks *bp, FINFO *fip) 1296 { 1297 void *firstblock; 1298 1299 firstblock = (char *)fip + FINFOSIZE(fs); 1300 if (fs->lfs_is64) { 1301 bp->b64 = (int64_t *)firstblock; 1302 } else { 1303 bp->b32 = (int32_t *)firstblock; 1304 } 1305 } 1306 1307 static __unused inline daddr_t 1308 lfs_blocks_get(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index) 1309 { 1310 if (fs->lfs_is64) { 1311 return bp->b64[index]; 1312 } else { 1313 return bp->b32[index]; 1314 } 1315 } 1316 1317 static __unused inline void 1318 lfs_blocks_set(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index, daddr_t val) 1319 { 1320 if (fs->lfs_is64) { 1321 bp->b64[index] = val; 1322 } else { 1323 bp->b32[index] = val; 1324 } 1325 } 1326 1327 static __unused inline void 1328 lfs_blocks_inc(STRUCT_LFS *fs, union lfs_blocks *bp) 1329 { 1330 if (fs->lfs_is64) { 1331 bp->b64++; 1332 } else { 1333 bp->b32++; 1334 } 1335 } 1336 1337 static __unused inline int 1338 lfs_blocks_eq(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2) 1339 { 1340 if (fs->lfs_is64) { 1341 return bp1->b64 == bp2->b64; 1342 } else { 1343 return bp1->b32 == bp2->b32; 1344 } 1345 } 1346 1347 static __unused inline int 1348 lfs_blocks_sub(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2) 1349 { 1350 /* (remember that the pointers are typed) */ 1351 if (fs->lfs_is64) { 1352 return bp1->b64 - bp2->b64; 1353 } else { 1354 return bp1->b32 - bp2->b32; 1355 } 1356 } 1357 1358 /* 1359 * struct segment 1360 */ 1361 1362 1363 /* 1364 * Macros for determining free space on the disk, with the variable metadata 1365 * of segment summaries and inode blocks taken into account. 1366 */ 1367 /* 1368 * Estimate number of clean blocks not available for writing because 1369 * they will contain metadata or overhead. This is calculated as 1370 * 1371 * E = ((C * M / D) * D + (0) * (T - D)) / T 1372 * or more simply 1373 * E = (C * M) / T 1374 * 1375 * where 1376 * C is the clean space, 1377 * D is the dirty space, 1378 * M is the dirty metadata, and 1379 * T = C + D is the total space on disk. 1380 * 1381 * This approximates the old formula of E = C * M / D when D is close to T, 1382 * but avoids falsely reporting "disk full" when the sample size (D) is small. 1383 */ 1384 #define LFS_EST_CMETA(F) (int32_t)(( \ 1385 (lfs_sb_getdmeta(F) * (int64_t)lfs_sb_getnclean(F)) / \ 1386 (lfs_sb_getnseg(F)))) 1387 1388 /* Estimate total size of the disk not including metadata */ 1389 #define LFS_EST_NONMETA(F) (lfs_sb_getdsize(F) - lfs_sb_getdmeta(F) - LFS_EST_CMETA(F)) 1390 1391 /* Estimate number of blocks actually available for writing */ 1392 #define LFS_EST_BFREE(F) (lfs_sb_getbfree(F) > LFS_EST_CMETA(F) ? \ 1393 lfs_sb_getbfree(F) - LFS_EST_CMETA(F) : 0) 1394 1395 /* Amount of non-meta space not available to mortal man */ 1396 #define LFS_EST_RSVD(F) (int32_t)((LFS_EST_NONMETA(F) * \ 1397 (u_int64_t)lfs_sb_getminfree(F)) / \ 1398 100) 1399 1400 /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */ 1401 #define ISSPACE(F, BB, C) \ 1402 ((((C) == NOCRED || kauth_cred_geteuid(C) == 0) && \ 1403 LFS_EST_BFREE(F) >= (BB)) || \ 1404 (kauth_cred_geteuid(C) != 0 && IS_FREESPACE(F, BB))) 1405 1406 /* Can an ordinary user write BB blocks */ 1407 #define IS_FREESPACE(F, BB) \ 1408 (LFS_EST_BFREE(F) >= (BB) + LFS_EST_RSVD(F)) 1409 1410 /* 1411 * The minimum number of blocks to create a new inode. This is: 1412 * directory direct block (1) + ULFS_NIADDR indirect blocks + inode block (1) + 1413 * ifile direct block (1) + ULFS_NIADDR indirect blocks = 3 + 2 * ULFS_NIADDR blocks. 1414 */ 1415 #define LFS_NRESERVE(F) (lfs_btofsb((F), (2 * ULFS_NIADDR + 3) << lfs_sb_getbshift(F))) 1416 1417 1418 1419 #endif /* _UFS_LFS_LFS_ACCESSORS_H_ */ 1420