Home | History | Annotate | Line # | Download | only in lfs
lfs_accessors.h revision 1.49
      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 (at) 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