lfs_accessors.h revision 1.9 1 /* $NetBSD: lfs_accessors.h,v 1.9 2015/08/12 18:25:04 dholland Exp $ */
2
3 /* from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp */
4 /* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */
5 /* from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp */
6
7 /*-
8 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
9 * All rights reserved.
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Konrad E. Schroder <perseant (at) hhhh.org>.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35 /*-
36 * Copyright (c) 1991, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)lfs.h 8.9 (Berkeley) 5/8/95
64 */
65 /*
66 * Copyright (c) 2002 Networks Associates Technology, Inc.
67 * All rights reserved.
68 *
69 * This software was developed for the FreeBSD Project by Marshall
70 * Kirk McKusick and Network Associates Laboratories, the Security
71 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
72 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
73 * research program
74 *
75 * Copyright (c) 1982, 1989, 1993
76 * The Regents of the University of California. All rights reserved.
77 * (c) UNIX System Laboratories, Inc.
78 * All or some portions of this file are derived from material licensed
79 * to the University of California by American Telephone and Telegraph
80 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81 * the permission of UNIX System Laboratories, Inc.
82 *
83 * Redistribution and use in source and binary forms, with or without
84 * modification, are permitted provided that the following conditions
85 * are met:
86 * 1. Redistributions of source code must retain the above copyright
87 * notice, this list of conditions and the following disclaimer.
88 * 2. Redistributions in binary form must reproduce the above copyright
89 * notice, this list of conditions and the following disclaimer in the
90 * documentation and/or other materials provided with the distribution.
91 * 3. Neither the name of the University nor the names of its contributors
92 * may be used to endorse or promote products derived from this software
93 * without specific prior written permission.
94 *
95 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105 * SUCH DAMAGE.
106 *
107 * @(#)dinode.h 8.9 (Berkeley) 3/29/95
108 */
109 /*
110 * Copyright (c) 1982, 1986, 1989, 1993
111 * The Regents of the University of California. All rights reserved.
112 * (c) UNIX System Laboratories, Inc.
113 * All or some portions of this file are derived from material licensed
114 * to the University of California by American Telephone and Telegraph
115 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
116 * the permission of UNIX System Laboratories, Inc.
117 *
118 * Redistribution and use in source and binary forms, with or without
119 * modification, are permitted provided that the following conditions
120 * are met:
121 * 1. Redistributions of source code must retain the above copyright
122 * notice, this list of conditions and the following disclaimer.
123 * 2. Redistributions in binary form must reproduce the above copyright
124 * notice, this list of conditions and the following disclaimer in the
125 * documentation and/or other materials provided with the distribution.
126 * 3. Neither the name of the University nor the names of its contributors
127 * may be used to endorse or promote products derived from this software
128 * without specific prior written permission.
129 *
130 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
131 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
132 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
133 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
134 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
135 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
136 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
137 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
138 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
139 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
140 * SUCH DAMAGE.
141 *
142 * @(#)dir.h 8.5 (Berkeley) 4/27/95
143 */
144
145 #ifndef _UFS_LFS_LFS_ACCESSORS_H_
146 #define _UFS_LFS_LFS_ACCESSORS_H_
147
148 /*
149 * STRUCT_LFS is used by the libsa code to get accessors that work
150 * with struct salfs instead of struct lfs, and by the cleaner to
151 * get accessors that work with struct clfs.
152 */
153
154 #ifndef STRUCT_LFS
155 #define STRUCT_LFS struct lfs
156 #endif
157
158
159 /*
160 * Maximum length of a symlink that can be stored within the inode.
161 */
162 #define ULFS1_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int32_t))
163 #define ULFS2_MAXSYMLINKLEN ((ULFS_NDADDR + ULFS_NIADDR) * sizeof(int64_t))
164
165 #define ULFS_MAXSYMLINKLEN(ip) \
166 ((ip)->i_ump->um_fstype == ULFS1) ? \
167 ULFS1_MAXSYMLINKLEN : ULFS2_MAXSYMLINKLEN
168
169 /*
170 * "struct buf" associated definitions
171 */
172
173 # define LFS_LOCK_BUF(bp) do { \
174 if (((bp)->b_flags & B_LOCKED) == 0 && bp->b_iodone == NULL) { \
175 mutex_enter(&lfs_lock); \
176 ++locked_queue_count; \
177 locked_queue_bytes += bp->b_bufsize; \
178 mutex_exit(&lfs_lock); \
179 } \
180 (bp)->b_flags |= B_LOCKED; \
181 } while (0)
182
183 # define LFS_UNLOCK_BUF(bp) do { \
184 if (((bp)->b_flags & B_LOCKED) != 0 && bp->b_iodone == NULL) { \
185 mutex_enter(&lfs_lock); \
186 --locked_queue_count; \
187 locked_queue_bytes -= bp->b_bufsize; \
188 if (locked_queue_count < LFS_WAIT_BUFS && \
189 locked_queue_bytes < LFS_WAIT_BYTES) \
190 cv_broadcast(&locked_queue_cv); \
191 mutex_exit(&lfs_lock); \
192 } \
193 (bp)->b_flags &= ~B_LOCKED; \
194 } while (0)
195
196 /*
197 * "struct inode" associated definitions
198 */
199
200 #define LFS_SET_UINO(ip, flags) do { \
201 if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED)) \
202 lfs_sb_adduinodes((ip)->i_lfs, 1); \
203 if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING)) \
204 lfs_sb_adduinodes((ip)->i_lfs, 1); \
205 if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED)) \
206 lfs_sb_adduinodes((ip)->i_lfs, 1); \
207 (ip)->i_flag |= (flags); \
208 } while (0)
209
210 #define LFS_CLR_UINO(ip, flags) do { \
211 if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED)) \
212 lfs_sb_subuinodes((ip)->i_lfs, 1); \
213 if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING)) \
214 lfs_sb_subuinodes((ip)->i_lfs, 1); \
215 if (((flags) & IN_MODIFIED) && ((ip)->i_flag & IN_MODIFIED)) \
216 lfs_sb_subuinodes((ip)->i_lfs, 1); \
217 (ip)->i_flag &= ~(flags); \
218 if (lfs_sb_getuinodes((ip)->i_lfs) < 0) { \
219 panic("lfs_uinodes < 0"); \
220 } \
221 } while (0)
222
223 #define LFS_ITIMES(ip, acc, mod, cre) \
224 while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
225 lfs_itimes(ip, acc, mod, cre)
226
227 /*
228 * On-disk and in-memory checkpoint segment usage structure.
229 */
230
231 #define SEGUPB(fs) (lfs_sb_getsepb(fs))
232 #define SEGTABSIZE_SU(fs) \
233 ((lfs_sb_getnseg(fs) + SEGUPB(fs) - 1) / lfs_sb_getsepb(fs))
234
235 #ifdef _KERNEL
236 # define SHARE_IFLOCK(F) \
237 do { \
238 rw_enter(&(F)->lfs_iflock, RW_READER); \
239 } while(0)
240 # define UNSHARE_IFLOCK(F) \
241 do { \
242 rw_exit(&(F)->lfs_iflock); \
243 } while(0)
244 #else /* ! _KERNEL */
245 # define SHARE_IFLOCK(F)
246 # define UNSHARE_IFLOCK(F)
247 #endif /* ! _KERNEL */
248
249 /* Read in the block with a specific segment usage entry from the ifile. */
250 #define LFS_SEGENTRY(SP, F, IN, BP) do { \
251 int _e; \
252 SHARE_IFLOCK(F); \
253 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
254 if ((_e = bread((F)->lfs_ivnode, \
255 ((IN) / lfs_sb_getsepb(F)) + lfs_sb_getcleansz(F), \
256 lfs_sb_getbsize(F), 0, &(BP))) != 0) \
257 panic("lfs: ifile read: %d", _e); \
258 if (lfs_sb_getversion(F) == 1) \
259 (SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data + \
260 ((IN) & (lfs_sb_getsepb(F) - 1))); \
261 else \
262 (SP) = (SEGUSE *)(BP)->b_data + ((IN) % lfs_sb_getsepb(F)); \
263 UNSHARE_IFLOCK(F); \
264 } while (0)
265
266 #define LFS_WRITESEGENTRY(SP, F, IN, BP) do { \
267 if ((SP)->su_nbytes == 0) \
268 (SP)->su_flags |= SEGUSE_EMPTY; \
269 else \
270 (SP)->su_flags &= ~SEGUSE_EMPTY; \
271 (F)->lfs_suflags[(F)->lfs_activesb][(IN)] = (SP)->su_flags; \
272 LFS_BWRITE_LOG(BP); \
273 } while (0)
274
275 /*
276 * Index file inode entries.
277 */
278
279 /*
280 * LFSv1 compatibility code is not allowed to touch if_atime, since it
281 * may not be mapped!
282 */
283 /* Read in the block with a specific inode from the ifile. */
284 #define LFS_IENTRY(IP, F, IN, BP) do { \
285 int _e; \
286 SHARE_IFLOCK(F); \
287 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
288 if ((_e = bread((F)->lfs_ivnode, \
289 (IN) / lfs_sb_getifpb(F) + lfs_sb_getcleansz(F) + lfs_sb_getsegtabsz(F), \
290 lfs_sb_getbsize(F), 0, &(BP))) != 0) \
291 panic("lfs: ifile ino %d read %d", (int)(IN), _e); \
292 if (lfs_sb_getversion(F) == 1) \
293 (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + \
294 (IN) % lfs_sb_getifpb(F)); \
295 else \
296 (IP) = (IFILE *)(BP)->b_data + (IN) % lfs_sb_getifpb(F); \
297 UNSHARE_IFLOCK(F); \
298 } while (0)
299
300 /*
301 * Cleaner information structure. This resides in the ifile and is used
302 * to pass information from the kernel to the cleaner.
303 */
304
305 #define CLEANSIZE_SU(fs) \
306 ((((fs)->lfs_is64 ? sizeof(CLEANERINFO64) : sizeof(CLEANERINFO32)) + \
307 lfs_sb_getbsize(fs) - 1) >> lfs_sb_getbshift(fs))
308
309 #define LFS_DEF_CI_ACCESSOR(type, type32, field) \
310 static __unused inline type \
311 lfs_ci_get##field(STRUCT_LFS *fs, CLEANERINFO *cip) \
312 { \
313 if (fs->lfs_is64) { \
314 return cip->u_64.field; \
315 } else { \
316 return cip->u_32.field; \
317 } \
318 } \
319 static __unused inline void \
320 lfs_ci_set##field(STRUCT_LFS *fs, CLEANERINFO *cip, type val) \
321 { \
322 if (fs->lfs_is64) { \
323 type *p = &cip->u_64.field; \
324 (void)p; \
325 cip->u_64.field = val; \
326 } else { \
327 type32 *p = &cip->u_32.field; \
328 (void)p; \
329 cip->u_32.field = val; \
330 } \
331 } \
332
333 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, clean);
334 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, dirty);
335 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, bfree);
336 LFS_DEF_CI_ACCESSOR(int64_t, int32_t, avail);
337 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_head);
338 LFS_DEF_CI_ACCESSOR(u_int64_t, u_int32_t, free_tail);
339 LFS_DEF_CI_ACCESSOR(u_int32_t, u_int32_t, flags);
340
341 static __unused inline void
342 lfs_ci_shiftcleantodirty(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num)
343 {
344 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) - num);
345 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) + num);
346 }
347
348 static __unused inline void
349 lfs_ci_shiftdirtytoclean(STRUCT_LFS *fs, CLEANERINFO *cip, unsigned num)
350 {
351 lfs_ci_setdirty(fs, cip, lfs_ci_getdirty(fs, cip) - num);
352 lfs_ci_setclean(fs, cip, lfs_ci_getclean(fs, cip) + num);
353 }
354
355 /* Read in the block with the cleaner info from the ifile. */
356 #define LFS_CLEANERINFO(CP, F, BP) do { \
357 SHARE_IFLOCK(F); \
358 VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
359 if (bread((F)->lfs_ivnode, \
360 (daddr_t)0, lfs_sb_getbsize(F), 0, &(BP))) \
361 panic("lfs: ifile read"); \
362 (CP) = (CLEANERINFO *)(BP)->b_data; \
363 UNSHARE_IFLOCK(F); \
364 } while (0)
365
366 /*
367 * Synchronize the Ifile cleaner info with current avail and bfree.
368 */
369 #define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do { \
370 mutex_enter(&lfs_lock); \
371 if ((w) || lfs_ci_getbfree(fs, cip) != lfs_sb_getbfree(fs) || \
372 lfs_ci_getavail(fs, cip) != lfs_sb_getavail(fs) - fs->lfs_ravail - \
373 fs->lfs_favail) { \
374 lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); \
375 lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) - fs->lfs_ravail - \
376 fs->lfs_favail); \
377 if (((bp)->b_flags & B_GATHERED) == 0) { \
378 fs->lfs_flags |= LFS_IFDIRTY; \
379 } \
380 mutex_exit(&lfs_lock); \
381 (void) LFS_BWRITE_LOG(bp); /* Ifile */ \
382 } else { \
383 mutex_exit(&lfs_lock); \
384 brelse(bp, 0); \
385 } \
386 } while (0)
387
388 /*
389 * Get the head of the inode free list.
390 * Always called with the segment lock held.
391 */
392 #define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do { \
393 if (lfs_sb_getversion(FS) > 1) { \
394 LFS_CLEANERINFO((CIP), (FS), (BP)); \
395 lfs_sb_setfreehd(FS, lfs_ci_getfree_head(FS, CIP)); \
396 brelse(BP, 0); \
397 } \
398 *(FREEP) = lfs_sb_getfreehd(FS); \
399 } while (0)
400
401 #define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do { \
402 lfs_sb_setfreehd(FS, VAL); \
403 if (lfs_sb_getversion(FS) > 1) { \
404 LFS_CLEANERINFO((CIP), (FS), (BP)); \
405 lfs_ci_setfree_head(FS, CIP, VAL); \
406 LFS_BWRITE_LOG(BP); \
407 mutex_enter(&lfs_lock); \
408 (FS)->lfs_flags |= LFS_IFDIRTY; \
409 mutex_exit(&lfs_lock); \
410 } \
411 } while (0)
412
413 #define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do { \
414 LFS_CLEANERINFO((CIP), (FS), (BP)); \
415 *(FREEP) = lfs_ci_getfree_tail(FS, CIP); \
416 brelse(BP, 0); \
417 } while (0)
418
419 #define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \
420 LFS_CLEANERINFO((CIP), (FS), (BP)); \
421 lfs_ci_setfree_tail(FS, CIP, VAL); \
422 LFS_BWRITE_LOG(BP); \
423 mutex_enter(&lfs_lock); \
424 (FS)->lfs_flags |= LFS_IFDIRTY; \
425 mutex_exit(&lfs_lock); \
426 } while (0)
427
428 /*
429 * On-disk segment summary information
430 */
431
432 #define SEGSUM_SIZE(fs) (lfs_sb_getversion(fs) == 1 ? sizeof(SEGSUM_V1) : sizeof(SEGSUM))
433
434 /*
435 * Super block.
436 */
437
438 /*
439 * Generate accessors for the on-disk superblock fields with cpp.
440 */
441
442 #define LFS_DEF_SB_ACCESSOR_FULL(type, type32, field) \
443 static __unused inline type \
444 lfs_sb_get##field(STRUCT_LFS *fs) \
445 { \
446 if (fs->lfs_is64) { \
447 return fs->lfs_dlfs_u.u_64.dlfs_##field; \
448 } else { \
449 return fs->lfs_dlfs_u.u_32.dlfs_##field; \
450 } \
451 } \
452 static __unused inline void \
453 lfs_sb_set##field(STRUCT_LFS *fs, type val) \
454 { \
455 if (fs->lfs_is64) { \
456 fs->lfs_dlfs_u.u_64.dlfs_##field = val; \
457 } else { \
458 fs->lfs_dlfs_u.u_32.dlfs_##field = val; \
459 } \
460 } \
461 static __unused inline void \
462 lfs_sb_add##field(STRUCT_LFS *fs, type val) \
463 { \
464 if (fs->lfs_is64) { \
465 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
466 *p64 += val; \
467 } else { \
468 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
469 *p32 += val; \
470 } \
471 } \
472 static __unused inline void \
473 lfs_sb_sub##field(STRUCT_LFS *fs, type val) \
474 { \
475 if (fs->lfs_is64) { \
476 type *p64 = &fs->lfs_dlfs_u.u_64.dlfs_##field; \
477 *p64 -= val; \
478 } else { \
479 type32 *p32 = &fs->lfs_dlfs_u.u_32.dlfs_##field; \
480 *p32 -= val; \
481 } \
482 }
483
484 #define LFS_DEF_SB_ACCESSOR(t, f) LFS_DEF_SB_ACCESSOR_FULL(t, t, f)
485
486 #define LFS_DEF_SB_ACCESSOR_32ONLY(type, field, val64) \
487 static __unused inline type \
488 lfs_sb_get##field(STRUCT_LFS *fs) \
489 { \
490 if (fs->lfs_is64) { \
491 return val64; \
492 } else { \
493 return fs->lfs_dlfs_u.u_32.dlfs_##field; \
494 } \
495 }
496
497 #define lfs_magic lfs_dlfs.dlfs_magic
498 LFS_DEF_SB_ACCESSOR(u_int32_t, version);
499 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, size);
500 LFS_DEF_SB_ACCESSOR(u_int32_t, ssize);
501 LFS_DEF_SB_ACCESSOR_FULL(u_int64_t, u_int32_t, dsize);
502 LFS_DEF_SB_ACCESSOR(u_int32_t, bsize);
503 LFS_DEF_SB_ACCESSOR(u_int32_t, fsize);
504 LFS_DEF_SB_ACCESSOR(u_int32_t, frag);
505 LFS_DEF_SB_ACCESSOR(u_int32_t, freehd);
506 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, bfree);
507 LFS_DEF_SB_ACCESSOR(u_int32_t, nfiles);
508 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, avail);
509 LFS_DEF_SB_ACCESSOR(int32_t, uinodes);
510 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, idaddr);
511 LFS_DEF_SB_ACCESSOR(u_int32_t, ifile);
512 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastseg);
513 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, nextseg);
514 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, curseg);
515 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, offset);
516 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, lastpseg);
517 LFS_DEF_SB_ACCESSOR(u_int32_t, inopf);
518 LFS_DEF_SB_ACCESSOR(u_int32_t, minfree);
519 LFS_DEF_SB_ACCESSOR(uint64_t, maxfilesize);
520 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbpseg);
521 LFS_DEF_SB_ACCESSOR(u_int32_t, inopb);
522 LFS_DEF_SB_ACCESSOR(u_int32_t, ifpb);
523 LFS_DEF_SB_ACCESSOR(u_int32_t, sepb);
524 LFS_DEF_SB_ACCESSOR(u_int32_t, nindir);
525 LFS_DEF_SB_ACCESSOR(u_int32_t, nseg);
526 LFS_DEF_SB_ACCESSOR(u_int32_t, nspf);
527 LFS_DEF_SB_ACCESSOR(u_int32_t, cleansz);
528 LFS_DEF_SB_ACCESSOR(u_int32_t, segtabsz);
529 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segmask, 0);
530 LFS_DEF_SB_ACCESSOR_32ONLY(u_int32_t, segshift, 0);
531 LFS_DEF_SB_ACCESSOR(u_int64_t, bmask);
532 LFS_DEF_SB_ACCESSOR(u_int32_t, bshift);
533 LFS_DEF_SB_ACCESSOR(u_int64_t, ffmask);
534 LFS_DEF_SB_ACCESSOR(u_int32_t, ffshift);
535 LFS_DEF_SB_ACCESSOR(u_int64_t, fbmask);
536 LFS_DEF_SB_ACCESSOR(u_int32_t, fbshift);
537 LFS_DEF_SB_ACCESSOR(u_int32_t, blktodb);
538 LFS_DEF_SB_ACCESSOR(u_int32_t, fsbtodb);
539 LFS_DEF_SB_ACCESSOR(u_int32_t, sushift);
540 LFS_DEF_SB_ACCESSOR(int32_t, maxsymlinklen);
541 LFS_DEF_SB_ACCESSOR(u_int32_t, cksum);
542 LFS_DEF_SB_ACCESSOR(u_int16_t, pflags);
543 LFS_DEF_SB_ACCESSOR(u_int32_t, nclean);
544 LFS_DEF_SB_ACCESSOR(int32_t, dmeta);
545 LFS_DEF_SB_ACCESSOR(u_int32_t, minfreeseg);
546 LFS_DEF_SB_ACCESSOR(u_int32_t, sumsize);
547 LFS_DEF_SB_ACCESSOR(u_int64_t, serial);
548 LFS_DEF_SB_ACCESSOR(u_int32_t, ibsize);
549 LFS_DEF_SB_ACCESSOR_FULL(int64_t, int32_t, s0addr);
550 LFS_DEF_SB_ACCESSOR(u_int64_t, tstamp);
551 LFS_DEF_SB_ACCESSOR(u_int32_t, inodefmt);
552 LFS_DEF_SB_ACCESSOR(u_int32_t, interleave);
553 LFS_DEF_SB_ACCESSOR(u_int32_t, ident);
554 LFS_DEF_SB_ACCESSOR(u_int32_t, resvseg);
555
556 /* special-case accessors */
557
558 /*
559 * the v1 otstamp field lives in what's now dlfs_inopf
560 */
561 #define lfs_sb_getotstamp(fs) lfs_sb_getinopf(fs)
562 #define lfs_sb_setotstamp(fs, val) lfs_sb_setinopf(fs, val)
563
564 /*
565 * lfs_sboffs is an array
566 */
567 static __unused inline int32_t
568 lfs_sb_getsboff(STRUCT_LFS *fs, unsigned n)
569 {
570 #ifdef KASSERT /* ugh */
571 KASSERT(n < LFS_MAXNUMSB);
572 #endif
573 if (fs->lfs_is64) {
574 return fs->lfs_dlfs_u.u_64.dlfs_sboffs[n];
575 } else {
576 return fs->lfs_dlfs_u.u_32.dlfs_sboffs[n];
577 }
578 }
579 static __unused inline void
580 lfs_sb_setsboff(STRUCT_LFS *fs, unsigned n, int32_t val)
581 {
582 #ifdef KASSERT /* ugh */
583 KASSERT(n < LFS_MAXNUMSB);
584 #endif
585 if (fs->lfs_is64) {
586 fs->lfs_dlfs_u.u_64.dlfs_sboffs[n] = val;
587 } else {
588 fs->lfs_dlfs_u.u_32.dlfs_sboffs[n] = val;
589 }
590 }
591
592 /*
593 * lfs_fsmnt is a string
594 */
595 static __unused inline const char *
596 lfs_sb_getfsmnt(STRUCT_LFS *fs)
597 {
598 if (fs->lfs_is64) {
599 return fs->lfs_dlfs_u.u_64.dlfs_fsmnt;
600 } else {
601 return fs->lfs_dlfs_u.u_32.dlfs_fsmnt;
602 }
603 }
604
605 static __unused inline void
606 lfs_sb_setfsmnt(STRUCT_LFS *fs, const char *str)
607 {
608 if (fs->lfs_is64) {
609 (void)strncpy(fs->lfs_dlfs_u.u_64.dlfs_fsmnt, str,
610 sizeof(fs->lfs_dlfs_u.u_64.dlfs_fsmnt));
611 } else {
612 (void)strncpy(fs->lfs_dlfs_u.u_32.dlfs_fsmnt, str,
613 sizeof(fs->lfs_dlfs_u.u_32.dlfs_fsmnt));
614 }
615 }
616
617 /* Highest addressable fsb */
618 #define LFS_MAX_DADDR(fs) \
619 ((fs)->lfs_is64 ? 0x7fffffffffffffff : 0x7fffffff)
620
621 /* LFS_NINDIR is the number of indirects in a file system block. */
622 #define LFS_NINDIR(fs) (lfs_sb_getnindir(fs))
623
624 /* LFS_INOPB is the number of inodes in a secondary storage block. */
625 #define LFS_INOPB(fs) (lfs_sb_getinopb(fs))
626 /* LFS_INOPF is the number of inodes in a fragment. */
627 #define LFS_INOPF(fs) (lfs_sb_getinopf(fs))
628
629 #define lfs_blkoff(fs, loc) ((int)((loc) & lfs_sb_getbmask(fs)))
630 #define lfs_fragoff(fs, loc) /* calculates (loc % fs->lfs_fsize) */ \
631 ((int)((loc) & lfs_sb_getffmask(fs)))
632
633 /* XXX: lowercase these as they're no longer macros */
634 /* Frags to diskblocks */
635 static __unused inline uint64_t
636 LFS_FSBTODB(STRUCT_LFS *fs, uint64_t b)
637 {
638 #if defined(_KERNEL)
639 return b << (lfs_sb_getffshift(fs) - DEV_BSHIFT);
640 #else
641 return b << lfs_sb_getfsbtodb(fs);
642 #endif
643 }
644 /* Diskblocks to frags */
645 static __unused inline uint64_t
646 LFS_DBTOFSB(STRUCT_LFS *fs, uint64_t b)
647 {
648 #if defined(_KERNEL)
649 return b >> (lfs_sb_getffshift(fs) - DEV_BSHIFT);
650 #else
651 return b >> lfs_sb_getfsbtodb(fs);
652 #endif
653 }
654
655 #define lfs_lblkno(fs, loc) ((loc) >> lfs_sb_getbshift(fs))
656 #define lfs_lblktosize(fs, blk) ((blk) << lfs_sb_getbshift(fs))
657
658 /* Frags to bytes */
659 static __unused inline uint64_t
660 lfs_fsbtob(STRUCT_LFS *fs, uint64_t b)
661 {
662 return b << lfs_sb_getffshift(fs);
663 }
664 /* Bytes to frags */
665 static __unused inline uint64_t
666 lfs_btofsb(STRUCT_LFS *fs, uint64_t b)
667 {
668 return b >> lfs_sb_getffshift(fs);
669 }
670
671 #define lfs_numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \
672 ((loc) >> lfs_sb_getffshift(fs))
673 #define lfs_blkroundup(fs, size)/* calculates roundup(size, lfs_sb_getbsize(fs)) */ \
674 ((off_t)(((size) + lfs_sb_getbmask(fs)) & (~lfs_sb_getbmask(fs))))
675 #define lfs_fragroundup(fs, size)/* calculates roundup(size, fs->lfs_fsize) */ \
676 ((off_t)(((size) + lfs_sb_getffmask(fs)) & (~lfs_sb_getffmask(fs))))
677 #define lfs_fragstoblks(fs, frags)/* calculates (frags / fs->fs_frag) */ \
678 ((frags) >> lfs_sb_getfbshift(fs))
679 #define lfs_blkstofrags(fs, blks)/* calculates (blks * fs->fs_frag) */ \
680 ((blks) << lfs_sb_getfbshift(fs))
681 #define lfs_fragnum(fs, fsb) /* calculates (fsb % fs->lfs_frag) */ \
682 ((fsb) & ((fs)->lfs_frag - 1))
683 #define lfs_blknum(fs, fsb) /* calculates rounddown(fsb, fs->lfs_frag) */ \
684 ((fsb) &~ ((fs)->lfs_frag - 1))
685 #define lfs_dblksize(fs, dp, lbn) \
686 (((lbn) >= ULFS_NDADDR || (dp)->di_size >= ((lbn) + 1) << lfs_sb_getbshift(fs)) \
687 ? lfs_sb_getbsize(fs) \
688 : (lfs_fragroundup(fs, lfs_blkoff(fs, (dp)->di_size))))
689
690 #define lfs_segsize(fs) (lfs_sb_getversion(fs) == 1 ? \
691 lfs_lblktosize((fs), lfs_sb_getssize(fs)) : \
692 lfs_sb_getssize(fs))
693 /* XXX segtod produces a result in frags despite the 'd' */
694 #define lfs_segtod(fs, seg) (lfs_btofsb(fs, lfs_segsize(fs)) * (seg))
695 #define lfs_dtosn(fs, daddr) /* block address to segment number */ \
696 ((uint32_t)(((daddr) - lfs_sb_gets0addr(fs)) / lfs_segtod((fs), 1)))
697 #define lfs_sntod(fs, sn) /* segment number to disk address */ \
698 ((daddr_t)(lfs_segtod((fs), (sn)) + lfs_sb_gets0addr(fs)))
699
700 /* XXX, blah. make this appear only if struct inode is defined */
701 #ifdef _UFS_LFS_LFS_INODE_H_
702 static __unused inline uint32_t
703 lfs_blksize(STRUCT_LFS *fs, struct inode *ip, uint64_t lbn)
704 {
705 if (lbn >= ULFS_NDADDR || ip->i_ffs1_size >= (lbn + 1) << lfs_sb_getbshift(fs)) {
706 return lfs_sb_getbsize(fs);
707 } else {
708 return lfs_fragroundup(fs, lfs_blkoff(fs, ip->i_ffs1_size));
709 }
710 }
711 #endif
712
713
714 /*
715 * Macros for determining free space on the disk, with the variable metadata
716 * of segment summaries and inode blocks taken into account.
717 */
718 /*
719 * Estimate number of clean blocks not available for writing because
720 * they will contain metadata or overhead. This is calculated as
721 *
722 * E = ((C * M / D) * D + (0) * (T - D)) / T
723 * or more simply
724 * E = (C * M) / T
725 *
726 * where
727 * C is the clean space,
728 * D is the dirty space,
729 * M is the dirty metadata, and
730 * T = C + D is the total space on disk.
731 *
732 * This approximates the old formula of E = C * M / D when D is close to T,
733 * but avoids falsely reporting "disk full" when the sample size (D) is small.
734 */
735 #define LFS_EST_CMETA(F) (int32_t)(( \
736 (lfs_sb_getdmeta(F) * (int64_t)lfs_sb_getnclean(F)) / \
737 (lfs_sb_getnseg(F))))
738
739 /* Estimate total size of the disk not including metadata */
740 #define LFS_EST_NONMETA(F) (lfs_sb_getdsize(F) - lfs_sb_getdmeta(F) - LFS_EST_CMETA(F))
741
742 /* Estimate number of blocks actually available for writing */
743 #define LFS_EST_BFREE(F) (lfs_sb_getbfree(F) > LFS_EST_CMETA(F) ? \
744 lfs_sb_getbfree(F) - LFS_EST_CMETA(F) : 0)
745
746 /* Amount of non-meta space not available to mortal man */
747 #define LFS_EST_RSVD(F) (int32_t)((LFS_EST_NONMETA(F) * \
748 (u_int64_t)lfs_sb_getminfree(F)) / \
749 100)
750
751 /* Can credential C write BB blocks? XXX: kauth_cred_geteuid is abusive */
752 #define ISSPACE(F, BB, C) \
753 ((((C) == NOCRED || kauth_cred_geteuid(C) == 0) && \
754 LFS_EST_BFREE(F) >= (BB)) || \
755 (kauth_cred_geteuid(C) != 0 && IS_FREESPACE(F, BB)))
756
757 /* Can an ordinary user write BB blocks */
758 #define IS_FREESPACE(F, BB) \
759 (LFS_EST_BFREE(F) >= (BB) + LFS_EST_RSVD(F))
760
761 /*
762 * The minimum number of blocks to create a new inode. This is:
763 * directory direct block (1) + ULFS_NIADDR indirect blocks + inode block (1) +
764 * ifile direct block (1) + ULFS_NIADDR indirect blocks = 3 + 2 * ULFS_NIADDR blocks.
765 */
766 #define LFS_NRESERVE(F) (lfs_btofsb((F), (2 * ULFS_NIADDR + 3) << lfs_sb_getbshift(F)))
767
768
769
770 #endif /* _UFS_LFS_LFS_ACCESSORS_H_ */
771