xref: /netbsd-src/sys/ufs/lfs/lfs_accessors.h (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
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