Home | History | Annotate | Line # | Download | only in lfs
lfs_accessors.h revision 1.8
      1 /*	$NetBSD: lfs_accessors.h,v 1.8 2015/08/02 18:18:46 dholland Exp $	*/
      2 
      3 /*  from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp  */
      4 /*  from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp  */
      5 /*  from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp  */
      6 
      7 /*-
      8  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
      9  * All rights reserved.
     10  *
     11  * This code is derived from software contributed to The NetBSD Foundation
     12  * by Konrad E. Schroder <perseant (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 /*
    149  * Maximum length of a symlink that can be stored within the inode.
    150  */
    151 #define ULFS1_MAXSYMLINKLEN	((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t))
    152 #define ULFS2_MAXSYMLINKLEN	((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t))
    153 
    154 #define ULFS_MAXSYMLINKLEN(ip) \
    155 	((ip)->i_ump->um_fstype == ULFS1) ? \
    156 	ULFS1_MAXSYMLINKLEN : ULFS2_MAXSYMLINKLEN
    157 
    158 /*
    159  * "struct buf" associated definitions
    160  */
    161 
    162 # define LFS_LOCK_BUF(bp) do {						\
    163 	if (((bp)->b_flags & B_LOCKED) == 0 && bp->b_iodone == NULL) {	\
    164 		mutex_enter(&lfs_lock);					\
    165 		++locked_queue_count;					\
    166 		locked_queue_bytes += bp->b_bufsize;			\
    167 		mutex_exit(&lfs_lock);					\
    168 	}								\
    169 	(bp)->b_flags |= B_LOCKED;					\
    170 } while (0)
    171 
    172 # define LFS_UNLOCK_BUF(bp) do {					\
    173 	if (((bp)->b_flags & B_LOCKED) != 0 && bp->b_iodone == NULL) {	\
    174 		mutex_enter(&lfs_lock);					\
    175 		--locked_queue_count;					\
    176 		locked_queue_bytes -= bp->b_bufsize;			\
    177 		if (locked_queue_count < LFS_WAIT_BUFS &&		\
    178 		    locked_queue_bytes < LFS_WAIT_BYTES)		\
    179 			cv_broadcast(&locked_queue_cv);			\
    180 		mutex_exit(&lfs_lock);					\
    181 	}								\
    182 	(bp)->b_flags &= ~B_LOCKED;					\
    183 } while (0)
    184 
    185 /*
    186  * "struct inode" associated definitions
    187  */
    188 
    189 #define LFS_SET_UINO(ip, flags) do {					\
    190 	if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED))	\
    191 		lfs_sb_adduinodes((ip)->i_lfs, 1);			\
    192 	if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING))	\
    193 		lfs_sb_adduinodes((ip)->i_lfs, 1);			\
    194 	if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED))	\
    195 		lfs_sb_adduinodes((ip)->i_lfs, 1);			\
    196 	(ip)->i_flag |= (flags);					\
    197 } while (0)
    198 
    199 #define LFS_CLR_UINO(ip, flags) do {					\
    200 	if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED))	\
    201 		lfs_sb_subuinodes((ip)->i_lfs, 1);			\
    202 	if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING))	\
    203 		lfs_sb_subuinodes((ip)->i_lfs, 1);			\
    204 	if (((flags) & IN_MODIFIED) && ((ip)->i_flag & IN_MODIFIED))	\
    205 		lfs_sb_subuinodes((ip)->i_lfs, 1);			\
    206 	(ip)->i_flag &= ~(flags);					\
    207 	if (lfs_sb_getuinodes((ip)->i_lfs) < 0) {			\
    208 		panic("lfs_uinodes < 0");				\
    209 	}								\
    210 } while (0)
    211 
    212 #define LFS_ITIMES(ip, acc, mod, cre) \
    213 	while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
    214 		lfs_itimes(ip, acc, mod, cre)
    215 
    216 /*
    217  * On-disk and in-memory checkpoint segment usage structure.
    218  */
    219 
    220 #define	SEGUPB(fs)	(lfs_sb_getsepb(fs))
    221 #define	SEGTABSIZE_SU(fs)						\
    222 	((lfs_sb_getnseg(fs) + SEGUPB(fs) - 1) / lfs_sb_getsepb(fs))
    223 
    224 #ifdef _KERNEL
    225 # define SHARE_IFLOCK(F) 						\
    226   do {									\
    227 	rw_enter(&(F)->lfs_iflock, RW_READER);				\
    228   } while(0)
    229 # define UNSHARE_IFLOCK(F)						\
    230   do {									\
    231 	rw_exit(&(F)->lfs_iflock);					\
    232   } while(0)
    233 #else /* ! _KERNEL */
    234 # define SHARE_IFLOCK(F)
    235 # define UNSHARE_IFLOCK(F)
    236 #endif /* ! _KERNEL */
    237 
    238 /* Read in the block with a specific segment usage entry from the ifile. */
    239 #define	LFS_SEGENTRY(SP, F, IN, BP) do {				\
    240 	int _e;								\
    241 	SHARE_IFLOCK(F);						\
    242 	VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;			\
    243 	if ((_e = bread((F)->lfs_ivnode,				\
    244 	    ((IN) / lfs_sb_getsepb(F)) + lfs_sb_getcleansz(F),		\
    245 	    lfs_sb_getbsize(F), 0, &(BP))) != 0)			\
    246 		panic("lfs: ifile read: %d", _e);			\
    247 	if (lfs_sb_getversion(F) == 1)					\
    248 		(SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data +		\
    249 			((IN) & (lfs_sb_getsepb(F) - 1)));		\
    250 	else								\
    251 		(SP) = (SEGUSE *)(BP)->b_data + ((IN) % lfs_sb_getsepb(F)); \
    252 	UNSHARE_IFLOCK(F);						\
    253 } while (0)
    254 
    255 #define LFS_WRITESEGENTRY(SP, F, IN, BP) do {				\
    256 	if ((SP)->su_nbytes == 0)					\
    257 		(SP)->su_flags |= SEGUSE_EMPTY;				\
    258 	else								\
    259 		(SP)->su_flags &= ~SEGUSE_EMPTY;			\
    260 	(F)->lfs_suflags[(F)->lfs_activesb][(IN)] = (SP)->su_flags;	\
    261 	LFS_BWRITE_LOG(BP);						\
    262 } while (0)
    263 
    264 /*
    265  * Index file inode entries.
    266  */
    267 
    268 /*
    269  * LFSv1 compatibility code is not allowed to touch if_atime, since it
    270  * may not be mapped!
    271  */
    272 /* Read in the block with a specific inode from the ifile. */
    273 #define	LFS_IENTRY(IP, F, IN, BP) do {					\
    274 	int _e;								\
    275 	SHARE_IFLOCK(F);						\
    276 	VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;			\
    277 	if ((_e = bread((F)->lfs_ivnode,				\
    278 	(IN) / lfs_sb_getifpb(F) + lfs_sb_getcleansz(F) + lfs_sb_getsegtabsz(F), \
    279 	lfs_sb_getbsize(F), 0, &(BP))) != 0)				\
    280 		panic("lfs: ifile ino %d read %d", (int)(IN), _e);	\
    281 	if (lfs_sb_getversion(F) == 1)					\
    282 		(IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data +		\
    283 				 (IN) % lfs_sb_getifpb(F));		\
    284 	else								\
    285 		(IP) = (IFILE *)(BP)->b_data + (IN) % lfs_sb_getifpb(F); \
    286 	UNSHARE_IFLOCK(F);						\
    287 } while (0)
    288 
    289 /*
    290  * Cleaner information structure.  This resides in the ifile and is used
    291  * to pass information from the kernel to the cleaner.
    292  */
    293 
    294 #define	CLEANSIZE_SU(fs)						\
    295 	((sizeof(CLEANERINFO) + lfs_sb_getbsize(fs) - 1) >> lfs_sb_getbshift(fs))
    296 
    297 /* Read in the block with the cleaner info from the ifile. */
    298 #define LFS_CLEANERINFO(CP, F, BP) do {					\
    299 	SHARE_IFLOCK(F);						\
    300 	VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;			\
    301 	if (bread((F)->lfs_ivnode,					\
    302 	    (daddr_t)0, lfs_sb_getbsize(F), 0, &(BP)))			\
    303 		panic("lfs: ifile read");				\
    304 	(CP) = (CLEANERINFO *)(BP)->b_data;				\
    305 	UNSHARE_IFLOCK(F);						\
    306 } while (0)
    307 
    308 /*
    309  * Synchronize the Ifile cleaner info with current avail and bfree.
    310  */
    311 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do {		 	\
    312     mutex_enter(&lfs_lock);						\
    313     if ((w) || (cip)->bfree != lfs_sb_getbfree(fs) ||		 	\
    314 	(cip)->avail != lfs_sb_getavail(fs) - fs->lfs_ravail -	 	\
    315 	fs->lfs_favail) {	 					\
    316 	(cip)->bfree = lfs_sb_getbfree(fs);			 	\
    317 	(cip)->avail = lfs_sb_getavail(fs) - fs->lfs_ravail -		\
    318 		fs->lfs_favail;					 	\
    319 	if (((bp)->b_flags & B_GATHERED) == 0) {		 	\
    320 		fs->lfs_flags |= LFS_IFDIRTY;				\
    321 	}								\
    322 	mutex_exit(&lfs_lock);						\
    323 	(void) LFS_BWRITE_LOG(bp); /* Ifile */			 	\
    324     } else {							 	\
    325 	mutex_exit(&lfs_lock);						\
    326 	brelse(bp, 0);						 	\
    327     }									\
    328 } while (0)
    329 
    330 /*
    331  * Get the head of the inode free list.
    332  * Always called with the segment lock held.
    333  */
    334 #define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do {			\
    335 	if (lfs_sb_getversion(FS) > 1) {				\
    336 		LFS_CLEANERINFO((CIP), (FS), (BP));			\
    337 		lfs_sb_setfreehd(FS, (CIP)->free_head);			\
    338 		brelse(BP, 0);						\
    339 	}								\
    340 	*(FREEP) = lfs_sb_getfreehd(FS);				\
    341 } while (0)
    342 
    343 #define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do {				\
    344 	lfs_sb_setfreehd(FS, VAL);					\
    345 	if (lfs_sb_getversion(FS) > 1) {				\
    346 		LFS_CLEANERINFO((CIP), (FS), (BP));			\
    347 		(CIP)->free_head = (VAL);				\
    348 		LFS_BWRITE_LOG(BP);					\
    349 		mutex_enter(&lfs_lock);					\
    350 		(FS)->lfs_flags |= LFS_IFDIRTY;				\
    351 		mutex_exit(&lfs_lock);					\
    352 	}								\
    353 } while (0)
    354 
    355 #define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do {			\
    356 	LFS_CLEANERINFO((CIP), (FS), (BP));				\
    357 	*(FREEP) = (CIP)->free_tail;					\
    358 	brelse(BP, 0);							\
    359 } while (0)
    360 
    361 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do {				\
    362 	LFS_CLEANERINFO((CIP), (FS), (BP));				\
    363 	(CIP)->free_tail = (VAL);					\
    364 	LFS_BWRITE_LOG(BP);						\
    365 	mutex_enter(&lfs_lock);						\
    366 	(FS)->lfs_flags |= LFS_IFDIRTY;					\
    367 	mutex_exit(&lfs_lock);						\
    368 } while (0)
    369 
    370 /*
    371  * On-disk segment summary information
    372  */
    373 
    374 #define SEGSUM_SIZE(fs) (lfs_sb_getversion(fs) == 1 ? sizeof(SEGSUM_V1) : sizeof(SEGSUM))
    375 
    376 /*
    377  * Super block.
    378  */
    379 
    380 /*
    381  * Generate accessors for the on-disk superblock fields with cpp.
    382  *
    383  * STRUCT_LFS is used by the libsa code to get accessors that work
    384  * with struct salfs instead of struct lfs.
    385  */
    386 
    387 #ifndef STRUCT_LFS
    388 #define STRUCT_LFS struct lfs
    389 #endif
    390 
    391 #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \
    392 	static __unused inline type				\
    393 	lfs_sb_get##field(STRUCT_LFS *fs)			\
    394 	{							\
    395 		if (fs->lfs_is64) {				\
    396 			return fs->lfs_dlfs_u.u_64.dlfs_##field; \
    397 		} else {					\
    398 			return fs->lfs_dlfs_u.u_32.dlfs_##field; \
    399 		}						\
    400 	}							\
    401 	static __unused inline void				\
    402 	lfs_sb_set##field(STRUCT_LFS *fs, type val)		\
    403 	{							\
    404 		if (fs->lfs_is64) {				\
    405 			fs->lfs_dlfs_u.u_64.dlfs_##field = val;	\
    406 		} else {					\
    407 			fs->lfs_dlfs_u.u_32.dlfs_##field = val;	\
    408 		}						\
    409 	}							\
    410 	static __unused inline void				\
    411 	lfs_sb_add##field(STRUCT_LFS *fs, type val)		\
    412 	{							\
    413 		if (fs->lfs_is64) {				\
    414 			type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
    415 			*p64 += val;				\
    416 		} else {					\
    417 			type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
    418 			*p32 += val;				\
    419 		}						\
    420 	}							\
    421 	static __unused inline void				\
    422 	lfs_sb_sub##field(STRUCT_LFS *fs, type val)		\
    423 	{							\
    424 		if (fs->lfs_is64) {				\
    425 			type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
    426 			*p64 -= val;				\
    427 		} else {					\
    428 			type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
    429 			*p32 -= val;				\
    430 		}						\
    431 	}
    432 
    433 #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f)
    434 
    435 #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \
    436 	static __unused inline type				\
    437 	lfs_sb_get##field(STRUCT_LFS *fs)			\
    438 	{							\
    439 		if (fs->lfs_is64) {				\
    440 			return val64;				\
    441 		} else {					\
    442 			return fs->lfs_dlfs_u.u_32.dlfs_##field; \
    443 		}						\
    444 	}
    445 
    446 #define lfs_magic lfs_dlfs.dlfs_magic
    447 LFS_DEF_SB_ACCESSOR(u_int32_t, version);
    448 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, size);
    449 LFS_DEF_SB_ACCESSOR(u_int32_t, ssize);
    450 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, dsize);
    451 LFS_DEF_SB_ACCESSOR(u_int32_t, bsize);
    452 LFS_DEF_SB_ACCESSOR(u_int32_t, fsize);
    453 LFS_DEF_SB_ACCESSOR(u_int32_t, frag);
    454 LFS_DEF_SB_ACCESSOR(u_int32_t, freehd);
    455 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree);
    456 LFS_DEF_SB_ACCESSOR(u_int32_t, nfiles);
    457 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail);
    458 LFS_DEF_SB_ACCESSOR(int32_t, uinodes);
    459 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr);
    460 LFS_DEF_SB_ACCESSOR(u_int32_t, ifile);
    461 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastseg);
    462 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, nextseg);
    463 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, curseg);
    464 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, offset);
    465 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastpseg);
    466 LFS_DEF_SB_ACCESSOR(u_int32_t, inopf);
    467 LFS_DEF_SB_ACCESSOR(u_int32_t, minfree);
    468 LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize);
    469 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbpseg);
    470 LFS_DEF_SB_ACCESSOR(u_int32_t, inopb);
    471 LFS_DEF_SB_ACCESSOR(u_int32_t, ifpb);
    472 LFS_DEF_SB_ACCESSOR(u_int32_t, sepb);
    473 LFS_DEF_SB_ACCESSOR(u_int32_t, nindir);
    474 LFS_DEF_SB_ACCESSOR(u_int32_t, nseg);
    475 LFS_DEF_SB_ACCESSOR(u_int32_t, nspf);
    476 LFS_DEF_SB_ACCESSOR(u_int32_t, cleansz);
    477 LFS_DEF_SB_ACCESSOR(u_int32_t, segtabsz);
    478 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segmask, 0);
    479 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segshift, 0);
    480 LFS_DEF_SB_ACCESSOR(u_int64_t, bmask);
    481 LFS_DEF_SB_ACCESSOR(u_int32_t, bshift);
    482 LFS_DEF_SB_ACCESSOR(u_int64_t, ffmask);
    483 LFS_DEF_SB_ACCESSOR(u_int32_t, ffshift);
    484 LFS_DEF_SB_ACCESSOR(u_int64_t, fbmask);
    485 LFS_DEF_SB_ACCESSOR(u_int32_t, fbshift);
    486 LFS_DEF_SB_ACCESSOR(u_int32_t, blktodb);
    487 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbtodb);
    488 LFS_DEF_SB_ACCESSOR(u_int32_t, sushift);
    489 LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen);
    490 LFS_DEF_SB_ACCESSOR(u_int32_t, cksum);
    491 LFS_DEF_SB_ACCESSOR(u_int16_t, pflags);
    492 LFS_DEF_SB_ACCESSOR(u_int32_t, nclean);
    493 LFS_DEF_SB_ACCESSOR(int32_t, dmeta);
    494 LFS_DEF_SB_ACCESSOR(u_int32_t, minfreeseg);
    495 LFS_DEF_SB_ACCESSOR(u_int32_t, sumsize);
    496 LFS_DEF_SB_ACCESSOR(u_int64_t, serial);
    497 LFS_DEF_SB_ACCESSOR(u_int32_t, ibsize);
    498 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr);
    499 LFS_DEF_SB_ACCESSOR(u_int64_t, tstamp);
    500 LFS_DEF_SB_ACCESSOR(u_int32_t, inodefmt);
    501 LFS_DEF_SB_ACCESSOR(u_int32_t, interleave);
    502 LFS_DEF_SB_ACCESSOR(u_int32_t, ident);
    503 LFS_DEF_SB_ACCESSOR(u_int32_t, resvseg);
    504 
    505 /* special-case accessors */
    506 
    507 /*
    508  * the v1 otstamp field lives in what's now dlfs_inopf
    509  */
    510 #define lfs_sb_getotstamp(fs) lfs_sb_getinopf(fs)
    511 #define lfs_sb_setotstamp(fs, val) lfs_sb_setinopf(fs, val)
    512 
    513 /*
    514  * lfs_sboffs is an array
    515  */
    516 static __unused inline int32_t
    517 lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n)
    518 {
    519 #ifdef KASSERT /* ugh */
    520 	KASSERT(n < LFS_MAXNUMSB);
    521 #endif
    522 	if (fs->lfs_is64) {
    523 		return fs->lfs_dlfs_u.u_64.dlfs_sboffs[n];
    524 	} else {
    525 		return fs->lfs_dlfs_u.u_32.dlfs_sboffs[n];
    526 	}
    527 }
    528 static __unused inline void
    529 lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val)
    530 {
    531 #ifdef KASSERT /* ugh */
    532 	KASSERT(n < LFS_MAXNUMSB);
    533 #endif
    534 	if (fs->lfs_is64) {
    535 		fs->lfs_dlfs_u.u_64.dlfs_sboffs[n] = val;
    536 	} else {
    537 		fs->lfs_dlfs_u.u_32.dlfs_sboffs[n] = val;
    538 	}
    539 }
    540 
    541 /*
    542  * lfs_fsmnt is a string
    543  */
    544 static __unused inline const char *
    545 lfs_sb_getfsmnt(STRUCT_LFS *fs)
    546 {
    547 	if (fs->lfs_is64) {
    548 		return fs->lfs_dlfs_u.u_64.dlfs_fsmnt;
    549 	} else {
    550 		return fs->lfs_dlfs_u.u_32.dlfs_fsmnt;
    551 	}
    552 }
    553 
    554 static __unused inline void
    555 lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str)
    556 {
    557 	if (fs->lfs_is64) {
    558 		(void)strncpy(fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str,
    559 			sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt));
    560 	} else {
    561 		(void)strncpy(fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str,
    562 			sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt));
    563 	}
    564 }
    565 
    566 /* Highest addressable fsb */
    567 #define LFS_MAX_DADDR(fs) \
    568 	((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff)
    569 
    570 /* LFS_NINDIR is the number of indirects in a file system block. */
    571 #define	LFS_NINDIR(fs)	(lfs_sb_getnindir(fs))
    572 
    573 /* LFS_INOPB is the number of inodes in a secondary storage block. */
    574 #define	LFS_INOPB(fs)	(lfs_sb_getinopb(fs))
    575 /* LFS_INOPF is the number of inodes in a fragment. */
    576 #define LFS_INOPF(fs)	(lfs_sb_getinopf(fs))
    577 
    578 #define	lfs_blkoff(fs, loc)	((int)((loc) & lfs_sb_getbmask(fs)))
    579 #define lfs_fragoff(fs, loc)    /* calculates (loc % fs->lfs_fsize) */ \
    580     ((int)((loc) & lfs_sb_getffmask(fs)))
    581 
    582 /* XXX: lowercase these as they're no longer macros */
    583 /* Frags to diskblocks */
    584 static __unused inline uint64_t
    585 LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b)
    586 {
    587 #if defined(_KERNEL)
    588 	return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT);
    589 #else
    590 	return b << lfs_sb_getfsbtodb(fs);
    591 #endif
    592 }
    593 /* Diskblocks to frags */
    594 static __unused inline uint64_t
    595 LFS_DBTOFSB(STRUCT_LFS *fs, uint64_t b)
    596 {
    597 #if defined(_KERNEL)
    598 	return b >> (lfs_sb_getffshift(fs) - DEV_BSHIFT);
    599 #else
    600 	return b >> lfs_sb_getfsbtodb(fs);
    601 #endif
    602 }
    603 
    604 #define	lfs_lblkno(fs, loc)	((loc) >> lfs_sb_getbshift(fs))
    605 #define	lfs_lblktosize(fs, blk)	((blk) << lfs_sb_getbshift(fs))
    606 
    607 /* Frags to bytes */
    608 static __unused inline uint64_t
    609 lfs_fsbtob(STRUCT_LFS *fs, uint64_t b)
    610 {
    611 	return b << lfs_sb_getffshift(fs);
    612 }
    613 /* Bytes to frags */
    614 static __unused inline uint64_t
    615 lfs_btofsb(STRUCT_LFS *fs, uint64_t b)
    616 {
    617 	return b >> lfs_sb_getffshift(fs);
    618 }
    619 
    620 #define lfs_numfrags(fs, loc)	/* calculates (loc / fs->lfs_fsize) */	\
    621 	((loc) >> lfs_sb_getffshift(fs))
    622 #define lfs_blkroundup(fs, size)/* calculates roundup(size, lfs_sb_getbsize(fs)) */ \
    623 	((off_t)(((size) + lfs_sb_getbmask(fs)) & (~lfs_sb_getbmask(fs))))
    624 #define lfs_fragroundup(fs, size)/* calculates roundup(size, fs->lfs_fsize) */ \
    625 	((off_t)(((size) + lfs_sb_getffmask(fs)) & (~lfs_sb_getffmask(fs))))
    626 #define lfs_fragstoblks(fs, frags)/* calculates (frags / fs->fs_frag) */ \
    627 	((frags) >> lfs_sb_getfbshift(fs))
    628 #define lfs_blkstofrags(fs, blks)/* calculates (blks * fs->fs_frag) */ \
    629 	((blks) << lfs_sb_getfbshift(fs))
    630 #define lfs_fragnum(fs, fsb)	/* calculates (fsb % fs->lfs_frag) */	\
    631 	((fsb) & ((fs)->lfs_frag - 1))
    632 #define lfs_blknum(fs, fsb)	/* calculates rounddown(fsb, fs->lfs_frag) */ \
    633 	((fsb) &~ ((fs)->lfs_frag - 1))
    634 #define lfs_dblksize(fs, dp, lbn) \
    635 	(((lbn) >= ULFS_NDADDR || (dp)->di_size >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \
    636 	    ? lfs_sb_getbsize(fs) \
    637 	    : (lfs_fragroundup(fs, lfs_blkoff(fs, (dp)->di_size))))
    638 
    639 #define	lfs_segsize(fs)	(lfs_sb_getversion(fs) == 1 ?	     		\
    640 			   lfs_lblktosize((fs), lfs_sb_getssize(fs)) :	\
    641 			   lfs_sb_getssize(fs))
    642 /* XXX segtod produces a result in frags despite the 'd' */
    643 #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg))
    644 #define	lfs_dtosn(fs, daddr)	/* block address to segment number */	\
    645 	((uint32_t)(((daddr) - lfs_sb_gets0addr(fs)) / lfs_segtod((fs), 1)))
    646 #define lfs_sntod(fs, sn)	/* segment number to disk address */	\
    647 	((daddr_t)(lfs_segtod((fs), (sn)) + lfs_sb_gets0addr(fs)))
    648 
    649 /* XXX, blah. make this appear only if struct inode is defined */
    650 #ifdef _UFS_LFS_LFS_INODE_H_
    651 static __unused inline uint32_t
    652 lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn)
    653 {
    654 	if (lbn >= ULFS_NDADDR || ip->i_ffs1_size >= (lbn + 1) << lfs_sb_getbshift(fs)) {
    655 		return lfs_sb_getbsize(fs);
    656 	} else {
    657 		return lfs_fragroundup(fs, lfs_blkoff(fs, ip->i_ffs1_size));
    658 	}
    659 }
    660 #endif
    661 
    662 
    663 /*
    664  * Macros for determining free space on the disk, with the variable metadata
    665  * of segment summaries and inode blocks taken into account.
    666  */
    667 /*
    668  * Estimate number of clean blocks not available for writing because
    669  * they will contain metadata or overhead.  This is calculated as
    670  *
    671  *		E = ((C * M / D) * D + (0) * (T - D)) / T
    672  * or more simply
    673  *		E = (C * M) / T
    674  *
    675  * where
    676  * C is the clean space,
    677  * D is the dirty space,
    678  * M is the dirty metadata, and
    679  * T = C + D is the total space on disk.
    680  *
    681  * This approximates the old formula of E = C * M / D when D is close to T,
    682  * but avoids falsely reporting "disk full" when the sample size (D) is small.
    683  */
    684 #define LFS_EST_CMETA(F) (int32_t)((					\
    685 	(lfs_sb_getdmeta(F) * (int64_t)lfs_sb_getnclean(F)) / 		\
    686 	(lfs_sb_getnseg(F))))
    687 
    688 /* Estimate total size of the disk not including metadata */
    689 #define LFS_EST_NONMETA(F) (lfs_sb_getdsize(F) - lfs_sb_getdmeta(F) - LFS_EST_CMETA(F))
    690 
    691 /* Estimate number of blocks actually available for writing */
    692 #define LFS_EST_BFREE(F) (lfs_sb_getbfree(F) > LFS_EST_CMETA(F) ?	     \
    693 			  lfs_sb_getbfree(F) - LFS_EST_CMETA(F) : 0)
    694 
    695 /* Amount of non-meta space not available to mortal man */
    696 #define LFS_EST_RSVD(F) (int32_t)((LFS_EST_NONMETA(F) *			     \
    697 				   (u_int64_t)lfs_sb_getminfree(F)) /	     \
    698 				  100)
    699 
    700 /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */
    701 #define ISSPACE(F, BB, C)						\
    702 	((((C) == NOCRED || kauth_cred_geteuid(C) == 0) &&		\
    703 	  LFS_EST_BFREE(F) >= (BB)) ||					\
    704 	 (kauth_cred_geteuid(C) != 0 && IS_FREESPACE(F, BB)))
    705 
    706 /* Can an ordinary user write BB blocks */
    707 #define IS_FREESPACE(F, BB)						\
    708 	  (LFS_EST_BFREE(F) >= (BB) + LFS_EST_RSVD(F))
    709 
    710 /*
    711  * The minimum number of blocks to create a new inode.  This is:
    712  * directory direct block (1) + ULFS_NIADDR indirect blocks + inode block (1) +
    713  * ifile direct block (1) + ULFS_NIADDR indirect blocks = 3 + 2 * ULFS_NIADDR blocks.
    714  */
    715 #define LFS_NRESERVE(F) (lfs_btofsb((F), (2 * ULFS_NIADDR + 3) << lfs_sb_getbshift(F)))
    716 
    717 
    718 
    719 #endif /* _UFS_LFS_LFS_ACCESSORS_H_ */
    720