1 /* $NetBSD: lfs_accessors.h,v 1.49 2020/03/21 06:11:05 riastradh 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.25 2016/01/22 23:06:10 dholland Exp */ 5 /* from NetBSD: dir.h,v 1.25 2015/09/01 06:16:03 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 #include <ufs/lfs/lfs.h> 155 156 #if !defined(_KERNEL) && !defined(_STANDALONE) 157 #include <assert.h> 158 #include <string.h> 159 #define KASSERT assert 160 #else 161 #include <sys/systm.h> 162 #endif 163 164 /* 165 * STRUCT_LFS is used by the libsa code to get accessors that work 166 * with struct salfs instead of struct lfs, and by the cleaner to 167 * get accessors that work with struct clfs. 168 */ 169 170 #ifndef STRUCT_LFS 171 #define STRUCT_LFS struct lfs 172 #endif 173 174 /* 175 * byte order 176 */ 177 178 /* 179 * For now at least, the bootblocks shall not be endian-independent. 180 * We can see later if it fits in the size budget. Also disable the 181 * byteswapping if LFS_EI is off. 182 * 183 * Caution: these functions "know" that bswap16/32/64 are unsigned, 184 * and if that changes will likely break silently. 185 */ 186 187 #if defined(_STANDALONE) || (defined(_KERNEL) && !defined(LFS_EI)) 188 #define LFS_SWAP_int16_t(fs, val) (val) 189 #define LFS_SWAP_int32_t(fs, val) (val) 190 #define LFS_SWAP_int64_t(fs, val) (val) 191 #define LFS_SWAP_uint16_t(fs, val) (val) 192 #define LFS_SWAP_uint32_t(fs, val) (val) 193 #define LFS_SWAP_uint64_t(fs, val) (val) 194 #else 195 #define LFS_SWAP_int16_t(fs, val) \ 196 ((fs)->lfs_dobyteswap ? (int16_t)bswap16(val) : (val)) 197 #define LFS_SWAP_int32_t(fs, val) \ 198 ((fs)->lfs_dobyteswap ? (int32_t)bswap32(val) : (val)) 199 #define LFS_SWAP_int64_t(fs, val) \ 200 ((fs)->lfs_dobyteswap ? (int64_t)bswap64(val) : (val)) 201 #define LFS_SWAP_uint16_t(fs, val) \ 202 ((fs)->lfs_dobyteswap ? bswap16(val) : (val)) 203 #define LFS_SWAP_uint32_t(fs, val) \ 204 ((fs)->lfs_dobyteswap ? bswap32(val) : (val)) 205 #define LFS_SWAP_uint64_t(fs, val) \ 206 ((fs)->lfs_dobyteswap ? bswap64(val) : (val)) 207 #endif 208 209 /* 210 * For handling directories we will need to know if the volume is 211 * little-endian. 212 */ 213 #if BYTE_ORDER == LITTLE_ENDIAN 214 #define LFS_LITTLE_ENDIAN_ONDISK(fs) (!(fs)->lfs_dobyteswap) 215 #else 216 #define LFS_LITTLE_ENDIAN_ONDISK(fs) ((fs)->lfs_dobyteswap) 217 #endif 218 219 220 /* 221 * directories 222 */ 223 224 #define LFS_DIRHEADERSIZE(fs) \ 225 ((fs)->lfs_is64 ? sizeof(struct lfs_dirheader64) : sizeof(struct lfs_dirheader32)) 226 227 /* 228 * The LFS_DIRSIZ macro gives the minimum record length which will hold 229 * the directory entry. This requires the amount of space in struct lfs_direct 230 * without the d_name field, plus enough space for the name with a terminating 231 * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 232 */ 233 #define LFS_DIRECTSIZ(fs, namlen) \ 234 (LFS_DIRHEADERSIZE(fs) + (((namlen)+1 + 3) &~ 3)) 235 236 /* 237 * The size of the largest possible directory entry. This is 238 * used by ulfs_dirhash to figure the size of an array, so we 239 * need a single constant value true for both lfs32 and lfs64. 240 */ 241 #define LFS_MAXDIRENTRYSIZE \ 242 (sizeof(struct lfs_dirheader64) + (((LFS_MAXNAMLEN+1)+1 + 3) & ~3)) 243 244 #if (BYTE_ORDER == LITTLE_ENDIAN) 245 #define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ 246 (((oldfmt) && !(needswap)) ? \ 247 LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) 248 #else 249 #define LFS_OLDDIRSIZ(oldfmt, dp, needswap) \ 250 (((oldfmt) && (needswap)) ? \ 251 LFS_DIRECTSIZ((dp)->d_type) : LFS_DIRECTSIZ((dp)->d_namlen)) 252 #endif 253 254 #define LFS_DIRSIZ(fs, dp) LFS_DIRECTSIZ(fs, lfs_dir_getnamlen(fs, dp)) 255 256 /* Constants for the first argument of LFS_OLDDIRSIZ */ 257 #define LFS_OLDDIRFMT 1 258 #define LFS_NEWDIRFMT 0 259 260 #define LFS_NEXTDIR(fs, dp) \ 261 ((LFS_DIRHEADER *)((char *)(dp) + lfs_dir_getreclen(fs, dp))) 262 263 static __inline char * 264 lfs_dir_nameptr(const STRUCT_LFS *fs, LFS_DIRHEADER *dh) 265 { 266 if (fs->lfs_is64) { 267 return (char *)(&dh->u_64 + 1); 268 } else { 269 return (char *)(&dh->u_32 + 1); 270 } 271 } 272 273 static __inline uint64_t 274 lfs_dir_getino(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) 275 { 276 if (fs->lfs_is64) { 277 return LFS_SWAP_uint64_t(fs, dh->u_64.dh_ino); 278 } else { 279 return LFS_SWAP_uint32_t(fs, dh->u_32.dh_ino); 280 } 281 } 282 283 static __inline uint16_t 284 lfs_dir_getreclen(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) 285 { 286 if (fs->lfs_is64) { 287 return LFS_SWAP_uint16_t(fs, dh->u_64.dh_reclen); 288 } else { 289 return LFS_SWAP_uint16_t(fs, dh->u_32.dh_reclen); 290 } 291 } 292 293 static __inline uint8_t 294 lfs_dir_gettype(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) 295 { 296 if (fs->lfs_is64) { 297 KASSERT(fs->lfs_hasolddirfmt == 0); 298 return dh->u_64.dh_type; 299 } else if (fs->lfs_hasolddirfmt) { 300 return LFS_DT_UNKNOWN; 301 } else { 302 return dh->u_32.dh_type; 303 } 304 } 305 306 static __inline uint8_t 307 lfs_dir_getnamlen(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) 308 { 309 if (fs->lfs_is64) { 310 KASSERT(fs->lfs_hasolddirfmt == 0); 311 return dh->u_64.dh_namlen; 312 } else if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 313 /* low-order byte of old 16-bit namlen field */ 314 return dh->u_32.dh_type; 315 } else { 316 return dh->u_32.dh_namlen; 317 } 318 } 319 320 static __inline void 321 lfs_dir_setino(STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint64_t ino) 322 { 323 if (fs->lfs_is64) { 324 dh->u_64.dh_ino = LFS_SWAP_uint64_t(fs, ino); 325 } else { 326 dh->u_32.dh_ino = LFS_SWAP_uint32_t(fs, ino); 327 } 328 } 329 330 static __inline void 331 lfs_dir_setreclen(STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint16_t reclen) 332 { 333 if (fs->lfs_is64) { 334 dh->u_64.dh_reclen = LFS_SWAP_uint16_t(fs, reclen); 335 } else { 336 dh->u_32.dh_reclen = LFS_SWAP_uint16_t(fs, reclen); 337 } 338 } 339 340 static __inline void 341 lfs_dir_settype(const STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint8_t type) 342 { 343 if (fs->lfs_is64) { 344 KASSERT(fs->lfs_hasolddirfmt == 0); 345 dh->u_64.dh_type = type; 346 } else if (fs->lfs_hasolddirfmt) { 347 /* do nothing */ 348 return; 349 } else { 350 dh->u_32.dh_type = type; 351 } 352 } 353 354 static __inline void 355 lfs_dir_setnamlen(const STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint8_t namlen) 356 { 357 if (fs->lfs_is64) { 358 KASSERT(fs->lfs_hasolddirfmt == 0); 359 dh->u_64.dh_namlen = namlen; 360 } else if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { 361 /* low-order byte of old 16-bit namlen field */ 362 dh->u_32.dh_type = namlen; 363 } else { 364 dh->u_32.dh_namlen = namlen; 365 } 366 } 367 368 static __inline void 369 lfs_copydirname(STRUCT_LFS *fs, char *dest, const char *src, 370 unsigned namlen, unsigned reclen) 371 { 372 unsigned spacelen; 373 374 KASSERT(reclen > LFS_DIRHEADERSIZE(fs)); 375 spacelen = reclen - LFS_DIRHEADERSIZE(fs); 376 377 /* must always be at least 1 byte as a null terminator */ 378 KASSERT(spacelen > namlen); 379 380 memcpy(dest, src, namlen); 381 memset(dest + namlen, '\0', spacelen - namlen); 382 } 383 384 static __inline LFS_DIRHEADER * 385 lfs_dirtemplate_dotdot(STRUCT_LFS *fs, union lfs_dirtemplate *dt) 386 { 387 /* XXX blah, be nice to have a way to do this w/o casts */ 388 if (fs->lfs_is64) { 389 return (LFS_DIRHEADER *)&dt->u_64.dotdot_header; 390 } else { 391 return (LFS_DIRHEADER *)&dt->u_32.dotdot_header; 392 } 393 } 394 395 static __inline char * 396 lfs_dirtemplate_dotdotname(STRUCT_LFS *fs, union lfs_dirtemplate *dt) 397 { 398 if (fs->lfs_is64) { 399 return dt->u_64.dotdot_name; 400 } else { 401 return dt->u_32.dotdot_name; 402 } 403 } 404 405 /* 406 * dinodes 407 */ 408 409 /* 410 * Maximum length of a symlink that can be stored within the inode. 411 */ 412 #define LFS32_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t)) 413 #define LFS64_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t)) 414 415 #define LFS_MAXSYMLINKLEN(fs) \ 416 ((fs)->lfs_is64 ? LFS64_MAXSYMLINKLEN : LFS32_MAXSYMLINKLEN) 417 418 #define DINOSIZE(fs) ((fs)->lfs_is64 ? sizeof(struct lfs64_dinode) : sizeof(struct lfs32_dinode)) 419 420 #define DINO_IN_BLOCK(fs, base, ix) \ 421 ((union lfs_dinode *)((char *)(base) + DINOSIZE(fs) * (ix))) 422 423 static __inline void 424 lfs_copy_dinode(STRUCT_LFS *fs, 425 union lfs_dinode *dst, const union lfs_dinode *src) 426 { 427 /* 428 * We can do structure assignment of the structs, but not of 429 * the whole union, as the union is the size of the (larger) 430 * 64-bit struct and on a 32-bit fs the upper half of it might 431 * be off the end of a buffer or otherwise invalid. 432 */ 433 if (fs->lfs_is64) { 434 dst->u_64 = src->u_64; 435 } else { 436 dst->u_32 = src->u_32; 437 } 438 } 439 440 #define LFS_DEF_DINO_ACCESSOR(type, type32, field) \ 441 static __inline type \ 442 lfs_dino_get##field(STRUCT_LFS *fs, union lfs_dinode *dip) \ 443 { \ 444 if (fs->lfs_is64) { \ 445 return LFS_SWAP_##type(fs, dip->u_64.di_##field); \ 446 } else { \ 447 return LFS_SWAP_##type32(fs, dip->u_32.di_##field); \ 448 } \ 449 } \ 450 static __inline void \ 451 lfs_dino_set##field(STRUCT_LFS *fs, union lfs_dinode *dip, type val) \ 452 { \ 453 if (fs->lfs_is64) { \ 454 type *p = &dip->u_64.di_##field; \ 455 (void)p; \ 456 dip->u_64.di_##field = LFS_SWAP_##type(fs, val); \ 457 } else { \ 458 type32 *p = &dip->u_32.di_##field; \ 459 (void)p; \ 460 dip->u_32.di_##field = LFS_SWAP_##type32(fs, val); \ 461 } \ 462 } \ 463 464 LFS_DEF_DINO_ACCESSOR(uint16_t, uint16_t, mode); 465 LFS_DEF_DINO_ACCESSOR(int16_t, int16_t, nlink); 466 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, inumber); 467 LFS_DEF_DINO_ACCESSOR(uint64_t, uint64_t, size); 468 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, atime); 469 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, atimensec); 470 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, mtime); 471 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, mtimensec); 472 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, ctime); 473 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, ctimensec); 474 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, flags); 475 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, blocks); 476 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, gen); 477 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, uid); 478 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, gid); 479 480 /* XXX this should be done differently (it's a fake field) */ 481 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, rdev); 482 483 static __inline daddr_t 484 lfs_dino_getdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) 485 { 486 KASSERT(ix < ULFS_NDADDR); 487 if (fs->lfs_is64) { 488 return LFS_SWAP_int64_t(fs, dip->u_64.di_db[ix]); 489 } else { 490 /* note: this must sign-extend or UNWRITTEN gets trashed */ 491 return (int32_t)LFS_SWAP_int32_t(fs, dip->u_32.di_db[ix]); 492 } 493 } 494 495 static __inline daddr_t 496 lfs_dino_getib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) 497 { 498 KASSERT(ix < ULFS_NIADDR); 499 if (fs->lfs_is64) { 500 return LFS_SWAP_int64_t(fs, dip->u_64.di_ib[ix]); 501 } else { 502 /* note: this must sign-extend or UNWRITTEN gets trashed */ 503 return (int32_t)LFS_SWAP_int32_t(fs, dip->u_32.di_ib[ix]); 504 } 505 } 506 507 static __inline void 508 lfs_dino_setdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val) 509 { 510 KASSERT(ix < ULFS_NDADDR); 511 if (fs->lfs_is64) { 512 dip->u_64.di_db[ix] = LFS_SWAP_int64_t(fs, val); 513 } else { 514 dip->u_32.di_db[ix] = LFS_SWAP_uint32_t(fs, val); 515 } 516 } 517 518 static __inline void 519 lfs_dino_setib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val) 520 { 521 KASSERT(ix < ULFS_NIADDR); 522 if (fs->lfs_is64) { 523 dip->u_64.di_ib[ix] = LFS_SWAP_int64_t(fs, val); 524 } else { 525 dip->u_32.di_ib[ix] = LFS_SWAP_uint32_t(fs, val); 526 } 527 } 528 529 /* birthtime is present only in the 64-bit inode */ 530 static __inline void 531 lfs_dino_setbirthtime(STRUCT_LFS *fs, union lfs_dinode *dip, 532 const struct timespec *ts) 533 { 534 if (fs->lfs_is64) { 535 dip->u_64.di_birthtime = ts->tv_sec; 536 dip->u_64.di_birthnsec = ts->tv_nsec; 537 } else { 538 /* drop it on the floor */ 539 } 540 } 541 542 /* 543 * indirect blocks 544 */ 545 546 static __inline daddr_t 547 lfs_iblock_get(STRUCT_LFS *fs, void *block, unsigned ix) 548 { 549 if (fs->lfs_is64) { 550 // XXX re-enable these asserts after reorging this file 551 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t)); 552 return (daddr_t)(((int64_t *)block)[ix]); 553 } else { 554 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t)); 555 /* must sign-extend or UNWRITTEN gets trashed */ 556 return (daddr_t)(int64_t)(((int32_t *)block)[ix]); 557 } 558 } 559 560 static __inline void 561 lfs_iblock_set(STRUCT_LFS *fs, void *block, unsigned ix, daddr_t val) 562 { 563 if (fs->lfs_is64) { 564 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t)); 565 ((int64_t *)block)[ix] = val; 566 } else { 567 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t)); 568 ((int32_t *)block)[ix] = val; 569 } 570 } 571 572 /* 573 * "struct buf" associated definitions 574 */ 575 576 # define LFS_LOCK_BUF(bp) do { \ 577 if (((bp)->b_flags & B_LOCKED) == 0 && bp->b_iodone == NULL) { \ 578 mutex_enter(&lfs_lock); \ 579 ++locked_queue_count; \ 580 locked_queue_bytes += bp->b_bufsize; \ 581 mutex_exit(&lfs_lock); \ 582 } \ 583 (bp)->b_flags |= B_LOCKED; \ 584 } while (0) 585 586 # define LFS_UNLOCK_BUF(bp) do { \ 587 if (((bp)->b_flags & B_LOCKED) != 0 && bp->b_iodone == NULL) { \ 588 mutex_enter(&lfs_lock); \ 589 --locked_queue_count; \ 590 locked_queue_bytes -= bp->b_bufsize; \ 591 if (locked_queue_count < LFS_WAIT_BUFS && \ 592 locked_queue_bytes < LFS_WAIT_BYTES) \ 593 cv_broadcast(&locked_queue_cv); \ 594 mutex_exit(&lfs_lock); \ 595 } \ 596 (bp)->b_flags &= ~B_LOCKED; \ 597 } while (0) 598 599 /* 600 * "struct inode" associated definitions 601 */ 602 603 #define LFS_SET_UINO(ip, states) do { \ 604 if (((states) & IN_ACCESSED) && !((ip)->i_state & IN_ACCESSED)) \ 605 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 606 if (((states) & IN_CLEANING) && !((ip)->i_state & IN_CLEANING)) \ 607 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 608 if (((states) & IN_MODIFIED) && !((ip)->i_state & IN_MODIFIED)) \ 609 lfs_sb_adduinodes((ip)->i_lfs, 1); \ 610 (ip)->i_state |= (states); \ 611 } while (0) 612 613 #define LFS_CLR_UINO(ip, states) do { \ 614 if (((states) & IN_ACCESSED) && ((ip)->i_state & IN_ACCESSED)) \ 615 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 616 if (((states) & IN_CLEANING) && ((ip)->i_state & IN_CLEANING)) \ 617 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 618 if (((states) & IN_MODIFIED) && ((ip)->i_state & IN_MODIFIED)) \ 619 lfs_sb_subuinodes((ip)->i_lfs, 1); \ 620 (ip)->i_state &= ~(states); \ 621 if (lfs_sb_getuinodes((ip)->i_lfs) < 0) { \ 622 panic("lfs_uinodes < 0"); \ 623 } \ 624 } while (0) 625 626 #define LFS_ITIMES(ip, acc, mod, cre) \ 627 while ((ip)->i_state & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \ 628 lfs_itimes(ip, acc, mod, cre) 629 630 /* 631 * On-disk and in-memory checkpoint segment usage structure. 632 */ 633 634 #define SEGUPB(fs) (lfs_sb_getsepb(fs)) 635 #define SEGTABSIZE_SU(fs) \ 636 ((lfs_sb_getnseg(fs) + SEGUPB(fs) - 1) / lfs_sb_getsepb(fs)) 637 638 #ifdef _KERNEL 639 # define SHARE_IFLOCK(F) \ 640 do { \ 641 rw_enter(&(F)->lfs_iflock, RW_READER); \ 642 } while(0) 643 # define UNSHARE_IFLOCK(F) \ 644 do { \ 645 rw_exit(&(F)->lfs_iflock); \ 646 } while(0) 647 #else /* ! _KERNEL */ 648 # define SHARE_IFLOCK(F) 649 # define UNSHARE_IFLOCK(F) 650 #endif /* ! _KERNEL */ 651 652 /* Read in the block with a specific segment usage entry from the ifile. */ 653 #define LFS_SEGENTRY(SP, F, IN, BP) do { \ 654 int _e; \ 655 SHARE_IFLOCK(F); \ 656 VTOI((F)->lfs_ivnode)->i_state |= IN_ACCESS; \ 657 if ((_e = bread((F)->lfs_ivnode, \ 658 ((IN) / lfs_sb_getsepb(F)) + lfs_sb_getcleansz(F), \ 659 lfs_sb_getbsize(F), 0, &(BP))) != 0) \ 660 panic("lfs: ifile read: segentry %llu: error %d\n", \ 661 (unsigned long long)(IN), _e); \ 662 if (lfs_sb_getversion(F) == 1) \ 663 (SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data + \ 664 ((IN) & (lfs_sb_getsepb(F) - 1))); \ 665 else \ 666 (SP) = (SEGUSE *)(BP)->b_data + ((IN) % lfs_sb_getsepb(F)); \ 667 UNSHARE_IFLOCK(F); \ 668 } while (0) 669 670 #define LFS_WRITESEGENTRY(SP, F, IN, BP) do { \ 671 if ((SP)->su_nbytes == 0) \ 672 (SP)->su_flags |= SEGUSE_EMPTY; \ 673 else \ 674 (SP)->su_flags &= ~SEGUSE_EMPTY; \ 675 (F)->lfs_suflags[(F)->lfs_activesb][(IN)] = (SP)->su_flags; \ 676 LFS_BWRITE_LOG(BP); \ 677 } while (0) 678 679 /* 680 * FINFO (file info) entries. 681 */ 682 683 /* Size of an on-disk block pointer, e.g. in an indirect block. */ 684 /* XXX: move to a more suitable location in this file */ 685 #define LFS_BLKPTRSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t)) 686 687 /* Size of an on-disk inode number. */ 688 /* XXX: move to a more suitable location in this file */ 689 #define LFS_INUMSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t)) 690 691 /* size of a FINFO, without the block pointers */ 692 #define FINFOSIZE(fs) ((fs)->lfs_is64 ? sizeof(FINFO64) : sizeof(FINFO32)) 693 694 /* Full size of the provided FINFO record, including its block pointers. */ 695 #define FINFO_FULLSIZE(fs, fip) \ 696 (FINFOSIZE(fs) + lfs_fi_getnblocks(fs, fip) * LFS_BLKPTRSIZE(fs)) 697 698 #define NEXT_FINFO(fs, fip) \ 699 ((FINFO *)((char *)(fip) + FINFO_FULLSIZE(fs, fip))) 700 701 #define LFS_DEF_FI_ACCESSOR(type, type32, field) \ 702 static __inline type \ 703 lfs_fi_get##field(STRUCT_LFS *fs, FINFO *fip) \ 704 { \ 705 if (fs->lfs_is64) { \ 706 return fip->u_64.fi_##field; \ 707 } else { \ 708 return fip->u_32.fi_##field; \ 709 } \ 710 } \ 711 static __inline void \ 712 lfs_fi_set##field(STRUCT_LFS *fs, FINFO *fip, type val) \ 713 { \ 714 if (fs->lfs_is64) { \ 715 type *p = &fip->u_64.fi_##field; \ 716 (void)p; \ 717 fip->u_64.fi_##field = val; \ 718 } else { \ 719 type32 *p = &fip->u_32.fi_##field; \ 720 (void)p; \ 721 fip->u_32.fi_##field = val; \ 722 } \ 723 } \ 724 725 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, nblocks); 726 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, version); 727 LFS_DEF_FI_ACCESSOR(uint64_t, uint32_t, ino); 728 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, lastlength); 729 730 static __inline daddr_t 731 lfs_fi_getblock(STRUCT_LFS *fs, FINFO *fip, unsigned idx) 732 { 733 void *firstblock; 734 735 firstblock = (char *)fip + FINFOSIZE(fs); 736 KASSERT(idx < lfs_fi_getnblocks(fs, fip)); 737 if (fs->lfs_is64) { 738 return ((int64_t *)firstblock)[idx]; 739 } else { 740 return ((int32_t *)firstblock)[idx]; 741 } 742 } 743 744 static __inline void 745 lfs_fi_setblock(STRUCT_LFS *fs, FINFO *fip, unsigned idx, daddr_t blk) 746 { 747 void *firstblock; 748 749 firstblock = (char *)fip + FINFOSIZE(fs); 750 KASSERT(idx < lfs_fi_getnblocks(fs, fip)); 751 if (fs->lfs_is64) { 752 ((int64_t *)firstblock)[idx] = blk; 753 } else { 754 ((int32_t *)firstblock)[idx] = blk; 755 } 756 } 757 758 /* 759 * inode info entries (in the segment summary) 760 */ 761 762 #define IINFOSIZE(fs) ((fs)->lfs_is64 ? sizeof(IINFO64) : sizeof(IINFO32)) 763 764 /* iinfos scroll backward from the end of the segment summary block */ 765 #define SEGSUM_IINFOSTART(fs, buf) \ 766 ((IINFO *)((char *)buf + lfs_sb_getsumsize(fs) - IINFOSIZE(fs))) 767 768 #define NEXTLOWER_IINFO(fs, iip) \ 769 ((IINFO *)((char *)(iip) - IINFOSIZE(fs))) 770 771 #define NTH_IINFO(fs, buf, n) \ 772 ((IINFO *)((char *)SEGSUM_IINFOSTART(fs, buf) - (n)*IINFOSIZE(fs))) 773 774 static __inline uint64_t 775 lfs_ii_getblock(STRUCT_LFS *fs, IINFO *iip) 776 { 777 if (fs->lfs_is64) { 778 return iip->u_64.ii_block; 779 } else { 780 return iip->u_32.ii_block; 781 } 782 } 783 784 static __inline void 785 lfs_ii_setblock(STRUCT_LFS *fs, IINFO *iip, uint64_t block) 786 { 787 if (fs->lfs_is64) { 788 iip->u_64.ii_block = block; 789 } else { 790 iip->u_32.ii_block = block; 791 } 792 } 793 794 /* 795 * Index file inode entries. 796 */ 797 798 #define IFILE_ENTRYSIZE(fs) \ 799 ((fs)->lfs_is64 ? sizeof(IFILE64) : sizeof(IFILE32)) 800 801 /* 802 * LFSv1 compatibility code is not allowed to touch if_atime, since it 803 * may not be mapped! 804 */ 805 /* Read in the block with a specific inode from the ifile. */ 806 #define LFS_IENTRY(IP, F, IN, BP) do { \ 807 int _e; \ 808 SHARE_IFLOCK(F); \ 809 VTOI((F)->lfs_ivnode)->i_state |= IN_ACCESS; \ 810 if ((_e = bread((F)->lfs_ivnode, \ 811 (IN) / lfs_sb_getifpb(F) + lfs_sb_getcleansz(F) + lfs_sb_getsegtabsz(F), \ 812 lfs_sb_getbsize(F), 0, &(BP))) != 0) \ 813 panic("lfs: ifile ino %d read %d", (int)(IN), _e); \ 814 if ((F)->lfs_is64) { \ 815 (IP) = (IFILE *)((IFILE64 *)(BP)->b_data + \ 816 (IN) % lfs_sb_getifpb(F)); \ 817 } else if (lfs_sb_getversion(F) > 1) { \ 818 (IP) = (IFILE *)((IFILE32 *)(BP)->b_data + \ 819 (IN) % lfs_sb_getifpb(F)); \ 820 } else { \ 821 (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + \ 822 (IN) % lfs_sb_getifpb(F)); \ 823 } \ 824 UNSHARE_IFLOCK(F); \ 825 } while (0) 826 #define LFS_IENTRY_NEXT(IP, F) do { \ 827 if ((F)->lfs_is64) { \ 828 (IP) = (IFILE *)((IFILE64 *)(IP) + 1); \ 829 } else if (lfs_sb_getversion(F) > 1) { \ 830 (IP) = (IFILE *)((IFILE32 *)(IP) + 1); \ 831 } else { \ 832 (IP) = (IFILE *)((IFILE_V1 *)(IP) + 1); \ 833 } \ 834 } while (0) 835 836 #define LFS_DEF_IF_ACCESSOR(type, type32, field) \ 837 static __inline type \ 838 lfs_if_get##field(STRUCT_LFS *fs, IFILE *ifp) \ 839 { \ 840 if (fs->lfs_is64) { \ 841 return ifp->u_64.if_##field; \ 842 } else { \ 843 return ifp->u_32.if_##field; \ 844 } \ 845 } \ 846 static __inline void \ 847 lfs_if_set##field(STRUCT_LFS *fs, IFILE *ifp, type val) \ 848 { \ 849 if (fs->lfs_is64) { \ 850 type *p = &ifp->u_64.if_##field; \ 851 (void)p; \ 852 ifp->u_64.if_##field = val; \ 853 } else { \ 854 type32 *p = &ifp->u_32.if_##field; \ 855 (void)p; \ 856 ifp->u_32.if_##field = val; \ 857 } \ 858 } \ 859 860 LFS_DEF_IF_ACCESSOR(uint32_t, uint32_t, version); 861 LFS_DEF_IF_ACCESSOR(int64_t, int32_t, daddr); 862 LFS_DEF_IF_ACCESSOR(uint64_t, uint32_t, nextfree); 863 LFS_DEF_IF_ACCESSOR(uint64_t, uint32_t, atime_sec); 864 LFS_DEF_IF_ACCESSOR(uint32_t, uint32_t, atime_nsec); 865 866 /* 867 * Cleaner information structure. This resides in the ifile and is used 868 * to pass information from the kernel to the cleaner. 869 */ 870 871 #define CLEANSIZE_SU(fs) \ 872 ((((fs)->lfs_is64 ? sizeof(CLEANERINFO64) : sizeof(CLEANERINFO32)) + \ 873 lfs_sb_getbsize(fs) - 1) >> lfs_sb_getbshift(fs)) 874 875 #define LFS_DEF_CI_ACCESSOR(type, type32, field) \ 876 static __inline type \ 877 lfs_ci_get##field(STRUCT_LFS *fs, CLEANERINFO *cip) \ 878 { \ 879 if (fs->lfs_is64) { \ 880 return cip->u_64.field; \ 881 } else { \ 882 return cip->u_32.field; \ 883 } \ 884 } \ 885 static __inline void \ 886 lfs_ci_set##field(STRUCT_LFS *fs, CLEANERINFO *cip, type val) \ 887 { \ 888 if (fs->lfs_is64) { \ 889 type *p = &cip->u_64.field; \ 890 (void)p; \ 891 cip->u_64.field = val; \ 892 } else { \ 893 type32 *p = &cip->u_32.field; \ 894 (void)p; \ 895 cip->u_32.field = val; \ 896 } \ 897 } \ 898 899 LFS_DEF_CI_ACCESSOR(uint32_t, uint32_t, clean); 900 LFS_DEF_CI_ACCESSOR(uint32_t, uint32_t, dirty); 901 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, bfree); 902 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, avail); 903 LFS_DEF_CI_ACCESSOR(uint64_t, uint32_t, free_head); 904 LFS_DEF_CI_ACCESSOR(uint64_t, uint32_t, free_tail); 905 LFS_DEF_CI_ACCESSOR(uint32_t, uint32_t, flags); 906 907 static __inline void 908 lfs_ci_shiftcleantodirty(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num) 909 { 910 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) - num); 911 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) + num); 912 } 913 914 static __inline void 915 lfs_ci_shiftdirtytoclean(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num) 916 { 917 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) - num); 918 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) + num); 919 } 920 921 /* Read in the block with the cleaner info from the ifile. */ 922 #define LFS_CLEANERINFO(CP, F, BP) do { \ 923 int _e; \ 924 SHARE_IFLOCK(F); \ 925 VTOI((F)->lfs_ivnode)->i_state |= IN_ACCESS; \ 926 _e = bread((F)->lfs_ivnode, \ 927 (daddr_t)0, lfs_sb_getbsize(F), 0, &(BP)); \ 928 if (_e) \ 929 panic("lfs: ifile read: cleanerinfo: error %d\n", _e); \ 930 (CP) = (CLEANERINFO *)(BP)->b_data; \ 931 UNSHARE_IFLOCK(F); \ 932 } while (0) 933 934 /* 935 * Synchronize the Ifile cleaner info with current avail and bfree. 936 */ 937 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do { \ 938 mutex_enter(&lfs_lock); \ 939 if ((w) || lfs_ci_getbfree(fs, cip) != lfs_sb_getbfree(fs) || \ 940 lfs_ci_getavail(fs, cip) != lfs_sb_getavail(fs) - fs->lfs_ravail - \ 941 fs->lfs_favail) { \ 942 lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); \ 943 lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) - fs->lfs_ravail - \ 944 fs->lfs_favail); \ 945 if (((bp)->b_flags & B_GATHERED) == 0) { \ 946 fs->lfs_flags |= LFS_IFDIRTY; \ 947 } \ 948 mutex_exit(&lfs_lock); \ 949 (void) LFS_BWRITE_LOG(bp); /* Ifile */ \ 950 } else { \ 951 mutex_exit(&lfs_lock); \ 952 brelse(bp, 0); \ 953 } \ 954 } while (0) 955 956 /* 957 * Get the head of the inode free list. 958 * Always called with the segment lock held. 959 */ 960 #define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do { \ 961 if (lfs_sb_getversion(FS) > 1) { \ 962 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 963 lfs_sb_setfreehd(FS, lfs_ci_getfree_head(FS, CIP)); \ 964 brelse(BP, 0); \ 965 } \ 966 *(FREEP) = lfs_sb_getfreehd(FS); \ 967 } while (0) 968 969 #define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do { \ 970 lfs_sb_setfreehd(FS, VAL); \ 971 if (lfs_sb_getversion(FS) > 1) { \ 972 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 973 lfs_ci_setfree_head(FS, CIP, VAL); \ 974 LFS_BWRITE_LOG(BP); \ 975 mutex_enter(&lfs_lock); \ 976 (FS)->lfs_flags |= LFS_IFDIRTY; \ 977 mutex_exit(&lfs_lock); \ 978 } \ 979 } while (0) 980 981 #define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do { \ 982 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 983 *(FREEP) = lfs_ci_getfree_tail(FS, CIP); \ 984 brelse(BP, 0); \ 985 } while (0) 986 987 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \ 988 LFS_CLEANERINFO((CIP), (FS), (BP)); \ 989 lfs_ci_setfree_tail(FS, CIP, VAL); \ 990 LFS_BWRITE_LOG(BP); \ 991 mutex_enter(&lfs_lock); \ 992 (FS)->lfs_flags |= LFS_IFDIRTY; \ 993 mutex_exit(&lfs_lock); \ 994 } while (0) 995 996 /* 997 * On-disk segment summary information 998 */ 999 1000 #define SEGSUM_SIZE(fs) \ 1001 (fs->lfs_is64 ? sizeof(SEGSUM64) : \ 1002 lfs_sb_getversion(fs) > 1 ? sizeof(SEGSUM32) : sizeof(SEGSUM_V1)) 1003 1004 /* 1005 * The SEGSUM structure is followed by FINFO structures. Get the pointer 1006 * to the first FINFO. 1007 * 1008 * XXX this can't be a macro yet; this file needs to be resorted. 1009 */ 1010 #if 0 1011 static __inline FINFO * 1012 segsum_finfobase(STRUCT_LFS *fs, SEGSUM *ssp) 1013 { 1014 return (FINFO *)((char *)ssp + SEGSUM_SIZE(fs)); 1015 } 1016 #else 1017 #define SEGSUM_FINFOBASE(fs, ssp) \ 1018 ((FINFO *)((char *)(ssp) + SEGSUM_SIZE(fs))); 1019 #endif 1020 1021 #define LFS_DEF_SS_ACCESSOR(type, type32, field) \ 1022 static __inline type \ 1023 lfs_ss_get##field(STRUCT_LFS *fs, SEGSUM *ssp) \ 1024 { \ 1025 if (fs->lfs_is64) { \ 1026 return ssp->u_64.ss_##field; \ 1027 } else { \ 1028 return ssp->u_32.ss_##field; \ 1029 } \ 1030 } \ 1031 static __inline void \ 1032 lfs_ss_set##field(STRUCT_LFS *fs, SEGSUM *ssp, type val) \ 1033 { \ 1034 if (fs->lfs_is64) { \ 1035 type *p = &ssp->u_64.ss_##field; \ 1036 (void)p; \ 1037 ssp->u_64.ss_##field = val; \ 1038 } else { \ 1039 type32 *p = &ssp->u_32.ss_##field; \ 1040 (void)p; \ 1041 ssp->u_32.ss_##field = val; \ 1042 } \ 1043 } \ 1044 1045 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, sumsum); 1046 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, datasum); 1047 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, magic); 1048 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, ident); 1049 LFS_DEF_SS_ACCESSOR(int64_t, int32_t, next); 1050 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, nfinfo); 1051 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, ninos); 1052 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, flags); 1053 LFS_DEF_SS_ACCESSOR(uint64_t, uint32_t, reclino); 1054 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, serial); 1055 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, create); 1056 1057 static __inline size_t 1058 lfs_ss_getsumstart(STRUCT_LFS *fs) 1059 { 1060 /* These are actually all the same. */ 1061 if (fs->lfs_is64) { 1062 return offsetof(SEGSUM64, ss_datasum); 1063 } else /* if (lfs_sb_getversion(fs) > 1) */ { 1064 return offsetof(SEGSUM32, ss_datasum); 1065 } /* else { 1066 return offsetof(SEGSUM_V1, ss_datasum); 1067 } */ 1068 /* 1069 * XXX ^^^ until this file is resorted lfs_sb_getversion isn't 1070 * defined yet. 1071 */ 1072 } 1073 1074 static __inline uint32_t 1075 lfs_ss_getocreate(STRUCT_LFS *fs, SEGSUM *ssp) 1076 { 1077 KASSERT(fs->lfs_is64 == 0); 1078 /* XXX need to resort this file before we can do this */ 1079 //KASSERT(lfs_sb_getversion(fs) == 1); 1080 1081 return ssp->u_v1.ss_create; 1082 } 1083 1084 static __inline void 1085 lfs_ss_setocreate(STRUCT_LFS *fs, SEGSUM *ssp, uint32_t val) 1086 { 1087 KASSERT(fs->lfs_is64 == 0); 1088 /* XXX need to resort this file before we can do this */ 1089 //KASSERT(lfs_sb_getversion(fs) == 1); 1090 1091 ssp->u_v1.ss_create = val; 1092 } 1093 1094 1095 /* 1096 * Super block. 1097 */ 1098 1099 /* 1100 * Generate accessors for the on-disk superblock fields with cpp. 1101 */ 1102 1103 #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \ 1104 static __inline type \ 1105 lfs_sb_get##field(STRUCT_LFS *fs) \ 1106 { \ 1107 if (fs->lfs_is64) { \ 1108 return fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1109 } else { \ 1110 return fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1111 } \ 1112 } \ 1113 static __inline void \ 1114 lfs_sb_set##field(STRUCT_LFS *fs, type val) \ 1115 { \ 1116 if (fs->lfs_is64) { \ 1117 fs->lfs_dlfs_u.u_64.dlfs_##field = val; \ 1118 } else { \ 1119 fs->lfs_dlfs_u.u_32.dlfs_##field = val; \ 1120 } \ 1121 } \ 1122 static __inline void \ 1123 lfs_sb_add##field(STRUCT_LFS *fs, type val) \ 1124 { \ 1125 if (fs->lfs_is64) { \ 1126 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1127 *p64 += val; \ 1128 } else { \ 1129 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1130 *p32 += val; \ 1131 } \ 1132 } \ 1133 static __inline void \ 1134 lfs_sb_sub##field(STRUCT_LFS *fs, type val) \ 1135 { \ 1136 if (fs->lfs_is64) { \ 1137 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \ 1138 *p64 -= val; \ 1139 } else { \ 1140 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1141 *p32 -= val; \ 1142 } \ 1143 } 1144 1145 #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f) 1146 1147 #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \ 1148 static __inline type \ 1149 lfs_sb_get##field(STRUCT_LFS *fs) \ 1150 { \ 1151 if (fs->lfs_is64) { \ 1152 return val64; \ 1153 } else { \ 1154 return fs->lfs_dlfs_u.u_32.dlfs_##field; \ 1155 } \ 1156 } 1157 1158 LFS_DEF_SB_ACCESSOR(uint32_t, version); 1159 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, size); 1160 LFS_DEF_SB_ACCESSOR(uint32_t, ssize); 1161 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, dsize); 1162 LFS_DEF_SB_ACCESSOR(uint32_t, bsize); 1163 LFS_DEF_SB_ACCESSOR(uint32_t, fsize); 1164 LFS_DEF_SB_ACCESSOR(uint32_t, frag); 1165 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, freehd); 1166 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree); 1167 LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, nfiles); 1168 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail); 1169 LFS_DEF_SB_ACCESSOR(int32_t, uinodes); 1170 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr); 1171 LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, ifile, LFS_IFILE_INUM); 1172 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastseg); 1173 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, nextseg); 1174 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, curseg); 1175 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, offset); 1176 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastpseg); 1177 LFS_DEF_SB_ACCESSOR(uint32_t, inopf); 1178 LFS_DEF_SB_ACCESSOR(uint32_t, minfree); 1179 LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize); 1180 LFS_DEF_SB_ACCESSOR(uint32_t, fsbpseg); 1181 LFS_DEF_SB_ACCESSOR(uint32_t, inopb); 1182 LFS_DEF_SB_ACCESSOR(uint32_t, ifpb); 1183 LFS_DEF_SB_ACCESSOR(uint32_t, sepb); 1184 LFS_DEF_SB_ACCESSOR(uint32_t, nindir); 1185 LFS_DEF_SB_ACCESSOR(uint32_t, nseg); 1186 LFS_DEF_SB_ACCESSOR(uint32_t, nspf); 1187 LFS_DEF_SB_ACCESSOR(uint32_t, cleansz); 1188 LFS_DEF_SB_ACCESSOR(uint32_t, segtabsz); 1189 LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, segmask, 0); 1190 LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, segshift, 0); 1191 LFS_DEF_SB_ACCESSOR(uint64_t, bmask); 1192 LFS_DEF_SB_ACCESSOR(uint32_t, bshift); 1193 LFS_DEF_SB_ACCESSOR(uint64_t, ffmask); 1194 LFS_DEF_SB_ACCESSOR(uint32_t, ffshift); 1195 LFS_DEF_SB_ACCESSOR(uint64_t, fbmask); 1196 LFS_DEF_SB_ACCESSOR(uint32_t, fbshift); 1197 LFS_DEF_SB_ACCESSOR(uint32_t, blktodb); 1198 LFS_DEF_SB_ACCESSOR(uint32_t, fsbtodb); 1199 LFS_DEF_SB_ACCESSOR(uint32_t, sushift); 1200 LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen); 1201 LFS_DEF_SB_ACCESSOR(uint32_t, cksum); 1202 LFS_DEF_SB_ACCESSOR(uint16_t, pflags); 1203 LFS_DEF_SB_ACCESSOR(uint32_t, nclean); 1204 LFS_DEF_SB_ACCESSOR(int32_t, dmeta); 1205 LFS_DEF_SB_ACCESSOR(uint32_t, minfreeseg); 1206 LFS_DEF_SB_ACCESSOR(uint32_t, sumsize); 1207 LFS_DEF_SB_ACCESSOR(uint64_t, serial); 1208 LFS_DEF_SB_ACCESSOR(uint32_t, ibsize); 1209 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr); 1210 LFS_DEF_SB_ACCESSOR(uint64_t, tstamp); 1211 LFS_DEF_SB_ACCESSOR(uint32_t, inodefmt); 1212 LFS_DEF_SB_ACCESSOR(uint32_t, interleave); 1213 LFS_DEF_SB_ACCESSOR(uint32_t, ident); 1214 LFS_DEF_SB_ACCESSOR(uint32_t, resvseg); 1215 1216 /* special-case accessors */ 1217 1218 /* 1219 * the v1 otstamp field lives in what's now dlfs_inopf 1220 */ 1221 #define lfs_sb_getotstamp(fs) lfs_sb_getinopf(fs) 1222 #define lfs_sb_setotstamp(fs, val) lfs_sb_setinopf(fs, val) 1223 1224 /* 1225 * lfs_sboffs is an array 1226 */ 1227 static __inline int32_t 1228 lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n) 1229 { 1230 #ifdef KASSERT /* ugh */ 1231 KASSERT(n < LFS_MAXNUMSB); 1232 #endif 1233 if (fs->lfs_is64) { 1234 return fs->lfs_dlfs_u.u_64.dlfs_sboffs[n]; 1235 } else { 1236 return fs->lfs_dlfs_u.u_32.dlfs_sboffs[n]; 1237 } 1238 } 1239 static __inline void 1240 lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val) 1241 { 1242 #ifdef KASSERT /* ugh */ 1243 KASSERT(n < LFS_MAXNUMSB); 1244 #endif 1245 if (fs->lfs_is64) { 1246 fs->lfs_dlfs_u.u_64.dlfs_sboffs[n] = val; 1247 } else { 1248 fs->lfs_dlfs_u.u_32.dlfs_sboffs[n] = val; 1249 } 1250 } 1251 1252 /* 1253 * lfs_fsmnt is a string 1254 */ 1255 static __inline const char * 1256 lfs_sb_getfsmnt(STRUCT_LFS *fs) 1257 { 1258 if (fs->lfs_is64) { 1259 return (const char *)fs->lfs_dlfs_u.u_64.dlfs_fsmnt; 1260 } else { 1261 return (const char *)fs->lfs_dlfs_u.u_32.dlfs_fsmnt; 1262 } 1263 } 1264 1265 static __inline void 1266 lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str) 1267 { 1268 if (fs->lfs_is64) { 1269 (void)strncpy((char *)fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str, 1270 sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt)); 1271 } else { 1272 (void)strncpy((char *)fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str, 1273 sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt)); 1274 } 1275 } 1276 1277 /* Highest addressable fsb */ 1278 #define LFS_MAX_DADDR(fs) \ 1279 ((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff) 1280 1281 /* LFS_NINDIR is the number of indirects in a file system block. */ 1282 #define LFS_NINDIR(fs) (lfs_sb_getnindir(fs)) 1283 1284 /* LFS_INOPB is the number of inodes in a secondary storage block. */ 1285 #define LFS_INOPB(fs) (lfs_sb_getinopb(fs)) 1286 /* LFS_INOPF is the number of inodes in a fragment. */ 1287 #define LFS_INOPF(fs) (lfs_sb_getinopf(fs)) 1288 1289 #define lfs_blkoff(fs, loc) ((int)((loc) & lfs_sb_getbmask(fs))) 1290 #define lfs_fragoff(fs, loc) /* calculates (loc % fs->lfs_fsize) */ \ 1291 ((int)((loc) & lfs_sb_getffmask(fs))) 1292 1293 /* XXX: lowercase these as they're no longer macros */ 1294 /* Frags to diskblocks */ 1295 static __inline uint64_t 1296 LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b) 1297 { 1298 #if defined(_KERNEL) 1299 return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT); 1300 #else 1301 return b << lfs_sb_getfsbtodb(fs); 1302 #endif 1303 } 1304 /* Diskblocks to frags */ 1305 static __inline uint64_t 1306 LFS_DBTOFSB(STRUCT_LFS *fs, uint64_t b) 1307 { 1308 #if defined(_KERNEL) 1309 return b >> (lfs_sb_getffshift(fs) - DEV_BSHIFT); 1310 #else 1311 return b >> lfs_sb_getfsbtodb(fs); 1312 #endif 1313 } 1314 1315 #define lfs_lblkno(fs, loc) ((loc) >> lfs_sb_getbshift(fs)) 1316 #define lfs_lblktosize(fs, blk) ((blk) << lfs_sb_getbshift(fs)) 1317 1318 /* Frags to bytes */ 1319 static __inline uint64_t 1320 lfs_fsbtob(STRUCT_LFS *fs, uint64_t b) 1321 { 1322 return b << lfs_sb_getffshift(fs); 1323 } 1324 /* Bytes to frags */ 1325 static __inline uint64_t 1326 lfs_btofsb(STRUCT_LFS *fs, uint64_t b) 1327 { 1328 return b >> lfs_sb_getffshift(fs); 1329 } 1330 1331 #define lfs_numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \ 1332 ((loc) >> lfs_sb_getffshift(fs)) 1333 #define lfs_blkroundup(fs, size)/* calculates roundup(size, lfs_sb_getbsize(fs)) */ \ 1334 ((off_t)(((size) + lfs_sb_getbmask(fs)) & (~lfs_sb_getbmask(fs)))) 1335 #define lfs_fragroundup(fs, size)/* calculates roundup(size, fs->lfs_fsize) */ \ 1336 ((off_t)(((size) + lfs_sb_getffmask(fs)) & (~lfs_sb_getffmask(fs)))) 1337 #define lfs_fragstoblks(fs, frags)/* calculates (frags / fs->fs_frag) */ \ 1338 ((frags) >> lfs_sb_getfbshift(fs)) 1339 #define lfs_blkstofrags(fs, blks)/* calculates (blks * fs->fs_frag) */ \ 1340 ((blks) << lfs_sb_getfbshift(fs)) 1341 #define lfs_fragnum(fs, fsb) /* calculates (fsb % fs->lfs_frag) */ \ 1342 ((fsb) & ((fs)->lfs_frag - 1)) 1343 #define lfs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->lfs_frag) */ \ 1344 ((fsb) &~ ((fs)->lfs_frag - 1)) 1345 #define lfs_dblksize(fs, dp, lbn) \ 1346 (((lbn) >= ULFS_NDADDR || lfs_dino_getsize(fs, dp) >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \ 1347 ? lfs_sb_getbsize(fs) \ 1348 : (lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, dp))))) 1349 1350 #define lfs_segsize(fs) (lfs_sb_getversion(fs) == 1 ? \ 1351 lfs_lblktosize((fs), lfs_sb_getssize(fs)) : \ 1352 lfs_sb_getssize(fs)) 1353 /* XXX segtod produces a result in frags despite the 'd' */ 1354 #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg)) 1355 #define lfs_dtosn(fs, daddr) /* block address to segment number */ \ 1356 ((uint32_t)(((daddr) - lfs_sb_gets0addr(fs)) / lfs_segtod((fs), 1))) 1357 #define lfs_sntod(fs, sn) /* segment number to disk address */ \ 1358 ((daddr_t)(lfs_segtod((fs), (sn)) + lfs_sb_gets0addr(fs))) 1359 1360 /* XXX, blah. make this appear only if struct inode is defined */ 1361 #ifdef _UFS_LFS_LFS_INODE_H_ 1362 static __inline uint32_t 1363 lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn) 1364 { 1365 if (lbn >= ULFS_NDADDR || lfs_dino_getsize(fs, ip->i_din) >= (lbn + 1) << lfs_sb_getbshift(fs)) { 1366 return lfs_sb_getbsize(fs); 1367 } else { 1368 return lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, ip->i_din))); 1369 } 1370 } 1371 #endif 1372 1373 /* 1374 * union lfs_blocks 1375 */ 1376 1377 static __inline void 1378 lfs_blocks_fromvoid(STRUCT_LFS *fs, union lfs_blocks *bp, void *p) 1379 { 1380 if (fs->lfs_is64) { 1381 bp->b64 = p; 1382 } else { 1383 bp->b32 = p; 1384 } 1385 } 1386 1387 static __inline void 1388 lfs_blocks_fromfinfo(STRUCT_LFS *fs, union lfs_blocks *bp, FINFO *fip) 1389 { 1390 void *firstblock; 1391 1392 firstblock = (char *)fip + FINFOSIZE(fs); 1393 if (fs->lfs_is64) { 1394 bp->b64 = (int64_t *)firstblock; 1395 } else { 1396 bp->b32 = (int32_t *)firstblock; 1397 } 1398 } 1399 1400 static __inline daddr_t 1401 lfs_blocks_get(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned idx) 1402 { 1403 if (fs->lfs_is64) { 1404 return bp->b64[idx]; 1405 } else { 1406 return bp->b32[idx]; 1407 } 1408 } 1409 1410 static __inline void 1411 lfs_blocks_set(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned idx, daddr_t val) 1412 { 1413 if (fs->lfs_is64) { 1414 bp->b64[idx] = val; 1415 } else { 1416 bp->b32[idx] = val; 1417 } 1418 } 1419 1420 static __inline void 1421 lfs_blocks_inc(STRUCT_LFS *fs, union lfs_blocks *bp) 1422 { 1423 if (fs->lfs_is64) { 1424 bp->b64++; 1425 } else { 1426 bp->b32++; 1427 } 1428 } 1429 1430 static __inline int 1431 lfs_blocks_eq(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2) 1432 { 1433 if (fs->lfs_is64) { 1434 return bp1->b64 == bp2->b64; 1435 } else { 1436 return bp1->b32 == bp2->b32; 1437 } 1438 } 1439 1440 static __inline int 1441 lfs_blocks_sub(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2) 1442 { 1443 /* (remember that the pointers are typed) */ 1444 if (fs->lfs_is64) { 1445 return bp1->b64 - bp2->b64; 1446 } else { 1447 return bp1->b32 - bp2->b32; 1448 } 1449 } 1450 1451 /* 1452 * struct segment 1453 */ 1454 1455 1456 /* 1457 * Macros for determining free space on the disk, with the variable metadata 1458 * of segment summaries and inode blocks taken into account. 1459 */ 1460 /* 1461 * Estimate number of clean blocks not available for writing because 1462 * they will contain metadata or overhead. This is calculated as 1463 * 1464 * E = ((C * M / D) * D + (0) * (T - D)) / T 1465 * or more simply 1466 * E = (C * M) / T 1467 * 1468 * where 1469 * C is the clean space, 1470 * D is the dirty space, 1471 * M is the dirty metadata, and 1472 * T = C + D is the total space on disk. 1473 * 1474 * This approximates the old formula of E = C * M / D when D is close to T, 1475 * but avoids falsely reporting "disk full" when the sample size (D) is small. 1476 */ 1477 #define LFS_EST_CMETA(F) (( \ 1478 (lfs_sb_getdmeta(F) * (int64_t)lfs_sb_getnclean(F)) / \ 1479 (lfs_sb_getnseg(F)))) 1480 1481 /* Estimate total size of the disk not including metadata */ 1482 #define LFS_EST_NONMETA(F) (lfs_sb_getdsize(F) - lfs_sb_getdmeta(F) - LFS_EST_CMETA(F)) 1483 1484 /* Estimate number of blocks actually available for writing */ 1485 #define LFS_EST_BFREE(F) (lfs_sb_getbfree(F) > LFS_EST_CMETA(F) ? \ 1486 lfs_sb_getbfree(F) - LFS_EST_CMETA(F) : 0) 1487 1488 /* Amount of non-meta space not available to mortal man */ 1489 #define LFS_EST_RSVD(F) ((LFS_EST_NONMETA(F) * \ 1490 (uint64_t)lfs_sb_getminfree(F)) / \ 1491 100) 1492 1493 /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */ 1494 #define ISSPACE(F, BB, C) \ 1495 ((((C) == NOCRED || kauth_cred_geteuid(C) == 0) && \ 1496 LFS_EST_BFREE(F) >= (BB)) || \ 1497 (kauth_cred_geteuid(C) != 0 && IS_FREESPACE(F, BB))) 1498 1499 /* Can an ordinary user write BB blocks */ 1500 #define IS_FREESPACE(F, BB) \ 1501 (LFS_EST_BFREE(F) >= (BB) + LFS_EST_RSVD(F)) 1502 1503 /* 1504 * The minimum number of blocks to create a new inode. This is: 1505 * directory direct block (1) + ULFS_NIADDR indirect blocks + inode block (1) + 1506 * ifile direct block (1) + ULFS_NIADDR indirect blocks = 3 + 2 * ULFS_NIADDR blocks. 1507 */ 1508 #define LFS_NRESERVE(F) (lfs_btofsb((F), (2 * ULFS_NIADDR + 3) << lfs_sb_getbshift(F))) 1509 1510 1511 1512 #endif /* _UFS_LFS_LFS_ACCESSORS_H_ */ 1513