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