1 | /* $NetBSD: lfs_accessors.h,v 1.46 2016/06/20 03:25:46 dholland Exp $ */ |
2 | |
3 | /* from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp */ |
4 | /* from NetBSD: dinode.h,v 1.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 (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 | 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 | } |
291 | } |
292 | |
293 | static __inline uint16_t |
294 | lfs_dir_getreclen(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) |
295 | { |
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 | } |
301 | } |
302 | |
303 | static __inline uint8_t |
304 | lfs_dir_gettype(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) |
305 | { |
306 | if (fs->lfs_is64) { |
307 | KASSERT(fs->lfs_hasolddirfmt == 0); |
308 | return dh->u_64.dh_type; |
309 | } else if (fs->lfs_hasolddirfmt) { |
310 | return LFS_DT_UNKNOWN; |
311 | } else { |
312 | return dh->u_32.dh_type; |
313 | } |
314 | } |
315 | |
316 | static __inline uint8_t |
317 | lfs_dir_getnamlen(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh) |
318 | { |
319 | if (fs->lfs_is64) { |
320 | KASSERT(fs->lfs_hasolddirfmt == 0); |
321 | return dh->u_64.dh_namlen; |
322 | } else if (fs->lfs_hasolddirfmt && LFS_LITTLE_ENDIAN_ONDISK(fs)) { |
323 | /* low-order byte of old 16-bit namlen field */ |
324 | return dh->u_32.dh_type; |
325 | } else { |
326 | return dh->u_32.dh_namlen; |
327 | } |
328 | } |
329 | |
330 | static __inline void |
331 | lfs_dir_setino(STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint64_t ino) |
332 | { |
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 | } |
347 | } |
348 | |
349 | static __inline void |
350 | lfs_dir_setreclen(STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint16_t reclen) |
351 | { |
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 | } |
357 | } |
358 | |
359 | static __inline void |
360 | lfs_dir_settype(const STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint8_t type) |
361 | { |
362 | if (fs->lfs_is64) { |
363 | KASSERT(fs->lfs_hasolddirfmt == 0); |
364 | dh->u_64.dh_type = type; |
365 | } else if (fs->lfs_hasolddirfmt) { |
366 | /* do nothing */ |
367 | return; |
368 | } else { |
369 | dh->u_32.dh_type = type; |
370 | } |
371 | } |
372 | |
373 | static __inline void |
374 | lfs_dir_setnamlen(const STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint8_t namlen) |
375 | { |
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)) { |
380 | /* low-order byte of old 16-bit namlen field */ |
381 | dh->u_32.dh_type = namlen; |
382 | } else { |
383 | dh->u_32.dh_namlen = namlen; |
384 | } |
385 | } |
386 | |
387 | static __inline void |
388 | lfs_copydirname(STRUCT_LFS *fs, char *dest, const char *src, |
389 | unsigned namlen, unsigned reclen) |
390 | { |
391 | unsigned spacelen; |
392 | |
393 | KASSERT(reclen > LFS_DIRHEADERSIZE(fs)); |
394 | spacelen = reclen - LFS_DIRHEADERSIZE(fs); |
395 | |
396 | /* must always be at least 1 byte as a null terminator */ |
397 | KASSERT(spacelen > namlen); |
398 | |
399 | memcpy(dest, src, namlen); |
400 | memset(dest + namlen, '\0', spacelen - namlen); |
401 | } |
402 | |
403 | static __inline LFS_DIRHEADER * |
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 | |
414 | static __inline char * |
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 | |
424 | /* |
425 | * dinodes |
426 | */ |
427 | |
428 | /* |
429 | * Maximum length of a symlink that can be stored within the inode. |
430 | */ |
431 | #define LFS32_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t)) |
432 | #define LFS64_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t)) |
433 | |
434 | #define LFS_MAXSYMLINKLEN(fs) \ |
435 | ((fs)->lfs_is64 ? LFS64_MAXSYMLINKLEN : LFS32_MAXSYMLINKLEN) |
436 | |
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 | |
442 | static __inline void |
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 | |
459 | #define LFS_DEF_DINO_ACCESSOR(type, type32, field) \ |
460 | static __inline type \ |
461 | lfs_dino_get##field(STRUCT_LFS *fs, union lfs_dinode *dip) \ |
462 | { \ |
463 | if (fs->lfs_is64) { \ |
464 | return LFS_SWAP_##type(fs, dip->u_64.di_##field); \ |
465 | } else { \ |
466 | return LFS_SWAP_##type32(fs, dip->u_32.di_##field); \ |
467 | } \ |
468 | } \ |
469 | static __inline void \ |
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; \ |
475 | dip->u_64.di_##field = LFS_SWAP_##type(fs, val); \ |
476 | } else { \ |
477 | type32 *p = &dip->u_32.di_##field; \ |
478 | (void)p; \ |
479 | dip->u_32.di_##field = LFS_SWAP_##type32(fs, val); \ |
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 | |
499 | /* XXX this should be done differently (it's a fake field) */ |
500 | LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, rdev); |
501 | |
502 | static __inline daddr_t |
503 | lfs_dino_getdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) |
504 | { |
505 | KASSERT(ix < ULFS_NDADDR); |
506 | if (fs->lfs_is64) { |
507 | return LFS_SWAP_uint64_t(fs, dip->u_64.di_db[ix]); |
508 | } else { |
509 | /* note: this must sign-extend or UNWRITTEN gets trashed */ |
510 | return (int32_t)LFS_SWAP_uint32_t(fs, dip->u_32.di_db[ix]); |
511 | } |
512 | } |
513 | |
514 | static __inline daddr_t |
515 | lfs_dino_getib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix) |
516 | { |
517 | KASSERT(ix < ULFS_NIADDR); |
518 | if (fs->lfs_is64) { |
519 | return LFS_SWAP_uint64_t(fs, dip->u_64.di_ib[ix]); |
520 | } else { |
521 | /* note: this must sign-extend or UNWRITTEN gets trashed */ |
522 | return (int32_t)LFS_SWAP_uint32_t(fs, dip->u_32.di_ib[ix]); |
523 | } |
524 | } |
525 | |
526 | static __inline void |
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) { |
531 | dip->u_64.di_db[ix] = LFS_SWAP_uint64_t(fs, val); |
532 | } else { |
533 | dip->u_32.di_db[ix] = LFS_SWAP_uint32_t(fs, val); |
534 | } |
535 | } |
536 | |
537 | static __inline void |
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) { |
542 | dip->u_64.di_ib[ix] = LFS_SWAP_uint64_t(fs, val); |
543 | } else { |
544 | dip->u_32.di_ib[ix] = LFS_SWAP_uint32_t(fs, val); |
545 | } |
546 | } |
547 | |
548 | /* birthtime is present only in the 64-bit inode */ |
549 | static __inline void |
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 | |
565 | static __inline daddr_t |
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 | |
579 | static __inline void |
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 | |
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) \ |
679 | panic("lfs: ifile read: segentry %llu: error %d\n", \ |
680 | (unsigned long long)(IN), _e); \ |
681 | if (lfs_sb_getversion(F) == 1) \ |
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 | /* |
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 | |
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 | |
713 | /* Full size of the provided FINFO record, including its block pointers. */ |
714 | #define FINFO_FULLSIZE(fs, fip) \ |
715 | (FINFOSIZE(fs) + lfs_fi_getnblocks(fs, fip) * LFS_BLKPTRSIZE(fs)) |
716 | |
717 | #define NEXT_FINFO(fs, fip) \ |
718 | ((FINFO *)((char *)(fip) + FINFO_FULLSIZE(fs, fip))) |
719 | |
720 | #define LFS_DEF_FI_ACCESSOR(type, type32, field) \ |
721 | static __inline type \ |
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 | } \ |
730 | static __inline void \ |
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 | |
749 | static __inline daddr_t |
750 | lfs_fi_getblock(STRUCT_LFS *fs, FINFO *fip, unsigned idx) |
751 | { |
752 | void *firstblock; |
753 | |
754 | firstblock = (char *)fip + FINFOSIZE(fs); |
755 | KASSERT(idx < lfs_fi_getnblocks(fs, fip)); |
756 | if (fs->lfs_is64) { |
757 | return ((int64_t *)firstblock)[idx]; |
758 | } else { |
759 | return ((int32_t *)firstblock)[idx]; |
760 | } |
761 | } |
762 | |
763 | static __inline void |
764 | lfs_fi_setblock(STRUCT_LFS *fs, FINFO *fip, unsigned idx, daddr_t blk) |
765 | { |
766 | void *firstblock; |
767 | |
768 | firstblock = (char *)fip + FINFOSIZE(fs); |
769 | KASSERT(idx < lfs_fi_getnblocks(fs, fip)); |
770 | if (fs->lfs_is64) { |
771 | ((int64_t *)firstblock)[idx] = blk; |
772 | } else { |
773 | ((int32_t *)firstblock)[idx] = blk; |
774 | } |
775 | } |
776 | |
777 | /* |
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 | |
790 | #define NTH_IINFO(fs, buf, n) \ |
791 | ((IINFO *)((char *)SEGSUM_IINFOSTART(fs, buf) - (n)*IINFOSIZE(fs))) |
792 | |
793 | static __inline uint64_t |
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 | |
803 | static __inline void |
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 | /* |
814 | * Index file inode entries. |
815 | */ |
816 | |
817 | #define IFILE_ENTRYSIZE(fs) \ |
818 | ((fs)->lfs_is64 ? sizeof(IFILE64) : sizeof(IFILE32)) |
819 | |
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); \ |
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 { \ |
840 | (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + \ |
841 | (IN) % lfs_sb_getifpb(F)); \ |
842 | } \ |
843 | UNSHARE_IFLOCK(F); \ |
844 | } while (0) |
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) |
854 | |
855 | #define LFS_DEF_IF_ACCESSOR(type, type32, field) \ |
856 | static __inline type \ |
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 | } \ |
865 | static __inline void \ |
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(uint32_t, uint32_t, version); |
880 | LFS_DEF_IF_ACCESSOR(int64_t, int32_t, daddr); |
881 | LFS_DEF_IF_ACCESSOR(uint64_t, uint32_t, nextfree); |
882 | LFS_DEF_IF_ACCESSOR(uint64_t, uint32_t, atime_sec); |
883 | LFS_DEF_IF_ACCESSOR(uint32_t, uint32_t, atime_nsec); |
884 | |
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) \ |
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) \ |
895 | static __inline type \ |
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 | } \ |
904 | static __inline void \ |
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(uint32_t, uint32_t, clean); |
919 | LFS_DEF_CI_ACCESSOR(uint32_t, uint32_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(uint64_t, uint32_t, free_head); |
923 | LFS_DEF_CI_ACCESSOR(uint64_t, uint32_t, free_tail); |
924 | LFS_DEF_CI_ACCESSOR(uint32_t, uint32_t, flags); |
925 | |
926 | static __inline void |
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 | |
933 | static __inline void |
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 | } |
939 | |
940 | /* Read in the block with the cleaner info from the ifile. */ |
941 | #define LFS_CLEANERINFO(CP, F, BP) do { \ |
942 | int _e; \ |
943 | SHARE_IFLOCK(F); \ |
944 | VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ |
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); \ |
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); \ |
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 - \ |
960 | fs->lfs_favail) { \ |
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); \ |
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 { \ |
980 | if (lfs_sb_getversion(FS) > 1) { \ |
981 | LFS_CLEANERINFO((CIP), (FS), (BP)); \ |
982 | lfs_sb_setfreehd(FS, lfs_ci_getfree_head(FS, CIP)); \ |
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); \ |
990 | if (lfs_sb_getversion(FS) > 1) { \ |
991 | LFS_CLEANERINFO((CIP), (FS), (BP)); \ |
992 | lfs_ci_setfree_head(FS, CIP, VAL); \ |
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)); \ |
1002 | *(FREEP) = lfs_ci_getfree_tail(FS, CIP); \ |
1003 | brelse(BP, 0); \ |
1004 | } while (0) |
1005 | |
1006 | #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \ |
1007 | LFS_CLEANERINFO((CIP), (FS), (BP)); \ |
1008 | lfs_ci_setfree_tail(FS, CIP, VAL); \ |
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 | |
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 |
1030 | static __inline FINFO * |
1031 | segsum_finfobase(STRUCT_LFS *fs, SEGSUM *ssp) |
1032 | { |
1033 | return (FINFO *)((char *)ssp + SEGSUM_SIZE(fs)); |
1034 | } |
1035 | #else |
1036 | #define SEGSUM_FINFOBASE(fs, ssp) \ |
1037 | ((FINFO *)((char *)(ssp) + SEGSUM_SIZE(fs))); |
1038 | #endif |
1039 | |
1040 | #define LFS_DEF_SS_ACCESSOR(type, type32, field) \ |
1041 | static __inline type \ |
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 | } \ |
1050 | static __inline void \ |
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 | |
1076 | static __inline size_t |
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 | |
1093 | static __inline uint32_t |
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 | |
1103 | static __inline void |
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 | |
1113 | |
1114 | /* |
1115 | * Super block. |
1116 | */ |
1117 | |
1118 | /* |
1119 | * Generate accessors for the on-disk superblock fields with cpp. |
1120 | */ |
1121 | |
1122 | #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \ |
1123 | static __inline type \ |
1124 | lfs_sb_get##field(STRUCT_LFS *fs) \ |
1125 | { \ |
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 | } \ |
1131 | } \ |
1132 | static __inline void \ |
1133 | lfs_sb_set##field(STRUCT_LFS *fs, type val) \ |
1134 | { \ |
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 | } \ |
1140 | } \ |
1141 | static __inline void \ |
1142 | lfs_sb_add##field(STRUCT_LFS *fs, type val) \ |
1143 | { \ |
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 | } \ |
1151 | } \ |
1152 | static __inline void \ |
1153 | lfs_sb_sub##field(STRUCT_LFS *fs, type val) \ |
1154 | { \ |
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 | } \ |
1162 | } |
1163 | |
1164 | #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f) |
1165 | |
1166 | #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \ |
1167 | static __inline type \ |
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 | |
1177 | LFS_DEF_SB_ACCESSOR(uint32_t, version); |
1178 | LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, size); |
1179 | LFS_DEF_SB_ACCESSOR(uint32_t, ssize); |
1180 | LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, dsize); |
1181 | LFS_DEF_SB_ACCESSOR(uint32_t, bsize); |
1182 | LFS_DEF_SB_ACCESSOR(uint32_t, fsize); |
1183 | LFS_DEF_SB_ACCESSOR(uint32_t, frag); |
1184 | LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, freehd); |
1185 | LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree); |
1186 | LFS_DEF_SB_ACCESSOR_FULL(uint64_t, uint32_t, nfiles); |
1187 | LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail); |
1188 | LFS_DEF_SB_ACCESSOR(int32_t, uinodes); |
1189 | LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr); |
1190 | LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, ifile, LFS_IFILE_INUM); |
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); |
1196 | LFS_DEF_SB_ACCESSOR(uint32_t, inopf); |
1197 | LFS_DEF_SB_ACCESSOR(uint32_t, minfree); |
1198 | LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize); |
1199 | LFS_DEF_SB_ACCESSOR(uint32_t, fsbpseg); |
1200 | LFS_DEF_SB_ACCESSOR(uint32_t, inopb); |
1201 | LFS_DEF_SB_ACCESSOR(uint32_t, ifpb); |
1202 | LFS_DEF_SB_ACCESSOR(uint32_t, sepb); |
1203 | LFS_DEF_SB_ACCESSOR(uint32_t, nindir); |
1204 | LFS_DEF_SB_ACCESSOR(uint32_t, nseg); |
1205 | LFS_DEF_SB_ACCESSOR(uint32_t, nspf); |
1206 | LFS_DEF_SB_ACCESSOR(uint32_t, cleansz); |
1207 | LFS_DEF_SB_ACCESSOR(uint32_t, segtabsz); |
1208 | LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, segmask, 0); |
1209 | LFS_DEF_SB_ACCESSOR_32ONLY(uint32_t, segshift, 0); |
1210 | LFS_DEF_SB_ACCESSOR(uint64_t, bmask); |
1211 | LFS_DEF_SB_ACCESSOR(uint32_t, bshift); |
1212 | LFS_DEF_SB_ACCESSOR(uint64_t, ffmask); |
1213 | LFS_DEF_SB_ACCESSOR(uint32_t, ffshift); |
1214 | LFS_DEF_SB_ACCESSOR(uint64_t, fbmask); |
1215 | LFS_DEF_SB_ACCESSOR(uint32_t, fbshift); |
1216 | LFS_DEF_SB_ACCESSOR(uint32_t, blktodb); |
1217 | LFS_DEF_SB_ACCESSOR(uint32_t, fsbtodb); |
1218 | LFS_DEF_SB_ACCESSOR(uint32_t, sushift); |
1219 | LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen); |
1220 | LFS_DEF_SB_ACCESSOR(uint32_t, cksum); |
1221 | LFS_DEF_SB_ACCESSOR(uint16_t, pflags); |
1222 | LFS_DEF_SB_ACCESSOR(uint32_t, nclean); |
1223 | LFS_DEF_SB_ACCESSOR(int32_t, dmeta); |
1224 | LFS_DEF_SB_ACCESSOR(uint32_t, minfreeseg); |
1225 | LFS_DEF_SB_ACCESSOR(uint32_t, sumsize); |
1226 | LFS_DEF_SB_ACCESSOR(uint64_t, serial); |
1227 | LFS_DEF_SB_ACCESSOR(uint32_t, ibsize); |
1228 | LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr); |
1229 | LFS_DEF_SB_ACCESSOR(uint64_t, tstamp); |
1230 | LFS_DEF_SB_ACCESSOR(uint32_t, inodefmt); |
1231 | LFS_DEF_SB_ACCESSOR(uint32_t, interleave); |
1232 | LFS_DEF_SB_ACCESSOR(uint32_t, ident); |
1233 | LFS_DEF_SB_ACCESSOR(uint32_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 | */ |
1246 | static __inline int32_t |
1247 | lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n) |
1248 | { |
1249 | #ifdef KASSERT /* ugh */ |
1250 | KASSERT(n < LFS_MAXNUMSB); |
1251 | #endif |
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 | } |
1257 | } |
1258 | static __inline void |
1259 | lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val) |
1260 | { |
1261 | #ifdef KASSERT /* ugh */ |
1262 | KASSERT(n < LFS_MAXNUMSB); |
1263 | #endif |
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 | } |
1269 | } |
1270 | |
1271 | /* |
1272 | * lfs_fsmnt is a string |
1273 | */ |
1274 | static __inline const char * |
1275 | lfs_sb_getfsmnt(STRUCT_LFS *fs) |
1276 | { |
1277 | if (fs->lfs_is64) { |
1278 | return (const char *)fs->lfs_dlfs_u.u_64.dlfs_fsmnt; |
1279 | } else { |
1280 | return (const char *)fs->lfs_dlfs_u.u_32.dlfs_fsmnt; |
1281 | } |
1282 | } |
1283 | |
1284 | static __inline void |
1285 | lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str) |
1286 | { |
1287 | if (fs->lfs_is64) { |
1288 | (void)strncpy((char *)fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str, |
1289 | sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt)); |
1290 | } else { |
1291 | (void)strncpy((char *)fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str, |
1292 | sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt)); |
1293 | } |
1294 | } |
1295 | |
1296 | /* Highest addressable fsb */ |
1297 | #define LFS_MAX_DADDR(fs) \ |
1298 | ((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff) |
1299 | |
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 | |
1312 | /* XXX: lowercase these as they're no longer macros */ |
1313 | /* Frags to diskblocks */ |
1314 | static __inline uint64_t |
1315 | LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b) |
1316 | { |
1317 | #if defined(_KERNEL) |
1318 | return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT); |
1319 | #else |
1320 | return b << lfs_sb_getfsbtodb(fs); |
1321 | #endif |
1322 | } |
1323 | /* Diskblocks to frags */ |
1324 | static __inline uint64_t |
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 | } |
1333 | |
1334 | #define lfs_lblkno(fs, loc) ((loc) >> lfs_sb_getbshift(fs)) |
1335 | #define lfs_lblktosize(fs, blk) ((blk) << lfs_sb_getbshift(fs)) |
1336 | |
1337 | /* Frags to bytes */ |
1338 | static __inline uint64_t |
1339 | lfs_fsbtob(STRUCT_LFS *fs, uint64_t b) |
1340 | { |
1341 | return b << lfs_sb_getffshift(fs); |
1342 | } |
1343 | /* Bytes to frags */ |
1344 | static __inline uint64_t |
1345 | lfs_btofsb(STRUCT_LFS *fs, uint64_t b) |
1346 | { |
1347 | return b >> lfs_sb_getffshift(fs); |
1348 | } |
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) \ |
1365 | (((lbn) >= ULFS_NDADDR || lfs_dino_getsize(fs, dp) >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \ |
1366 | ? lfs_sb_getbsize(fs) \ |
1367 | : (lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, dp))))) |
1368 | |
1369 | #define lfs_segsize(fs) (lfs_sb_getversion(fs) == 1 ? \ |
1370 | lfs_lblktosize((fs), lfs_sb_getssize(fs)) : \ |
1371 | lfs_sb_getssize(fs)) |
1372 | /* XXX segtod produces a result in frags despite the 'd' */ |
1373 | #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg)) |
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 | |
1379 | /* XXX, blah. make this appear only if struct inode is defined */ |
1380 | #ifdef _UFS_LFS_LFS_INODE_H_ |
1381 | static __inline uint32_t |
1382 | lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn) |
1383 | { |
1384 | if (lbn >= ULFS_NDADDR || lfs_dino_getsize(fs, ip->i_din) >= (lbn + 1) << lfs_sb_getbshift(fs)) { |
1385 | return lfs_sb_getbsize(fs); |
1386 | } else { |
1387 | return lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, ip->i_din))); |
1388 | } |
1389 | } |
1390 | #endif |
1391 | |
1392 | /* |
1393 | * union lfs_blocks |
1394 | */ |
1395 | |
1396 | static __inline void |
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 | |
1406 | static __inline void |
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 | |
1419 | static __inline daddr_t |
1420 | lfs_blocks_get(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned idx) |
1421 | { |
1422 | if (fs->lfs_is64) { |
1423 | return bp->b64[idx]; |
1424 | } else { |
1425 | return bp->b32[idx]; |
1426 | } |
1427 | } |
1428 | |
1429 | static __inline void |
1430 | lfs_blocks_set(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned idx, daddr_t val) |
1431 | { |
1432 | if (fs->lfs_is64) { |
1433 | bp->b64[idx] = val; |
1434 | } else { |
1435 | bp->b32[idx] = val; |
1436 | } |
1437 | } |
1438 | |
1439 | static __inline void |
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 | |
1449 | static __inline int |
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 | |
1459 | static __inline int |
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 | |
1474 | |
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 | */ |
1496 | #define LFS_EST_CMETA(F) (( \ |
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 */ |
1508 | #define LFS_EST_RSVD(F) ((LFS_EST_NONMETA(F) * \ |
1509 | (uint64_t)lfs_sb_getminfree(F)) / \ |
1510 | 100) |
1511 | |
1512 | /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */ |
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_ */ |
1532 | |