lfs_accessors.h revision 1.16 1 /* $NetBSD: lfs_accessors.h,v 1.16 2015/09/01 06:08:37 dholland Exp $ */
2
3 /* from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp */
4 /* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */
5 /* from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp */
6
7 /*-
8 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
9 * All rights reserved.
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Konrad E. Schroder <perseant (at) hhhh.org>.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35 /*-
36 * Copyright (c) 1991, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)lfs.h 8.9 (Berkeley) 5/8/95
64 */
65 /*
66 * Copyright (c) 2002 Networks Associates Technology, Inc.
67 * All rights reserved.
68 *
69 * This software was developed for the FreeBSD Project by Marshall
70 * Kirk McKusick and Network Associates Laboratories, the Security
71 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
72 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
73 * research program
74 *
75 * Copyright (c) 1982, 1989, 1993
76 * The Regents of the University of California. All rights reserved.
77 * (c) UNIX System Laboratories, Inc.
78 * All or some portions of this file are derived from material licensed
79 * to the University of California by American Telephone and Telegraph
80 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81 * the permission of UNIX System Laboratories, Inc.
82 *
83 * Redistribution and use in source and binary forms, with or without
84 * modification, are permitted provided that the following conditions
85 * are met:
86 * 1. Redistributions of source code must retain the above copyright
87 * notice, this list of conditions and the following disclaimer.
88 * 2. Redistributions in binary form must reproduce the above copyright
89 * notice, this list of conditions and the following disclaimer in the
90 * documentation and/or other materials provided with the distribution.
91 * 3. Neither the name of the University nor the names of its contributors
92 * may be used to endorse or promote products derived from this software
93 * without specific prior written permission.
94 *
95 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105 * SUCH DAMAGE.
106 *
107 * @(#)dinode.h 8.9 (Berkeley) 3/29/95
108 */
109 /*
110 * Copyright (c) 1982, 1986, 1989, 1993
111 * The Regents of the University of California. All rights reserved.
112 * (c) UNIX System Laboratories, Inc.
113 * All or some portions of this file are derived from material licensed
114 * to the University of California by American Telephone and Telegraph
115 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
116 * the permission of UNIX System Laboratories, Inc.
117 *
118 * Redistribution and use in source and binary forms, with or without
119 * modification, are permitted provided that the following conditions
120 * are met:
121 * 1. Redistributions of source code must retain the above copyright
122 * notice, this list of conditions and the following disclaimer.
123 * 2. Redistributions in binary form must reproduce the above copyright
124 * notice, this list of conditions and the following disclaimer in the
125 * documentation and/or other materials provided with the distribution.
126 * 3. Neither the name of the University nor the names of its contributors
127 * may be used to endorse or promote products derived from this software
128 * without specific prior written permission.
129 *
130 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
131 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
132 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
133 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
134 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
135 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
136 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
137 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
138 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
139 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
140 * SUCH DAMAGE.
141 *
142 * @(#)dir.h 8.5 (Berkeley) 4/27/95
143 */
144
145 #ifndef _UFS_LFS_LFS_ACCESSORS_H_
146 #define _UFS_LFS_LFS_ACCESSORS_H_
147
148 #if !defined(_KERNEL) && !defined(_STANDALONE)
149 #include <assert.h>
150 #define KASSERT assert
151 #endif
152
153 /*
154 * STRUCT_LFS is used by the libsa code to get accessors that work
155 * with struct salfs instead of struct lfs, and by the cleaner to
156 * get accessors that work with struct clfs.
157 */
158
159 #ifndef STRUCT_LFS
160 #define STRUCT_LFS struct lfs
161 #endif
162
163 /*
164 * dinodes
165 */
166
167 /*
168 * Maximum length of a symlink that can be stored within the inode.
169 */
170 #define ULFS1_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t))
171 #define ULFS2_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t))
172
173 #define ULFS_MAXSYMLINKLEN(ip) \
174 ((ip)->i_ump->um_fstype == ULFS1) ? \
175 ULFS1_MAXSYMLINKLEN : ULFS2_MAXSYMLINKLEN
176
177 #define DINOSIZE(fs) ((fs)->lfs_is64 ? sizeof(struct lfs64_dinode) : sizeof(struct lfs32_dinode))
178
179 #define DINO_IN_BLOCK(fs, base, ix) \
180 ((union lfs_dinode *)((char *)(base) + DINOSIZE(fs) * (ix)))
181
182 static __unused inline void
183 lfs_copy_dinode(STRUCT_LFS *fs,
184 union lfs_dinode *dst, const union lfs_dinode *src)
185 {
186 /*
187 * We can do structure assignment of the structs, but not of
188 * the whole union, as the union is the size of the (larger)
189 * 64-bit struct and on a 32-bit fs the upper half of it might
190 * be off the end of a buffer or otherwise invalid.
191 */
192 if (fs->lfs_is64) {
193 dst->u_64 = src->u_64;
194 } else {
195 dst->u_32 = src->u_32;
196 }
197 }
198
199 #define LFS_DEF_DINO_ACCESSOR(type, type32, field) \
200 static __unused inline type \
201 lfs_dino_get##field(STRUCT_LFS *fs, union lfs_dinode *dip) \
202 { \
203 if (fs->lfs_is64) { \
204 return dip->u_64.di_##field; \
205 } else { \
206 return dip->u_32.di_##field; \
207 } \
208 } \
209 static __unused inline void \
210 lfs_dino_set##field(STRUCT_LFS *fs, union lfs_dinode *dip, type val) \
211 { \
212 if (fs->lfs_is64) { \
213 type *p = &dip->u_64.di_##field; \
214 (void)p; \
215 dip->u_64.di_##field = val; \
216 } else { \
217 type32 *p = &dip->u_32.di_##field; \
218 (void)p; \
219 dip->u_32.di_##field = val; \
220 } \
221 } \
222
223 LFS_DEF_DINO_ACCESSOR(uint16_t, uint16_t, mode);
224 LFS_DEF_DINO_ACCESSOR(int16_t, int16_t, nlink);
225 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, inumber);
226 LFS_DEF_DINO_ACCESSOR(uint64_t, uint64_t, size);
227 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, atime);
228 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, atimensec);
229 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, mtime);
230 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, mtimensec);
231 LFS_DEF_DINO_ACCESSOR(int64_t, int32_t, ctime);
232 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, ctimensec);
233 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, flags);
234 LFS_DEF_DINO_ACCESSOR(uint64_t, uint32_t, blocks);
235 LFS_DEF_DINO_ACCESSOR(int32_t, int32_t, gen);
236 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, uid);
237 LFS_DEF_DINO_ACCESSOR(uint32_t, uint32_t, gid);
238
239 /* XXX this should be done differently (it's a fake field) */
240 LFS_DEF_DINO_ACCESSOR(uint64_t, int32_t, rdev);
241
242 static __unused inline daddr_t
243 lfs_dino_getdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix)
244 {
245 KASSERT(ix < ULFS_NDADDR);
246 if (fs->lfs_is64) {
247 return dip->u_64.di_db[ix];
248 } else {
249 return dip->u_32.di_db[ix];
250 }
251 }
252
253 static __unused inline daddr_t
254 lfs_dino_getib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix)
255 {
256 KASSERT(ix < ULFS_NIADDR);
257 if (fs->lfs_is64) {
258 return dip->u_64.di_ib[ix];
259 } else {
260 return dip->u_32.di_ib[ix];
261 }
262 }
263
264 static __unused inline void
265 lfs_dino_setdb(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val)
266 {
267 KASSERT(ix < ULFS_NDADDR);
268 if (fs->lfs_is64) {
269 dip->u_64.di_db[ix] = val;
270 } else {
271 dip->u_32.di_db[ix] = val;
272 }
273 }
274
275 static __unused inline void
276 lfs_dino_setib(STRUCT_LFS *fs, union lfs_dinode *dip, unsigned ix, daddr_t val)
277 {
278 KASSERT(ix < ULFS_NIADDR);
279 if (fs->lfs_is64) {
280 dip->u_64.di_ib[ix] = val;
281 } else {
282 dip->u_32.di_ib[ix] = val;
283 }
284 }
285
286 /* birthtime is present only in the 64-bit inode */
287 static __unused inline void
288 lfs_dino_setbirthtime(STRUCT_LFS *fs, union lfs_dinode *dip,
289 const struct timespec *ts)
290 {
291 if (fs->lfs_is64) {
292 dip->u_64.di_birthtime = ts->tv_sec;
293 dip->u_64.di_birthnsec = ts->tv_nsec;
294 } else {
295 /* drop it on the floor */
296 }
297 }
298
299 /*
300 * indirect blocks
301 */
302
303 static __unused inline daddr_t
304 lfs_iblock_get(STRUCT_LFS *fs, void *block, unsigned ix)
305 {
306 if (fs->lfs_is64) {
307 // XXX re-enable these asserts after reorging this file
308 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t));
309 return (daddr_t)(((int64_t *)block)[ix]);
310 } else {
311 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t));
312 /* must sign-extend or UNWRITTEN gets trashed */
313 return (daddr_t)(int64_t)(((int32_t *)block)[ix]);
314 }
315 }
316
317 static __unused inline void
318 lfs_iblock_set(STRUCT_LFS *fs, void *block, unsigned ix, daddr_t val)
319 {
320 if (fs->lfs_is64) {
321 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int64_t));
322 ((int64_t *)block)[ix] = val;
323 } else {
324 //KASSERT(ix < lfs_sb_getbsize(fs) / sizeof(int32_t));
325 ((int32_t *)block)[ix] = val;
326 }
327 }
328
329 /*
330 * "struct buf" associated definitions
331 */
332
333 # define LFS_LOCK_BUF(bp) do { \
334 if (((bp)->b_flags & B_LOCKED) == 0 && bp->b_iodone == NULL) { \
335 mutex_enter(&lfs_lock); \
336 ++locked_queue_count; \
337 locked_queue_bytes += bp->b_bufsize; \
338 mutex_exit(&lfs_lock); \
339 } \
340 (bp)->b_flags |= B_LOCKED; \
341 } while (0)
342
343 # define LFS_UNLOCK_BUF(bp) do { \
344 if (((bp)->b_flags & B_LOCKED) != 0 && bp->b_iodone == NULL) { \
345 mutex_enter(&lfs_lock); \
346 --locked_queue_count; \
347 locked_queue_bytes -= bp->b_bufsize; \
348 if (locked_queue_count < LFS_WAIT_BUFS && \
349 locked_queue_bytes < LFS_WAIT_BYTES) \
350 cv_broadcast(&locked_queue_cv); \
351 mutex_exit(&lfs_lock); \
352 } \
353 (bp)->b_flags &= ~B_LOCKED; \
354 } while (0)
355
356 /*
357 * "struct inode" associated definitions
358 */
359
360 #define LFS_SET_UINO(ip, flags) do { \
361 if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED)) \
362 lfs_sb_adduinodes((ip)->i_lfs, 1); \
363 if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING)) \
364 lfs_sb_adduinodes((ip)->i_lfs, 1); \
365 if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED)) \
366 lfs_sb_adduinodes((ip)->i_lfs, 1); \
367 (ip)->i_flag |= (flags); \
368 } while (0)
369
370 #define LFS_CLR_UINO(ip, flags) do { \
371 if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED)) \
372 lfs_sb_subuinodes((ip)->i_lfs, 1); \
373 if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING)) \
374 lfs_sb_subuinodes((ip)->i_lfs, 1); \
375 if (((flags) & IN_MODIFIED) && ((ip)->i_flag & IN_MODIFIED)) \
376 lfs_sb_subuinodes((ip)->i_lfs, 1); \
377 (ip)->i_flag &= ~(flags); \
378 if (lfs_sb_getuinodes((ip)->i_lfs) < 0) { \
379 panic("lfs_uinodes < 0"); \
380 } \
381 } while (0)
382
383 #define LFS_ITIMES(ip, acc, mod, cre) \
384 while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
385 lfs_itimes(ip, acc, mod, cre)
386
387 /*
388 * On-disk and in-memory checkpoint segment usage structure.
389 */
390
391 #define SEGUPB(fs) (lfs_sb_getsepb(fs))
392 #define SEGTABSIZE_SU(fs) \
393 ((lfs_sb_getnseg(fs) + SEGUPB(fs) - 1) / lfs_sb_getsepb(fs))
394
395 #ifdef _KERNEL
396 # define SHARE_IFLOCK(F) \
397 do { \
398 rw_enter(&(F)->lfs_iflock, RW_READER); \
399 } while(0)
400 # define UNSHARE_IFLOCK(F) \
401 do { \
402 rw_exit(&(F)->lfs_iflock); \
403 } while(0)
404 #else /* ! _KERNEL */
405 # define SHARE_IFLOCK(F)
406 # define UNSHARE_IFLOCK(F)
407 #endif /* ! _KERNEL */
408
409 /* Read in the block with a specific segment usage entry from the ifile. */
410 #define LFS_SEGENTRY(SP, F, IN, BP) do { \
411 int _e; \
412 SHARE_IFLOCK(F); \
413 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
414 if ((_e = bread((F)->lfs_ivnode, \
415 ((IN) / lfs_sb_getsepb(F)) + lfs_sb_getcleansz(F), \
416 lfs_sb_getbsize(F), 0, &(BP))) != 0) \
417 panic("lfs: ifile read: %d", _e); \
418 if (lfs_sb_getversion(F) == 1) \
419 (SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data + \
420 ((IN) & (lfs_sb_getsepb(F) - 1))); \
421 else \
422 (SP) = (SEGUSE *)(BP)->b_data + ((IN) % lfs_sb_getsepb(F)); \
423 UNSHARE_IFLOCK(F); \
424 } while (0)
425
426 #define LFS_WRITESEGENTRY(SP, F, IN, BP) do { \
427 if ((SP)->su_nbytes == 0) \
428 (SP)->su_flags |= SEGUSE_EMPTY; \
429 else \
430 (SP)->su_flags &= ~SEGUSE_EMPTY; \
431 (F)->lfs_suflags[(F)->lfs_activesb][(IN)] = (SP)->su_flags; \
432 LFS_BWRITE_LOG(BP); \
433 } while (0)
434
435 /*
436 * FINFO (file info) entries.
437 */
438
439 /* Size of an on-disk block pointer, e.g. in an indirect block. */
440 /* XXX: move to a more suitable location in this file */
441 #define LFS_BLKPTRSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t))
442
443 /* Size of an on-disk inode number. */
444 /* XXX: move to a more suitable location in this file */
445 #define LFS_INUMSIZE(fs) ((fs)->lfs_is64 ? sizeof(int64_t) : sizeof(int32_t))
446
447 /* size of a FINFO, without the block pointers */
448 #define FINFOSIZE(fs) ((fs)->lfs_is64 ? sizeof(FINFO64) : sizeof(FINFO32))
449
450 /* Full size of the provided FINFO record, including its block pointers. */
451 #define FINFO_FULLSIZE(fs, fip) \
452 (FINFOSIZE(fs) + lfs_fi_getnblocks(fs, fip) * LFS_BLKPTRSIZE(fs))
453
454 #define NEXT_FINFO(fs, fip) \
455 ((FINFO *)((char *)(fip) + FINFO_FULLSIZE(fs, fip)))
456
457 #define LFS_DEF_FI_ACCESSOR(type, type32, field) \
458 static __unused inline type \
459 lfs_fi_get##field(STRUCT_LFS *fs, FINFO *fip) \
460 { \
461 if (fs->lfs_is64) { \
462 return fip->u_64.fi_##field; \
463 } else { \
464 return fip->u_32.fi_##field; \
465 } \
466 } \
467 static __unused inline void \
468 lfs_fi_set##field(STRUCT_LFS *fs, FINFO *fip, type val) \
469 { \
470 if (fs->lfs_is64) { \
471 type *p = &fip->u_64.fi_##field; \
472 (void)p; \
473 fip->u_64.fi_##field = val; \
474 } else { \
475 type32 *p = &fip->u_32.fi_##field; \
476 (void)p; \
477 fip->u_32.fi_##field = val; \
478 } \
479 } \
480
481 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, nblocks);
482 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, version);
483 LFS_DEF_FI_ACCESSOR(uint64_t, uint32_t, ino);
484 LFS_DEF_FI_ACCESSOR(uint32_t, uint32_t, lastlength);
485
486 static __unused inline daddr_t
487 lfs_fi_getblock(STRUCT_LFS *fs, FINFO *fip, unsigned index)
488 {
489 void *firstblock;
490
491 firstblock = (char *)fip + FINFOSIZE(fs);
492 KASSERT(index < lfs_fi_getnblocks(fs, fip));
493 if (fs->lfs_is64) {
494 return ((int64_t *)firstblock)[index];
495 } else {
496 return ((int32_t *)firstblock)[index];
497 }
498 }
499
500 static __unused inline void
501 lfs_fi_setblock(STRUCT_LFS *fs, FINFO *fip, unsigned index, daddr_t blk)
502 {
503 void *firstblock;
504
505 firstblock = (char *)fip + FINFOSIZE(fs);
506 KASSERT(index < lfs_fi_getnblocks(fs, fip));
507 if (fs->lfs_is64) {
508 ((int64_t *)firstblock)[index] = blk;
509 } else {
510 ((int32_t *)firstblock)[index] = blk;
511 }
512 }
513
514 /*
515 * Index file inode entries.
516 */
517
518 /*
519 * LFSv1 compatibility code is not allowed to touch if_atime, since it
520 * may not be mapped!
521 */
522 /* Read in the block with a specific inode from the ifile. */
523 #define LFS_IENTRY(IP, F, IN, BP) do { \
524 int _e; \
525 SHARE_IFLOCK(F); \
526 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
527 if ((_e = bread((F)->lfs_ivnode, \
528 (IN) / lfs_sb_getifpb(F) + lfs_sb_getcleansz(F) + lfs_sb_getsegtabsz(F), \
529 lfs_sb_getbsize(F), 0, &(BP))) != 0) \
530 panic("lfs: ifile ino %d read %d", (int)(IN), _e); \
531 if ((F)->lfs_is64) { \
532 (IP) = (IFILE *)((IFILE64 *)(BP)->b_data + \
533 (IN) % lfs_sb_getifpb(F)); \
534 } else if (lfs_sb_getversion(F) > 1) { \
535 (IP) = (IFILE *)((IFILE32 *)(BP)->b_data + \
536 (IN) % lfs_sb_getifpb(F)); \
537 } else { \
538 (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + \
539 (IN) % lfs_sb_getifpb(F)); \
540 } \
541 UNSHARE_IFLOCK(F); \
542 } while (0)
543 #define LFS_IENTRY_NEXT(IP, F) do { \
544 if ((F)->lfs_is64) { \
545 (IP) = (IFILE *)((IFILE64 *)(IP) + 1); \
546 } else if (lfs_sb_getversion(F) > 1) { \
547 (IP) = (IFILE *)((IFILE32 *)(IP) + 1); \
548 } else { \
549 (IP) = (IFILE *)((IFILE_V1 *)(IP) + 1); \
550 } \
551 } while (0)
552
553 #define LFS_DEF_IF_ACCESSOR(type, type32, field) \
554 static __unused inline type \
555 lfs_if_get##field(STRUCT_LFS *fs, IFILE *ifp) \
556 { \
557 if (fs->lfs_is64) { \
558 return ifp->u_64.if_##field; \
559 } else { \
560 return ifp->u_32.if_##field; \
561 } \
562 } \
563 static __unused inline void \
564 lfs_if_set##field(STRUCT_LFS *fs, IFILE *ifp, type val) \
565 { \
566 if (fs->lfs_is64) { \
567 type *p = &ifp->u_64.if_##field; \
568 (void)p; \
569 ifp->u_64.if_##field = val; \
570 } else { \
571 type32 *p = &ifp->u_32.if_##field; \
572 (void)p; \
573 ifp->u_32.if_##field = val; \
574 } \
575 } \
576
577 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, version);
578 LFS_DEF_IF_ACCESSOR(int64_t, int32_t, daddr);
579 LFS_DEF_IF_ACCESSOR(u_int64_t, u_int32_t, nextfree);
580 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, atime_sec);
581 LFS_DEF_IF_ACCESSOR(u_int32_t, u_int32_t, atime_nsec);
582
583 /*
584 * Cleaner information structure. This resides in the ifile and is used
585 * to pass information from the kernel to the cleaner.
586 */
587
588 #define CLEANSIZE_SU(fs) \
589 ((((fs)->lfs_is64 ? sizeof(CLEANERINFO64) : sizeof(CLEANERINFO32)) + \
590 lfs_sb_getbsize(fs) - 1) >> lfs_sb_getbshift(fs))
591
592 #define LFS_DEF_CI_ACCESSOR(type, type32, field) \
593 static __unused inline type \
594 lfs_ci_get##field(STRUCT_LFS *fs, CLEANERINFO *cip) \
595 { \
596 if (fs->lfs_is64) { \
597 return cip->u_64.field; \
598 } else { \
599 return cip->u_32.field; \
600 } \
601 } \
602 static __unused inline void \
603 lfs_ci_set##field(STRUCT_LFS *fs, CLEANERINFO *cip, type val) \
604 { \
605 if (fs->lfs_is64) { \
606 type *p = &cip->u_64.field; \
607 (void)p; \
608 cip->u_64.field = val; \
609 } else { \
610 type32 *p = &cip->u_32.field; \
611 (void)p; \
612 cip->u_32.field = val; \
613 } \
614 } \
615
616 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, clean);
617 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, dirty);
618 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, bfree);
619 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, avail);
620 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_head);
621 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_tail);
622 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, flags);
623
624 static __unused inline void
625 lfs_ci_shiftcleantodirty(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num)
626 {
627 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) - num);
628 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) + num);
629 }
630
631 static __unused inline void
632 lfs_ci_shiftdirtytoclean(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num)
633 {
634 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) - num);
635 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) + num);
636 }
637
638 /* Read in the block with the cleaner info from the ifile. */
639 #define LFS_CLEANERINFO(CP, F, BP) do { \
640 SHARE_IFLOCK(F); \
641 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
642 if (bread((F)->lfs_ivnode, \
643 (daddr_t)0, lfs_sb_getbsize(F), 0, &(BP))) \
644 panic("lfs: ifile read"); \
645 (CP) = (CLEANERINFO *)(BP)->b_data; \
646 UNSHARE_IFLOCK(F); \
647 } while (0)
648
649 /*
650 * Synchronize the Ifile cleaner info with current avail and bfree.
651 */
652 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do { \
653 mutex_enter(&lfs_lock); \
654 if ((w) || lfs_ci_getbfree(fs, cip) != lfs_sb_getbfree(fs) || \
655 lfs_ci_getavail(fs, cip) != lfs_sb_getavail(fs) - fs->lfs_ravail - \
656 fs->lfs_favail) { \
657 lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); \
658 lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) - fs->lfs_ravail - \
659 fs->lfs_favail); \
660 if (((bp)->b_flags & B_GATHERED) == 0) { \
661 fs->lfs_flags |= LFS_IFDIRTY; \
662 } \
663 mutex_exit(&lfs_lock); \
664 (void) LFS_BWRITE_LOG(bp); /* Ifile */ \
665 } else { \
666 mutex_exit(&lfs_lock); \
667 brelse(bp, 0); \
668 } \
669 } while (0)
670
671 /*
672 * Get the head of the inode free list.
673 * Always called with the segment lock held.
674 */
675 #define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do { \
676 if (lfs_sb_getversion(FS) > 1) { \
677 LFS_CLEANERINFO((CIP), (FS), (BP)); \
678 lfs_sb_setfreehd(FS, lfs_ci_getfree_head(FS, CIP)); \
679 brelse(BP, 0); \
680 } \
681 *(FREEP) = lfs_sb_getfreehd(FS); \
682 } while (0)
683
684 #define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do { \
685 lfs_sb_setfreehd(FS, VAL); \
686 if (lfs_sb_getversion(FS) > 1) { \
687 LFS_CLEANERINFO((CIP), (FS), (BP)); \
688 lfs_ci_setfree_head(FS, CIP, VAL); \
689 LFS_BWRITE_LOG(BP); \
690 mutex_enter(&lfs_lock); \
691 (FS)->lfs_flags |= LFS_IFDIRTY; \
692 mutex_exit(&lfs_lock); \
693 } \
694 } while (0)
695
696 #define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do { \
697 LFS_CLEANERINFO((CIP), (FS), (BP)); \
698 *(FREEP) = lfs_ci_getfree_tail(FS, CIP); \
699 brelse(BP, 0); \
700 } while (0)
701
702 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \
703 LFS_CLEANERINFO((CIP), (FS), (BP)); \
704 lfs_ci_setfree_tail(FS, CIP, VAL); \
705 LFS_BWRITE_LOG(BP); \
706 mutex_enter(&lfs_lock); \
707 (FS)->lfs_flags |= LFS_IFDIRTY; \
708 mutex_exit(&lfs_lock); \
709 } while (0)
710
711 /*
712 * On-disk segment summary information
713 */
714
715 #define SEGSUM_SIZE(fs) \
716 (fs->lfs_is64 ? sizeof(SEGSUM64) : \
717 lfs_sb_getversion(fs) > 1 ? sizeof(SEGSUM32) : sizeof(SEGSUM_V1))
718
719 /*
720 * The SEGSUM structure is followed by FINFO structures. Get the pointer
721 * to the first FINFO.
722 *
723 * XXX this can't be a macro yet; this file needs to be resorted.
724 */
725 #if 0
726 static __unused inline FINFO *
727 segsum_finfobase(STRUCT_LFS *fs, SEGSUM *ssp)
728 {
729 return (FINFO *)((char *)ssp + SEGSUM_SIZE(fs));
730 }
731 #else
732 #define SEGSUM_FINFOBASE(fs, ssp) \
733 ((FINFO *)((char *)(ssp) + SEGSUM_SIZE(fs)));
734 #endif
735
736 #define LFS_DEF_SS_ACCESSOR(type, type32, field) \
737 static __unused inline type \
738 lfs_ss_get##field(STRUCT_LFS *fs, SEGSUM *ssp) \
739 { \
740 if (fs->lfs_is64) { \
741 return ssp->u_64.ss_##field; \
742 } else { \
743 return ssp->u_32.ss_##field; \
744 } \
745 } \
746 static __unused inline void \
747 lfs_ss_set##field(STRUCT_LFS *fs, SEGSUM *ssp, type val) \
748 { \
749 if (fs->lfs_is64) { \
750 type *p = &ssp->u_64.ss_##field; \
751 (void)p; \
752 ssp->u_64.ss_##field = val; \
753 } else { \
754 type32 *p = &ssp->u_32.ss_##field; \
755 (void)p; \
756 ssp->u_32.ss_##field = val; \
757 } \
758 } \
759
760 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, sumsum);
761 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, datasum);
762 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, magic);
763 LFS_DEF_SS_ACCESSOR(uint32_t, uint32_t, ident);
764 LFS_DEF_SS_ACCESSOR(int64_t, int32_t, next);
765 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, nfinfo);
766 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, ninos);
767 LFS_DEF_SS_ACCESSOR(uint16_t, uint16_t, flags);
768 LFS_DEF_SS_ACCESSOR(uint64_t, uint32_t, reclino);
769 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, serial);
770 LFS_DEF_SS_ACCESSOR(uint64_t, uint64_t, create);
771
772 static __unused inline size_t
773 lfs_ss_getsumstart(STRUCT_LFS *fs)
774 {
775 /* These are actually all the same. */
776 if (fs->lfs_is64) {
777 return offsetof(SEGSUM64, ss_datasum);
778 } else /* if (lfs_sb_getversion(fs) > 1) */ {
779 return offsetof(SEGSUM32, ss_datasum);
780 } /* else {
781 return offsetof(SEGSUM_V1, ss_datasum);
782 } */
783 /*
784 * XXX ^^^ until this file is resorted lfs_sb_getversion isn't
785 * defined yet.
786 */
787 }
788
789 static __unused inline uint32_t
790 lfs_ss_getocreate(STRUCT_LFS *fs, SEGSUM *ssp)
791 {
792 KASSERT(fs->lfs_is64 == 0);
793 /* XXX need to resort this file before we can do this */
794 //KASSERT(lfs_sb_getversion(fs) == 1);
795
796 return ssp->u_v1.ss_create;
797 }
798
799 static __unused inline void
800 lfs_ss_setocreate(STRUCT_LFS *fs, SEGSUM *ssp, uint32_t val)
801 {
802 KASSERT(fs->lfs_is64 == 0);
803 /* XXX need to resort this file before we can do this */
804 //KASSERT(lfs_sb_getversion(fs) == 1);
805
806 ssp->u_v1.ss_create = val;
807 }
808
809
810 /*
811 * Super block.
812 */
813
814 /*
815 * Generate accessors for the on-disk superblock fields with cpp.
816 */
817
818 #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \
819 static __unused inline type \
820 lfs_sb_get##field(STRUCT_LFS *fs) \
821 { \
822 if (fs->lfs_is64) { \
823 return fs->lfs_dlfs_u.u_64.dlfs_##field; \
824 } else { \
825 return fs->lfs_dlfs_u.u_32.dlfs_##field; \
826 } \
827 } \
828 static __unused inline void \
829 lfs_sb_set##field(STRUCT_LFS *fs, type val) \
830 { \
831 if (fs->lfs_is64) { \
832 fs->lfs_dlfs_u.u_64.dlfs_##field = val; \
833 } else { \
834 fs->lfs_dlfs_u.u_32.dlfs_##field = val; \
835 } \
836 } \
837 static __unused inline void \
838 lfs_sb_add##field(STRUCT_LFS *fs, type val) \
839 { \
840 if (fs->lfs_is64) { \
841 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
842 *p64 += val; \
843 } else { \
844 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
845 *p32 += val; \
846 } \
847 } \
848 static __unused inline void \
849 lfs_sb_sub##field(STRUCT_LFS *fs, type val) \
850 { \
851 if (fs->lfs_is64) { \
852 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
853 *p64 -= val; \
854 } else { \
855 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
856 *p32 -= val; \
857 } \
858 }
859
860 #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f)
861
862 #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \
863 static __unused inline type \
864 lfs_sb_get##field(STRUCT_LFS *fs) \
865 { \
866 if (fs->lfs_is64) { \
867 return val64; \
868 } else { \
869 return fs->lfs_dlfs_u.u_32.dlfs_##field; \
870 } \
871 }
872
873 #define lfs_magic lfs_dlfs.dlfs_magic
874 LFS_DEF_SB_ACCESSOR(u_int32_t, version);
875 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, size);
876 LFS_DEF_SB_ACCESSOR(u_int32_t, ssize);
877 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, dsize);
878 LFS_DEF_SB_ACCESSOR(u_int32_t, bsize);
879 LFS_DEF_SB_ACCESSOR(u_int32_t, fsize);
880 LFS_DEF_SB_ACCESSOR(u_int32_t, frag);
881 LFS_DEF_SB_ACCESSOR(u_int32_t, freehd);
882 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree);
883 LFS_DEF_SB_ACCESSOR(u_int32_t, nfiles);
884 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail);
885 LFS_DEF_SB_ACCESSOR(int32_t, uinodes);
886 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr);
887 LFS_DEF_SB_ACCESSOR(u_int32_t, ifile);
888 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastseg);
889 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, nextseg);
890 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, curseg);
891 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, offset);
892 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastpseg);
893 LFS_DEF_SB_ACCESSOR(u_int32_t, inopf);
894 LFS_DEF_SB_ACCESSOR(u_int32_t, minfree);
895 LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize);
896 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbpseg);
897 LFS_DEF_SB_ACCESSOR(u_int32_t, inopb);
898 LFS_DEF_SB_ACCESSOR(u_int32_t, ifpb);
899 LFS_DEF_SB_ACCESSOR(u_int32_t, sepb);
900 LFS_DEF_SB_ACCESSOR(u_int32_t, nindir);
901 LFS_DEF_SB_ACCESSOR(u_int32_t, nseg);
902 LFS_DEF_SB_ACCESSOR(u_int32_t, nspf);
903 LFS_DEF_SB_ACCESSOR(u_int32_t, cleansz);
904 LFS_DEF_SB_ACCESSOR(u_int32_t, segtabsz);
905 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segmask, 0);
906 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segshift, 0);
907 LFS_DEF_SB_ACCESSOR(u_int64_t, bmask);
908 LFS_DEF_SB_ACCESSOR(u_int32_t, bshift);
909 LFS_DEF_SB_ACCESSOR(u_int64_t, ffmask);
910 LFS_DEF_SB_ACCESSOR(u_int32_t, ffshift);
911 LFS_DEF_SB_ACCESSOR(u_int64_t, fbmask);
912 LFS_DEF_SB_ACCESSOR(u_int32_t, fbshift);
913 LFS_DEF_SB_ACCESSOR(u_int32_t, blktodb);
914 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbtodb);
915 LFS_DEF_SB_ACCESSOR(u_int32_t, sushift);
916 LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen);
917 LFS_DEF_SB_ACCESSOR(u_int32_t, cksum);
918 LFS_DEF_SB_ACCESSOR(u_int16_t, pflags);
919 LFS_DEF_SB_ACCESSOR(u_int32_t, nclean);
920 LFS_DEF_SB_ACCESSOR(int32_t, dmeta);
921 LFS_DEF_SB_ACCESSOR(u_int32_t, minfreeseg);
922 LFS_DEF_SB_ACCESSOR(u_int32_t, sumsize);
923 LFS_DEF_SB_ACCESSOR(u_int64_t, serial);
924 LFS_DEF_SB_ACCESSOR(u_int32_t, ibsize);
925 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr);
926 LFS_DEF_SB_ACCESSOR(u_int64_t, tstamp);
927 LFS_DEF_SB_ACCESSOR(u_int32_t, inodefmt);
928 LFS_DEF_SB_ACCESSOR(u_int32_t, interleave);
929 LFS_DEF_SB_ACCESSOR(u_int32_t, ident);
930 LFS_DEF_SB_ACCESSOR(u_int32_t, resvseg);
931
932 /* special-case accessors */
933
934 /*
935 * the v1 otstamp field lives in what's now dlfs_inopf
936 */
937 #define lfs_sb_getotstamp(fs) lfs_sb_getinopf(fs)
938 #define lfs_sb_setotstamp(fs, val) lfs_sb_setinopf(fs, val)
939
940 /*
941 * lfs_sboffs is an array
942 */
943 static __unused inline int32_t
944 lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n)
945 {
946 #ifdef KASSERT /* ugh */
947 KASSERT(n < LFS_MAXNUMSB);
948 #endif
949 if (fs->lfs_is64) {
950 return fs->lfs_dlfs_u.u_64.dlfs_sboffs[n];
951 } else {
952 return fs->lfs_dlfs_u.u_32.dlfs_sboffs[n];
953 }
954 }
955 static __unused inline void
956 lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val)
957 {
958 #ifdef KASSERT /* ugh */
959 KASSERT(n < LFS_MAXNUMSB);
960 #endif
961 if (fs->lfs_is64) {
962 fs->lfs_dlfs_u.u_64.dlfs_sboffs[n] = val;
963 } else {
964 fs->lfs_dlfs_u.u_32.dlfs_sboffs[n] = val;
965 }
966 }
967
968 /*
969 * lfs_fsmnt is a string
970 */
971 static __unused inline const char *
972 lfs_sb_getfsmnt(STRUCT_LFS *fs)
973 {
974 if (fs->lfs_is64) {
975 return fs->lfs_dlfs_u.u_64.dlfs_fsmnt;
976 } else {
977 return fs->lfs_dlfs_u.u_32.dlfs_fsmnt;
978 }
979 }
980
981 static __unused inline void
982 lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str)
983 {
984 if (fs->lfs_is64) {
985 (void)strncpy(fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str,
986 sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt));
987 } else {
988 (void)strncpy(fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str,
989 sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt));
990 }
991 }
992
993 /* Highest addressable fsb */
994 #define LFS_MAX_DADDR(fs) \
995 ((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff)
996
997 /* LFS_NINDIR is the number of indirects in a file system block. */
998 #define LFS_NINDIR(fs) (lfs_sb_getnindir(fs))
999
1000 /* LFS_INOPB is the number of inodes in a secondary storage block. */
1001 #define LFS_INOPB(fs) (lfs_sb_getinopb(fs))
1002 /* LFS_INOPF is the number of inodes in a fragment. */
1003 #define LFS_INOPF(fs) (lfs_sb_getinopf(fs))
1004
1005 #define lfs_blkoff(fs, loc) ((int)((loc) & lfs_sb_getbmask(fs)))
1006 #define lfs_fragoff(fs, loc) /* calculates (loc % fs->lfs_fsize) */ \
1007 ((int)((loc) & lfs_sb_getffmask(fs)))
1008
1009 /* XXX: lowercase these as they're no longer macros */
1010 /* Frags to diskblocks */
1011 static __unused inline uint64_t
1012 LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b)
1013 {
1014 #if defined(_KERNEL)
1015 return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT);
1016 #else
1017 return b << lfs_sb_getfsbtodb(fs);
1018 #endif
1019 }
1020 /* Diskblocks to frags */
1021 static __unused inline uint64_t
1022 LFS_DBTOFSB(STRUCT_LFS *fs, uint64_t b)
1023 {
1024 #if defined(_KERNEL)
1025 return b >> (lfs_sb_getffshift(fs) - DEV_BSHIFT);
1026 #else
1027 return b >> lfs_sb_getfsbtodb(fs);
1028 #endif
1029 }
1030
1031 #define lfs_lblkno(fs, loc) ((loc) >> lfs_sb_getbshift(fs))
1032 #define lfs_lblktosize(fs, blk) ((blk) << lfs_sb_getbshift(fs))
1033
1034 /* Frags to bytes */
1035 static __unused inline uint64_t
1036 lfs_fsbtob(STRUCT_LFS *fs, uint64_t b)
1037 {
1038 return b << lfs_sb_getffshift(fs);
1039 }
1040 /* Bytes to frags */
1041 static __unused inline uint64_t
1042 lfs_btofsb(STRUCT_LFS *fs, uint64_t b)
1043 {
1044 return b >> lfs_sb_getffshift(fs);
1045 }
1046
1047 #define lfs_numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \
1048 ((loc) >> lfs_sb_getffshift(fs))
1049 #define lfs_blkroundup(fs, size)/* calculates roundup(size, lfs_sb_getbsize(fs)) */ \
1050 ((off_t)(((size) + lfs_sb_getbmask(fs)) & (~lfs_sb_getbmask(fs))))
1051 #define lfs_fragroundup(fs, size)/* calculates roundup(size, fs->lfs_fsize) */ \
1052 ((off_t)(((size) + lfs_sb_getffmask(fs)) & (~lfs_sb_getffmask(fs))))
1053 #define lfs_fragstoblks(fs, frags)/* calculates (frags / fs->fs_frag) */ \
1054 ((frags) >> lfs_sb_getfbshift(fs))
1055 #define lfs_blkstofrags(fs, blks)/* calculates (blks * fs->fs_frag) */ \
1056 ((blks) << lfs_sb_getfbshift(fs))
1057 #define lfs_fragnum(fs, fsb) /* calculates (fsb % fs->lfs_frag) */ \
1058 ((fsb) & ((fs)->lfs_frag - 1))
1059 #define lfs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->lfs_frag) */ \
1060 ((fsb) &~ ((fs)->lfs_frag - 1))
1061 #define lfs_dblksize(fs, dp, lbn) \
1062 (((lbn) >= ULFS_NDADDR || lfs_dino_getsize(fs, dp) >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \
1063 ? lfs_sb_getbsize(fs) \
1064 : (lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, dp)))))
1065
1066 #define lfs_segsize(fs) (lfs_sb_getversion(fs) == 1 ? \
1067 lfs_lblktosize((fs), lfs_sb_getssize(fs)) : \
1068 lfs_sb_getssize(fs))
1069 /* XXX segtod produces a result in frags despite the 'd' */
1070 #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg))
1071 #define lfs_dtosn(fs, daddr) /* block address to segment number */ \
1072 ((uint32_t)(((daddr) - lfs_sb_gets0addr(fs)) / lfs_segtod((fs), 1)))
1073 #define lfs_sntod(fs, sn) /* segment number to disk address */ \
1074 ((daddr_t)(lfs_segtod((fs), (sn)) + lfs_sb_gets0addr(fs)))
1075
1076 /* XXX, blah. make this appear only if struct inode is defined */
1077 #ifdef _UFS_LFS_LFS_INODE_H_
1078 static __unused inline uint32_t
1079 lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn)
1080 {
1081 if (lbn >= ULFS_NDADDR || lfs_dino_getsize(fs, ip->i_din) >= (lbn + 1) << lfs_sb_getbshift(fs)) {
1082 return lfs_sb_getbsize(fs);
1083 } else {
1084 return lfs_fragroundup(fs, lfs_blkoff(fs, lfs_dino_getsize(fs, ip->i_din)));
1085 }
1086 }
1087 #endif
1088
1089 /*
1090 * union lfs_blocks
1091 */
1092
1093 static __unused inline void
1094 lfs_blocks_fromvoid(STRUCT_LFS *fs, union lfs_blocks *bp, void *p)
1095 {
1096 if (fs->lfs_is64) {
1097 bp->b64 = p;
1098 } else {
1099 bp->b32 = p;
1100 }
1101 }
1102
1103 static __unused inline void
1104 lfs_blocks_fromfinfo(STRUCT_LFS *fs, union lfs_blocks *bp, FINFO *fip)
1105 {
1106 void *firstblock;
1107
1108 firstblock = (char *)fip + FINFOSIZE(fs);
1109 if (fs->lfs_is64) {
1110 bp->b64 = (int64_t *)firstblock;
1111 } else {
1112 bp->b32 = (int32_t *)firstblock;
1113 }
1114 }
1115
1116 static __unused inline daddr_t
1117 lfs_blocks_get(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index)
1118 {
1119 if (fs->lfs_is64) {
1120 return bp->b64[index];
1121 } else {
1122 return bp->b32[index];
1123 }
1124 }
1125
1126 static __unused inline void
1127 lfs_blocks_set(STRUCT_LFS *fs, union lfs_blocks *bp, unsigned index, daddr_t val)
1128 {
1129 if (fs->lfs_is64) {
1130 bp->b64[index] = val;
1131 } else {
1132 bp->b32[index] = val;
1133 }
1134 }
1135
1136 static __unused inline void
1137 lfs_blocks_inc(STRUCT_LFS *fs, union lfs_blocks *bp)
1138 {
1139 if (fs->lfs_is64) {
1140 bp->b64++;
1141 } else {
1142 bp->b32++;
1143 }
1144 }
1145
1146 static __unused inline int
1147 lfs_blocks_eq(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2)
1148 {
1149 if (fs->lfs_is64) {
1150 return bp1->b64 == bp2->b64;
1151 } else {
1152 return bp1->b32 == bp2->b32;
1153 }
1154 }
1155
1156 static __unused inline int
1157 lfs_blocks_sub(STRUCT_LFS *fs, union lfs_blocks *bp1, union lfs_blocks *bp2)
1158 {
1159 /* (remember that the pointers are typed) */
1160 if (fs->lfs_is64) {
1161 return bp1->b64 - bp2->b64;
1162 } else {
1163 return bp1->b32 - bp2->b32;
1164 }
1165 }
1166
1167 /*
1168 * struct segment
1169 */
1170
1171
1172 /*
1173 * Macros for determining free space on the disk, with the variable metadata
1174 * of segment summaries and inode blocks taken into account.
1175 */
1176 /*
1177 * Estimate number of clean blocks not available for writing because
1178 * they will contain metadata or overhead. This is calculated as
1179 *
1180 * E = ((C * M / D) * D + (0) * (T - D)) / T
1181 * or more simply
1182 * E = (C * M) / T
1183 *
1184 * where
1185 * C is the clean space,
1186 * D is the dirty space,
1187 * M is the dirty metadata, and
1188 * T = C + D is the total space on disk.
1189 *
1190 * This approximates the old formula of E = C * M / D when D is close to T,
1191 * but avoids falsely reporting "disk full" when the sample size (D) is small.
1192 */
1193 #define LFS_EST_CMETA(F) (int32_t)(( \
1194 (lfs_sb_getdmeta(F) * (int64_t)lfs_sb_getnclean(F)) / \
1195 (lfs_sb_getnseg(F))))
1196
1197 /* Estimate total size of the disk not including metadata */
1198 #define LFS_EST_NONMETA(F) (lfs_sb_getdsize(F) - lfs_sb_getdmeta(F) - LFS_EST_CMETA(F))
1199
1200 /* Estimate number of blocks actually available for writing */
1201 #define LFS_EST_BFREE(F) (lfs_sb_getbfree(F) > LFS_EST_CMETA(F) ? \
1202 lfs_sb_getbfree(F) - LFS_EST_CMETA(F) : 0)
1203
1204 /* Amount of non-meta space not available to mortal man */
1205 #define LFS_EST_RSVD(F) (int32_t)((LFS_EST_NONMETA(F) * \
1206 (u_int64_t)lfs_sb_getminfree(F)) / \
1207 100)
1208
1209 /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */
1210 #define ISSPACE(F, BB, C) \
1211 ((((C) == NOCRED || kauth_cred_geteuid(C) == 0) && \
1212 LFS_EST_BFREE(F) >= (BB)) || \
1213 (kauth_cred_geteuid(C) != 0 && IS_FREESPACE(F, BB)))
1214
1215 /* Can an ordinary user write BB blocks */
1216 #define IS_FREESPACE(F, BB) \
1217 (LFS_EST_BFREE(F) >= (BB) + LFS_EST_RSVD(F))
1218
1219 /*
1220 * The minimum number of blocks to create a new inode. This is:
1221 * directory direct block (1) + ULFS_NIADDR indirect blocks + inode block (1) +
1222 * ifile direct block (1) + ULFS_NIADDR indirect blocks = 3 + 2 * ULFS_NIADDR blocks.
1223 */
1224 #define LFS_NRESERVE(F) (lfs_btofsb((F), (2 * ULFS_NIADDR + 3) << lfs_sb_getbshift(F)))
1225
1226
1227
1228 #endif /* _UFS_LFS_LFS_ACCESSORS_H_ */
1229