1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
|
/* $NetBSD: lfs.h,v 1.194 2015/10/03 08:29:34 dholland Exp $ */
/* from NetBSD: dinode.h,v 1.22 2013/01/22 09:39:18 dholland Exp */
/* from NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Konrad E. Schroder <perseant@hhhh.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)lfs.h 8.9 (Berkeley) 5/8/95
*/
/*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dinode.h 8.9 (Berkeley) 3/29/95
*/
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dir.h 8.5 (Berkeley) 4/27/95
*/
/*
* NOTE: COORDINATE ON-DISK FORMAT CHANGES WITH THE FREEBSD PROJECT.
*/
#ifndef _UFS_LFS_LFS_H_
#define _UFS_LFS_LFS_H_
#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <stddef.h> /* for offsetof */
#endif
#include <sys/rwlock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/condvar.h>
#include <sys/mount.h>
#include <sys/pool.h>
/*
* Compile-time options for LFS.
*/
#define LFS_IFIND_RETRIES 16
#define LFS_LOGLENGTH 1024 /* size of debugging log */
#define LFS_MAX_ACTIVE 10 /* Dirty segments before ckp forced */
/*
* Fixed filesystem layout parameters
*/
#define LFS_LABELPAD 8192 /* LFS label size */
#define LFS_SBPAD 8192 /* LFS superblock size */
#define LFS_UNUSED_INUM 0 /* 0: out of band inode number */
#define LFS_IFILE_INUM 1 /* 1: IFILE inode number */
/* 2: Root inode number */
#define LFS_LOSTFOUNDINO 3 /* 3: lost+found inode number */
#define LFS_FIRST_INUM 4 /* 4: first free inode number */
/*
* The root inode is the root of the file system. Inode 0 can't be used for
* normal purposes and historically bad blocks were linked to inode 1, thus
* the root inode is 2. (Inode 1 is no longer used for this purpose, however
* numerous dump tapes make this assumption, so we are stuck with it).
*/
#define ULFS_ROOTINO ((ino_t)2)
/*
* The Whiteout inode# is a dummy non-zero inode number which will
* never be allocated to a real file. It is used as a place holder
* in the directory entry which has been tagged as a LFS_DT_WHT entry.
* See the comments about ULFS_ROOTINO above.
*/
#define ULFS_WINO ((ino_t)1)
#define LFS_V1_SUMMARY_SIZE 512 /* V1 fixed summary size */
#define LFS_DFL_SUMMARY_SIZE 512 /* Default summary size */
#define LFS_MAXNAMLEN 255 /* maximum name length in a dir */
#define ULFS_NXADDR 2
#define ULFS_NDADDR 12 /* Direct addresses in inode. */
#define ULFS_NIADDR 3 /* Indirect addresses in inode. */
/*
* Adjustable filesystem parameters
*/
#ifndef LFS_ATIME_IFILE
# define LFS_ATIME_IFILE 0 /* Store atime info in ifile (optional in LFSv1) */
#endif
#define LFS_MARKV_MAXBLKCNT 65536 /* Max block count for lfs_markv() */
/*
* Directories
*/
/*
* Directories in LFS are files; they use the same inode and block
* mapping structures that regular files do. The directory per se is
* manifested in the file contents: an unordered, unstructured
* sequence of variable-size directory entries.
*
* This format and structure is taken (via what was originally shared
* ufs-level code) from FFS. Each directory entry is a fixed header
* followed by a string, the total length padded to a 4-byte boundary.
* All strings include a null terminator; the maximum string length
* is LFS_MAXNAMLEN, which is 255.
*
* The directory entry header structure (struct lfs_dirheader) is just
* the header information. A complete entry is this plus a null-
* terminated name following it, plus some amount of padding. The
* length of the name (not including the null terminator) is given by
* the namlen field of the header; the complete record length,
* including the null terminator and padding, is given by the reclen
* field of the header. The record length is always 4-byte aligned.
* (Even on 64-bit volumes, the record length is only 4-byte aligned,
* not 8-byte.)
*
* Historically, FFS directories were/are organized into blocks of
* size DIRBLKSIZE that can be written atomically to disk at the
* hardware level. Directory entries are not allowed to cross the
* boundaries of these blocks. The resulting atomicity is important
* for the integrity of FFS volumes; however, for LFS it's irrelevant.
* All we have to care about is not writing out directories that
* confuse earlier ufs-based versions of the LFS code.
*
* This means [to be determined]. (XXX)
*
* As DIRBLKSIZE in its FFS sense is hardware-dependent, and file
* system images do from time to time move to different hardware, code
* that reads directories should be prepared to handle directories
* written in a context where DIRBLKSIZE was different (smaller or
* larger) than its current value. Note however that it is not
* sensible for DIRBLKSIZE to be larger than the volume fragment size,
* and not practically possible for it to be larger than the volume
* block size.
*
* Some further notes:
* - the LFS_DIRSIZ macro provides the minimum space needed to hold
* a directory entry.
* - any particular entry may be arbitrarily larger (which is why the
* header stores both the entry size and the name size) to pad out
* unused space.
* - historically the padding in an entry is not necessarily zeroed
* but may contain trash.
* - dp->d_reclen is the size of the entry. This is always 4-byte
* aligned.
* - dp->d_namlen is the length of the string, and should always be
* the same as strlen(dp->d_name).
* - in particular, space available in an entry is given by
* dp->d_reclen - LFS_DIRSIZ(dp), and all space available within a
* directory block is tucked away within an existing entry.
* - all space within a directory block is part of some entry.
* - therefore, inserting a new entry requires finding and
* splitting a suitable existing entry, and when entries are
* removed their space is merged into the entry ahead of them.
* - an empty/unused entry has d_ino set to 0. This normally only
* appears in the first entry in a block, as elsewhere the unused
* entry should have been merged into the one before it. However,
* fsck leaves such entries behind so they must be tolerated
* elsewhere.
* - a completely empty directory block has one entry whose
* d_reclen is DIRBLKSIZ and whose d_ino is 0.
*
* The "old directory format" referenced by the fs->lfs_isolddirfmt
* flag (and some other things) refers to when the type field was
* added to directory entries. This change was made to FFS in the 80s,
* well before LFS was first written; there should be no LFS volumes
* (and certainly no LFS v2-format volumes or LFS64 volumes) where the
* old format pertains. All of the related logic should probably be
* removed; however, it hasn't been yet, and we get to carry it around
* until we can be conclusively sure it isn't needed.
*
* In the "old directory format" there is no type field and the namlen
* field is correspondingly 16 bits wide. On big-endian volumes this
* has no effect: namlen cannot exceed 255, so the upper byte is
* always 0 and this reads back from the type field as LFS_DT_UNKNOWN.
* On little-endian volumes, the namlen field will always be 0 and
* the namlen value needs to be read out of the type field. (The type
* is always LFS_DT_UNKNOWN.) The directory accessor functions take
* care of this so nothing else needs to be aware of it.
*
* LFS_OLDDIRFMT and LFS_NEWDIRFMT are code numbers for the old and
* new directory format respectively. These codes do not appear on
* disk; they're generated from a runtime macro called FSFMT() that's
* cued by other things. This is why (confusingly) LFS_OLDDIRFMT is 1
* and LFS_NEWDIRFMT is 0.
*
* FSFMT(), LFS_OLDDIRFMT, and LFS_NEWDIRFMT should be removed. (XXX)
*/
/*
* Directory block size.
*/
#undef LFS_DIRBLKSIZ
#define LFS_DIRBLKSIZ DEV_BSIZE
/*
* Convert between stat structure type codes and directory entry type codes.
*/
#define LFS_IFTODT(mode) (((mode) & 0170000) >> 12)
#define LFS_DTTOIF(dirtype) ((dirtype) << 12)
/*
* Theoretically, directories can be more than 2Gb in length; however, in
* practice this seems unlikely. So, we define the type doff_t as a 32-bit
* quantity to keep down the cost of doing lookup on a 32-bit machine.
*/
#define doff_t int32_t
#define lfs_doff_t int32_t
#define LFS_MAXDIRSIZE (0x7fffffff)
/*
* File types for d_type
*/
#define LFS_DT_UNKNOWN 0
#define LFS_DT_FIFO 1
#define LFS_DT_CHR 2
#define LFS_DT_DIR 4
#define LFS_DT_BLK 6
#define LFS_DT_REG 8
#define LFS_DT_LNK 10
#define LFS_DT_SOCK 12
#define LFS_DT_WHT 14
/*
* (See notes above)
*/
struct lfs_dirheader32 {
u_int32_t dh_ino; /* inode number of entry */
u_int16_t dh_reclen; /* length of this record */
u_int8_t dh_type; /* file type, see below */
u_int8_t dh_namlen; /* length of string in d_name */
};
struct lfs_dirheader64 {
u_int32_t dh_inoA; /* inode number of entry */
u_int32_t dh_inoB; /* inode number of entry */
u_int16_t dh_reclen; /* length of this record */
u_int8_t dh_type; /* file type, see below */
u_int8_t dh_namlen; /* length of string in d_name */
};
union lfs_dirheader {
struct lfs_dirheader64 u_64;
struct lfs_dirheader32 u_32;
};
typedef union lfs_dirheader LFS_DIRHEADER;
/*
* Template for manipulating directories.
*/
struct lfs_dirtemplate32 {
struct lfs_dirheader32 dot_header;
char dot_name[4]; /* must be multiple of 4 */
struct lfs_dirheader32 dotdot_header;
char dotdot_name[4]; /* ditto */
};
struct lfs_dirtemplate64 {
struct lfs_dirheader64 dot_header;
char dot_name[4]; /* must be multiple of 4 */
struct lfs_dirheader64 dotdot_header;
char dotdot_name[4]; /* ditto */
};
union lfs_dirtemplate {
struct lfs_dirtemplate64 u_64;
struct lfs_dirtemplate32 u_32;
};
#if 0
/*
* This is the old format of directories, sans type element.
*/
struct lfs_odirtemplate {
u_int32_t dot_ino;
int16_t dot_reclen;
u_int16_t dot_namlen;
char dot_name[4]; /* must be multiple of 4 */
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
u_int16_t dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
#endif
/*
* Inodes
*/
/*
* A dinode contains all the meta-data associated with a LFS file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
struct lfs32_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
u_int32_t di_inumber; /* 4: Inode number. */
u_int64_t di_size; /* 8: File byte count. */
int32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
int32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
int32_t di_db[ULFS_NDADDR]; /* 40: Direct disk blocks. */
int32_t di_ib[ULFS_NIADDR]; /* 88: Indirect disk blocks. */
u_int32_t di_flags; /* 100: Status flags (chflags). */
u_int32_t di_blocks; /* 104: Blocks actually held. */
int32_t di_gen; /* 108: Generation number. */
u_int32_t di_uid; /* 112: File owner. */
u_int32_t di_gid; /* 116: File group. */
u_int64_t di_modrev; /* 120: i_modrev for NFSv4 */
};
struct lfs64_dinode {
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
int16_t di_nlink; /* 2: File link count. */
u_int32_t di_uid; /* 4: File owner. */
u_int32_t di_gid; /* 8: File group. */
u_int32_t di_blksize; /* 12: Inode blocksize. */
u_int64_t di_size; /* 16: File byte count. */
u_int64_t di_blocks; /* 24: Bytes actually held. */
int64_t di_atime; /* 32: Last access time. */
int64_t di_mtime; /* 40: Last modified time. */
int64_t di_ctime; /* 48: Last inode change time. */
int64_t di_birthtime; /* 56: Inode creation time. */
int32_t di_mtimensec; /* 64: Last modified time. */
int32_t di_atimensec; /* 68: Last access time. */
int32_t di_ctimensec; /* 72: Last inode change time. */
int32_t di_birthnsec; /* 76: Inode creation time. */
int32_t di_gen; /* 80: Generation number. */
u_int32_t di_kernflags; /* 84: Kernel flags. */
u_int32_t di_flags; /* 88: Status flags (chflags). */
int32_t di_extsize; /* 92: External attributes block. */
int64_t di_extb[ULFS_NXADDR];/* 96: External attributes block. */
int64_t di_db[ULFS_NDADDR]; /* 112: Direct disk blocks. */
int64_t di_ib[ULFS_NIADDR]; /* 208: Indirect disk blocks. */
u_int64_t di_modrev; /* 232: i_modrev for NFSv4 */
u_int64_t di_inumber; /* 240: Inode number */
u_int64_t di_spare[1]; /* 244: Reserved; currently unused */
};
union lfs_dinode {
struct lfs64_dinode u_64;
struct lfs32_dinode u_32;
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define di_rdev di_db[0]
/* Size of the on-disk inode. */
//#define LFS_DINODE1_SIZE (sizeof(struct ulfs1_dinode)) /* 128 */
//#define LFS_DINODE2_SIZE (sizeof(struct ulfs2_dinode))
/* File types, found in the upper bits of di_mode. */
#define LFS_IFMT 0170000 /* Mask of file type. */
#define LFS_IFIFO 0010000 /* Named pipe (fifo). */
#define LFS_IFCHR 0020000 /* Character device. */
#define LFS_IFDIR 0040000 /* Directory file. */
#define LFS_IFBLK 0060000 /* Block device. */
#define LFS_IFREG 0100000 /* Regular file. */
#define LFS_IFLNK 0120000 /* Symbolic link. */
#define LFS_IFSOCK 0140000 /* UNIX domain socket. */
#define LFS_IFWHT 0160000 /* Whiteout. */
/*
* "struct buf" associated definitions
*/
/* Unassigned disk addresses. */
#define UNASSIGNED -1
#define UNWRITTEN -2
/* Unused logical block number */
#define LFS_UNUSED_LBN -1
/*
* "struct inode" associated definitions
*/
/* For convenience */
#define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_MODIFY|IN_ACCESSED|IN_CLEANING)
/*
* On-disk and in-memory checkpoint segment usage structure.
*/
typedef struct segusage SEGUSE;
struct segusage {
u_int32_t su_nbytes; /* 0: number of live bytes */
u_int32_t su_olastmod; /* 4: SEGUSE last modified timestamp */
u_int16_t su_nsums; /* 8: number of summaries in segment */
u_int16_t su_ninos; /* 10: number of inode blocks in seg */
#define SEGUSE_ACTIVE 0x01 /* segment currently being written */
#define SEGUSE_DIRTY 0x02 /* segment has data in it */
#define SEGUSE_SUPERBLOCK 0x04 /* segment contains a superblock */
#define SEGUSE_ERROR 0x08 /* cleaner: do not clean segment */
#define SEGUSE_EMPTY 0x10 /* segment is empty */
#define SEGUSE_INVAL 0x20 /* segment is invalid */
u_int32_t su_flags; /* 12: segment flags */
u_int64_t su_lastmod; /* 16: last modified timestamp */
};
typedef struct segusage_v1 SEGUSE_V1;
struct segusage_v1 {
u_int32_t su_nbytes; /* 0: number of live bytes */
u_int32_t su_lastmod; /* 4: SEGUSE last modified timestamp */
u_int16_t su_nsums; /* 8: number of summaries in segment */
u_int16_t su_ninos; /* 10: number of inode blocks in seg */
u_int32_t su_flags; /* 12: segment flags */
};
/*
* On-disk file information. One per file with data blocks in the segment.
*
* The FINFO structure is a header; it is followed by fi_nblocks block
* pointers, which are logical block numbers of the file. (These are the
* blocks of the file present in this segment.)
*/
typedef struct finfo64 FINFO64;
struct finfo64 {
u_int32_t fi_nblocks; /* number of blocks */
u_int32_t fi_version; /* version number */
u_int64_t fi_ino; /* inode number */
u_int32_t fi_lastlength; /* length of last block in array */
u_int32_t fi_pad; /* unused */
};
typedef struct finfo32 FINFO32;
struct finfo32 {
u_int32_t fi_nblocks; /* number of blocks */
u_int32_t fi_version; /* version number */
u_int32_t fi_ino; /* inode number */
u_int32_t fi_lastlength; /* length of last block in array */
};
typedef union finfo {
struct finfo64 u_64;
struct finfo32 u_32;
} FINFO;
/*
* inode info (part of the segment summary)
*
* Each one of these is just a block number; wrapping the structure
* around it gives more contextual information in the code about
* what's going on.
*/
typedef struct iinfo64 {
uint64_t ii_block; /* block number */
} IINFO64;
typedef struct iinfo32 {
uint32_t ii_block; /* block number */
} IINFO32;
typedef union iinfo {
struct iinfo64 u_64;
struct iinfo32 u_32;
} IINFO;
/*
* Index file inode entries.
*/
/* magic value for daddrs */
#define LFS_UNUSED_DADDR 0 /* out-of-band daddr */
/* magic value for if_nextfree */
#define LFS_ORPHAN_NEXTFREE (~(u_int32_t)0) /* indicate orphaned file */
typedef struct ifile64 IFILE64;
struct ifile64 {
u_int32_t if_version; /* inode version number */
u_int32_t if_atime_nsec; /* and nanoseconds */
u_int64_t if_atime_sec; /* Last access time, seconds */
int64_t if_daddr; /* inode disk address */
u_int64_t if_nextfree; /* next-unallocated inode */
};
typedef struct ifile32 IFILE32;
struct ifile32 {
u_int32_t if_version; /* inode version number */
int32_t if_daddr; /* inode disk address */
u_int32_t if_nextfree; /* next-unallocated inode */
u_int32_t if_atime_sec; /* Last access time, seconds */
u_int32_t if_atime_nsec; /* and nanoseconds */
};
typedef struct ifile_v1 IFILE_V1;
struct ifile_v1 {
u_int32_t if_version; /* inode version number */
int32_t if_daddr; /* inode disk address */
u_int32_t if_nextfree; /* next-unallocated inode */
#if LFS_ATIME_IFILE
#error "this cannot work"
struct timespec if_atime; /* Last access time */
#endif
};
/*
* Note: struct ifile_v1 is often handled by accessing the first three
* fields of struct ifile32. (XXX: Blah. This should be cleaned up as
* it may in some cases violate the strict-aliasing rules.)
*/
typedef union ifile {
struct ifile64 u_64;
struct ifile32 u_32;
struct ifile_v1 u_v1;
} IFILE;
/*
* Cleaner information structure. This resides in the ifile and is used
* to pass information from the kernel to the cleaner.
*/
/* flags for ->flags */
#define LFS_CLEANER_MUST_CLEAN 0x01
typedef struct _cleanerinfo32 {
u_int32_t clean; /* 0: number of clean segments */
u_int32_t dirty; /* 4: number of dirty segments */
int32_t bfree; /* 8: disk blocks free */
int32_t avail; /* 12: disk blocks available */
u_int32_t free_head; /* 16: head of the inode free list */
u_int32_t free_tail; /* 20: tail of the inode free list */
u_int32_t flags; /* 24: status word from the kernel */
} CLEANERINFO32;
typedef struct _cleanerinfo64 {
u_int32_t clean; /* 0: number of clean segments */
u_int32_t dirty; /* 4: number of dirty segments */
int64_t bfree; /* 8: disk blocks free */
int64_t avail; /* 16: disk blocks available */
u_int64_t free_head; /* 24: head of the inode free list */
u_int64_t free_tail; /* 32: tail of the inode free list */
u_int32_t flags; /* 40: status word from the kernel */
u_int32_t pad; /* 44: must be 64-bit aligned */
} CLEANERINFO64;
/* this must not go to disk directly of course */
typedef union _cleanerinfo {
CLEANERINFO32 u_32;
CLEANERINFO64 u_64;
} CLEANERINFO;
/*
* On-disk segment summary information
*/
/* magic value for ss_magic */
#define SS_MAGIC 0x061561
/* flags for ss_flags */
#define SS_DIROP 0x01 /* segment begins a dirop */
#define SS_CONT 0x02 /* more partials to finish this write*/
#define SS_CLEAN 0x04 /* written by the cleaner */
#define SS_RFW 0x08 /* written by the roll-forward agent */
#define SS_RECLAIM 0x10 /* written by the roll-forward agent */
/* type used for reading checksum signatures from metadata structures */
typedef uint32_t lfs_checkword;
typedef struct segsum_v1 SEGSUM_V1;
struct segsum_v1 {
u_int32_t ss_sumsum; /* 0: check sum of summary block */
u_int32_t ss_datasum; /* 4: check sum of data */
u_int32_t ss_magic; /* 8: segment summary magic number */
int32_t ss_next; /* 12: next segment */
u_int32_t ss_create; /* 16: creation time stamp */
u_int16_t ss_nfinfo; /* 20: number of file info structures */
u_int16_t ss_ninos; /* 22: number of inodes in summary */
u_int16_t ss_flags; /* 24: used for directory operations */
u_int16_t ss_pad; /* 26: extra space */
/* FINFO's and inode daddr's... */
};
typedef struct segsum32 SEGSUM32;
struct segsum32 {
u_int32_t ss_sumsum; /* 0: check sum of summary block */
u_int32_t ss_datasum; /* 4: check sum of data */
u_int32_t ss_magic; /* 8: segment summary magic number */
int32_t ss_next; /* 12: next segment (disk address) */
u_int32_t ss_ident; /* 16: roll-forward fsid */
u_int16_t ss_nfinfo; /* 20: number of file info structures */
u_int16_t ss_ninos; /* 22: number of inodes in summary */
u_int16_t ss_flags; /* 24: used for directory operations */
u_int8_t ss_pad[2]; /* 26: extra space */
u_int32_t ss_reclino; /* 28: inode being reclaimed */
u_int64_t ss_serial; /* 32: serial number */
u_int64_t ss_create; /* 40: time stamp */
/* FINFO's and inode daddr's... */
};
typedef struct segsum64 SEGSUM64;
struct segsum64 {
u_int32_t ss_sumsum; /* 0: check sum of summary block */
u_int32_t ss_datasum; /* 4: check sum of data */
u_int32_t ss_magic; /* 8: segment summary magic number */
u_int32_t ss_ident; /* 12: roll-forward fsid */
int64_t ss_next; /* 16: next segment (disk address) */
u_int16_t ss_nfinfo; /* 24: number of file info structures */
u_int16_t ss_ninos; /* 26: number of inodes in summary */
u_int16_t ss_flags; /* 28: used for directory operations */
u_int8_t ss_pad[2]; /* 30: extra space */
u_int64_t ss_reclino; /* 32: inode being reclaimed */
u_int64_t ss_serial; /* 40: serial number */
u_int64_t ss_create; /* 48: time stamp */
/* FINFO's and inode daddr's... */
};
typedef union segsum SEGSUM;
union segsum {
struct segsum64 u_64;
struct segsum32 u_32;
struct segsum_v1 u_v1;
};
/*
* On-disk super block.
*
* We have separate superblock structures for the 32-bit and 64-bit
* LFS, and accessor functions to hide the differences.
*
* For lfs64, the format version is always 2; version 1 lfs is old.
* For both, the inode format version is 0; for lfs32 this selects the
* same 32-bit inode as always, and for lfs64 this selects the larger
* 64-bit inode structure we got from ffsv2.
*
* In lfs64:
* - inode numbers are still 32 bit
* - segments may not be larger than 4G (counted in bytes)
* - there may not be more than 2^32 (or perhaps 2^31) segments
* - the total volume size is limited to 2^63 frags and/or 2^63
* disk blocks, and probably in practice 2^63 bytes.
*/
#define LFS_MAGIC 0x070162
#define LFS_MAGIC_SWAPPED 0x62010700
#define LFS64_MAGIC 0x19620701
#define LFS64_MAGIC_SWAPPED 0x01076219
#define LFS_VERSION 2
#define LFS_MIN_SBINTERVAL 5 /* min superblock segment spacing */
#define LFS_MAXNUMSB 10 /* max number of superblocks */
/* flags for dlfs_pflags */
#define LFS_PF_CLEAN 0x1
/* Inode format versions */
#define LFS_44INODEFMT 0
#define LFS_MAXINODEFMT 0
struct dlfs {
u_int32_t dlfs_magic; /* 0: magic number */
u_int32_t dlfs_version; /* 4: version number */
u_int32_t dlfs_size; /* 8: number of blocks in fs (v1) */
/* number of frags in fs (v2) */
u_int32_t dlfs_ssize; /* 12: number of blocks per segment (v1) */
/* number of bytes per segment (v2) */
u_int32_t dlfs_dsize; /* 16: number of disk blocks in fs */
u_int32_t dlfs_bsize; /* 20: file system block size */
u_int32_t dlfs_fsize; /* 24: size of frag blocks in fs */
u_int32_t dlfs_frag; /* 28: number of frags in a block in fs */
/* Checkpoint region. */
u_int32_t dlfs_freehd; /* 32: start of the free inode list */
int32_t dlfs_bfree; /* 36: number of free frags */
u_int32_t dlfs_nfiles; /* 40: number of allocated inodes */
int32_t dlfs_avail; /* 44: blocks available for writing */
int32_t dlfs_uinodes; /* 48: inodes in cache not yet on disk */
int32_t dlfs_idaddr; /* 52: inode file disk address */
u_int32_t dlfs_ifile; /* 56: inode file inode number */
int32_t dlfs_lastseg; /* 60: address of last segment written */
int32_t dlfs_nextseg; /* 64: address of next segment to write */
int32_t dlfs_curseg; /* 68: current segment being written */
int32_t dlfs_offset; /* 72: offset in curseg for next partial */
int32_t dlfs_lastpseg; /* 76: address of last partial written */
u_int32_t dlfs_inopf; /* 80: v1: time stamp; v2: inodes per frag */
/* These are configuration parameters. */
u_int32_t dlfs_minfree; /* 84: minimum percentage of free blocks */
/* These fields can be computed from the others. */
u_int64_t dlfs_maxfilesize; /* 88: maximum representable file size */
u_int32_t dlfs_fsbpseg; /* 96: frags (fsb) per segment */
u_int32_t dlfs_inopb; /* 100: inodes per block */
u_int32_t dlfs_ifpb; /* 104: IFILE entries per block */
u_int32_t dlfs_sepb; /* 108: SEGUSE entries per block */
u_int32_t dlfs_nindir; /* 112: indirect pointers per block */
u_int32_t dlfs_nseg; /* 116: number of segments */
u_int32_t dlfs_nspf; /* 120: number of sectors per fragment */
u_int32_t dlfs_cleansz; /* 124: cleaner info size in blocks */
u_int32_t dlfs_segtabsz; /* 128: segment table size in blocks */
u_int32_t dlfs_segmask; /* 132: calculate offset within a segment */
u_int32_t dlfs_segshift; /* 136: fast mult/div for segments */
u_int32_t dlfs_bshift; /* 140: calc block number from file offset */
u_int32_t dlfs_ffshift; /* 144: fast mult/div for frag from file */
u_int32_t dlfs_fbshift; /* 148: fast mult/div for frag from block */
u_int64_t dlfs_bmask; /* 152: calc block offset from file offset */
u_int64_t dlfs_ffmask; /* 160: calc frag offset from file offset */
u_int64_t dlfs_fbmask; /* 168: calc frag offset from block offset */
u_int32_t dlfs_blktodb; /* 176: blktodb and dbtoblk shift constant */
u_int32_t dlfs_sushift; /* 180: fast mult/div for segusage table */
int32_t dlfs_maxsymlinklen; /* 184: max length of an internal symlink */
/* 188: superblock disk offsets */
int32_t dlfs_sboffs[LFS_MAXNUMSB];
u_int32_t dlfs_nclean; /* 228: Number of clean segments */
u_char dlfs_fsmnt[MNAMELEN]; /* 232: name mounted on */
u_int16_t dlfs_pflags; /* 322: file system persistent flags */
int32_t dlfs_dmeta; /* 324: total number of dirty summaries */
u_int32_t dlfs_minfreeseg; /* 328: segments not counted in bfree */
u_int32_t dlfs_sumsize; /* 332: size of summary blocks */
u_int64_t dlfs_serial; /* 336: serial number */
u_int32_t dlfs_ibsize; /* 344: size of inode blocks */
int32_t dlfs_s0addr; /* 348: start of segment 0 */
u_int64_t dlfs_tstamp; /* 352: time stamp */
u_int32_t dlfs_inodefmt; /* 360: inode format version */
u_int32_t dlfs_interleave; /* 364: segment interleave */
u_int32_t dlfs_ident; /* 368: per-fs identifier */
u_int32_t dlfs_fsbtodb; /* 372: fsbtodb and dbtodsb shift constant */
u_int32_t dlfs_resvseg; /* 376: segments reserved for the cleaner */
int8_t dlfs_pad[128]; /* 380: round to 512 bytes */
/* Checksum -- last valid disk field. */
u_int32_t dlfs_cksum; /* 508: checksum for superblock checking */
};
struct dlfs64 {
u_int32_t dlfs_magic; /* 0: magic number */
u_int32_t dlfs_version; /* 4: version number (2) */
u_int64_t dlfs_size; /* 8: number of frags in fs (v2) */
u_int64_t dlfs_dsize; /* 16: number of disk blocks in fs */
u_int32_t dlfs_ssize; /* 24: number of bytes per segment (v2) */
u_int32_t dlfs_bsize; /* 28: file system block size */
u_int32_t dlfs_fsize; /* 32: size of frag blocks in fs */
u_int32_t dlfs_frag; /* 36: number of frags in a block in fs */
/* Checkpoint region. */
u_int64_t dlfs_freehd; /* 40: start of the free inode list */
u_int64_t dlfs_nfiles; /* 48: number of allocated inodes */
int64_t dlfs_bfree; /* 56: number of free frags */
int64_t dlfs_avail; /* 64: blocks available for writing */
int64_t dlfs_idaddr; /* 72: inode file disk address */
int32_t dlfs_uinodes; /* 80: inodes in cache not yet on disk */
u_int32_t dlfs_unused_0; /* 84: not used */
int64_t dlfs_lastseg; /* 88: address of last segment written */
int64_t dlfs_nextseg; /* 96: address of next segment to write */
int64_t dlfs_curseg; /* 104: current segment being written */
int64_t dlfs_offset; /* 112: offset in curseg for next partial */
int64_t dlfs_lastpseg; /* 120: address of last partial written */
u_int32_t dlfs_inopf; /* 128: inodes per frag */
/* These are configuration parameters. */
u_int32_t dlfs_minfree; /* 132: minimum percentage of free blocks */
/* These fields can be computed from the others. */
u_int64_t dlfs_maxfilesize; /* 136: maximum representable file size */
u_int32_t dlfs_fsbpseg; /* 144: frags (fsb) per segment */
u_int32_t dlfs_inopb; /* 148: inodes per block */
u_int32_t dlfs_ifpb; /* 152: IFILE entries per block */
u_int32_t dlfs_sepb; /* 156: SEGUSE entries per block */
u_int32_t dlfs_nindir; /* 160: indirect pointers per block */
u_int32_t dlfs_nseg; /* 164: number of segments */
u_int32_t dlfs_nspf; /* 168: number of sectors per fragment */
u_int32_t dlfs_cleansz; /* 172: cleaner info size in blocks */
u_int32_t dlfs_segtabsz; /* 176: segment table size in blocks */
u_int32_t dlfs_bshift; /* 180: calc block number from file offset */
u_int32_t dlfs_ffshift; /* 184: fast mult/div for frag from file */
u_int32_t dlfs_fbshift; /* 188: fast mult/div for frag from block */
u_int64_t dlfs_bmask; /* 192: calc block offset from file offset */
u_int64_t dlfs_ffmask; /* 200: calc frag offset from file offset */
u_int64_t dlfs_fbmask; /* 208: calc frag offset from block offset */
u_int32_t dlfs_blktodb; /* 216: blktodb and dbtoblk shift constant */
u_int32_t dlfs_sushift; /* 220: fast mult/div for segusage table */
/* 224: superblock disk offsets */
int64_t dlfs_sboffs[LFS_MAXNUMSB];
int32_t dlfs_maxsymlinklen; /* 304: max len of an internal symlink */
u_int32_t dlfs_nclean; /* 308: Number of clean segments */
u_char dlfs_fsmnt[MNAMELEN]; /* 312: name mounted on */
u_int16_t dlfs_pflags; /* 402: file system persistent flags */
int32_t dlfs_dmeta; /* 404: total number of dirty summaries */
u_int32_t dlfs_minfreeseg; /* 408: segments not counted in bfree */
u_int32_t dlfs_sumsize; /* 412: size of summary blocks */
u_int32_t dlfs_ibsize; /* 416: size of inode blocks */
u_int32_t dlfs_inodefmt; /* 420: inode format version */
u_int64_t dlfs_serial; /* 424: serial number */
int64_t dlfs_s0addr; /* 432: start of segment 0 */
u_int64_t dlfs_tstamp; /* 440: time stamp */
u_int32_t dlfs_interleave; /* 448: segment interleave */
u_int32_t dlfs_ident; /* 452: per-fs identifier */
u_int32_t dlfs_fsbtodb; /* 456: fsbtodb and dbtodsb shift constant */
u_int32_t dlfs_resvseg; /* 460: segments reserved for the cleaner */
int8_t dlfs_pad[44]; /* 464: round to 512 bytes */
/* Checksum -- last valid disk field. */
u_int32_t dlfs_cksum; /* 508: checksum for superblock checking */
};
/* Type used for the inode bitmap */
typedef u_int32_t lfs_bm_t;
/*
* Linked list of segments whose byte count needs updating following a
* file truncation.
*/
struct segdelta {
long segnum;
size_t num;
LIST_ENTRY(segdelta) list;
};
/*
* In-memory super block.
*/
struct lfs {
union { /* on-disk parameters */
struct dlfs u_32;
struct dlfs64 u_64;
} lfs_dlfs_u;
/* These fields are set at mount time and are meaningless on disk. */
unsigned lfs_is64 : 1, /* are we lfs64 or lfs32? */
lfs_dobyteswap : 1, /* are we opposite-endian? */
lfs_hasolddirfmt : 1; /* dir entries have no d_type */
struct segment *lfs_sp; /* current segment being written */
struct vnode *lfs_ivnode; /* vnode for the ifile */
u_int32_t lfs_seglock; /* single-thread the segment writer */
pid_t lfs_lockpid; /* pid of lock holder */
lwpid_t lfs_locklwp; /* lwp of lock holder */
u_int32_t lfs_iocount; /* number of ios pending */
u_int32_t lfs_writer; /* don't allow any dirops to start */
u_int32_t lfs_dirops; /* count of active directory ops */
u_int32_t lfs_dirvcount; /* count of VDIROP nodes in this fs */
u_int32_t lfs_doifile; /* Write ifile blocks on next write */
u_int32_t lfs_nactive; /* Number of segments since last ckp */
int8_t lfs_fmod; /* super block modified flag */
int8_t lfs_ronly; /* mounted read-only flag */
#define LFS_NOTYET 0x01
#define LFS_IFDIRTY 0x02
#define LFS_WARNED 0x04
#define LFS_UNDIROP 0x08
int8_t lfs_flags; /* currently unused flag */
u_int16_t lfs_activesb; /* toggle between superblocks */
daddr_t lfs_sbactive; /* disk address of current sb write */
struct vnode *lfs_flushvp; /* vnode being flushed */
int lfs_flushvp_fakevref; /* fake vref count for flushvp */
struct vnode *lfs_unlockvp; /* being inactivated in lfs_segunlock */
u_int32_t lfs_diropwait; /* # procs waiting on dirop flush */
size_t lfs_devbsize; /* Device block size */
size_t lfs_devbshift; /* Device block shift */
krwlock_t lfs_fraglock;
krwlock_t lfs_iflock; /* Ifile lock */
kcondvar_t lfs_stopcv; /* Wrap lock */
struct lwp *lfs_stoplwp;
pid_t lfs_rfpid; /* Process ID of roll-forward agent */
int lfs_nadirop; /* number of active dirop nodes */
long lfs_ravail; /* blocks pre-reserved for writing */
long lfs_favail; /* blocks pre-reserved for writing */
struct lfs_res_blk *lfs_resblk; /* Reserved memory for pageout */
TAILQ_HEAD(, inode) lfs_dchainhd; /* dirop vnodes */
TAILQ_HEAD(, inode) lfs_pchainhd; /* paging vnodes */
#define LFS_RESHASH_WIDTH 17
LIST_HEAD(, lfs_res_blk) lfs_reshash[LFS_RESHASH_WIDTH];
int lfs_pdflush; /* pagedaemon wants us to flush */
u_int32_t **lfs_suflags; /* Segment use flags */
#ifdef _KERNEL
struct pool lfs_clpool; /* Pool for struct lfs_cluster */
struct pool lfs_bpppool; /* Pool for bpp */
struct pool lfs_segpool; /* Pool for struct segment */
#endif /* _KERNEL */
#define LFS_MAX_CLEANIND 64
daddr_t lfs_cleanint[LFS_MAX_CLEANIND]; /* Active cleaning intervals */
int lfs_cleanind; /* Index into intervals */
int lfs_sleepers; /* # procs sleeping this fs */
int lfs_pages; /* dirty pages blaming this fs */
lfs_bm_t *lfs_ino_bitmap; /* Inuse inodes bitmap */
int lfs_nowrap; /* Suspend log wrap */
int lfs_wrappass; /* Allow first log wrap requester to pass */
int lfs_wrapstatus; /* Wrap status */
int lfs_reclino; /* Inode being reclaimed */
daddr_t lfs_startseg; /* Segment we started writing at */
LIST_HEAD(, segdelta) lfs_segdhd; /* List of pending trunc accounting events */
#ifdef _KERNEL
/* ULFS-level information */
u_int32_t um_flags; /* ULFS flags (below) */
u_long um_nindir; /* indirect ptrs per block */
u_long um_lognindir; /* log2 of um_nindir */
u_long um_bptrtodb; /* indir ptr to disk block */
u_long um_seqinc; /* inc between seq blocks */
int um_maxsymlinklen;
int um_dirblksiz;
u_int64_t um_maxfilesize;
/* Stuff used by quota2 code, not currently operable */
unsigned lfs_use_quota2 : 1;
uint32_t lfs_quota_magic;
uint8_t lfs_quota_flags;
uint64_t lfs_quotaino[2];
/* Sleep address replacing &lfs_avail inside the on-disk superblock */
/* XXX: should be replaced with a condvar */
int lfs_availsleep;
/* This one replaces &lfs_nextseg... all ditto */
int lfs_nextsegsleep;
#endif
};
/*
* Structures used by lfs_bmapv and lfs_markv to communicate information
* about inodes and data blocks.
*/
typedef struct block_info {
u_int64_t bi_inode; /* inode # */
int64_t bi_lbn; /* logical block w/in file */
int64_t bi_daddr; /* disk address of block */
u_int64_t bi_segcreate; /* origin segment create time */
int bi_version; /* file version number */
int bi_size; /* size of the block (if fragment) */
void *bi_bp; /* data buffer */
} BLOCK_INFO;
/* Compatibility for 7.0 binaries */
typedef struct block_info_70 {
u_int32_t bi_inode; /* inode # */
int32_t bi_lbn; /* logical block w/in file */
int32_t bi_daddr; /* disk address of block */
u_int64_t bi_segcreate; /* origin segment create time */
int bi_version; /* file version number */
void *bi_bp; /* data buffer */
int bi_size; /* size of the block (if fragment) */
} BLOCK_INFO_70;
/* Compatibility for 1.5 binaries */
typedef struct block_info_15 {
u_int32_t bi_inode; /* inode # */
int32_t bi_lbn; /* logical block w/in file */
int32_t bi_daddr; /* disk address of block */
u_int32_t bi_segcreate; /* origin segment create time */
int bi_version; /* file version number */
void *bi_bp; /* data buffer */
int bi_size; /* size of the block (if fragment) */
} BLOCK_INFO_15;
/*
* 32/64-bit-clean pointer to block pointers. This points into
* already-existing storage; it is mostly used to access the block
* pointers following a FINFO.
*/
union lfs_blocks {
int64_t *b64;
int32_t *b32;
};
/* In-memory description of a segment about to be written. */
struct segment {
struct lfs *fs; /* file system pointer */
struct buf **bpp; /* pointer to buffer array */
struct buf **cbpp; /* pointer to next available bp */
struct buf **start_bpp; /* pointer to first bp in this set */
struct buf *ibp; /* buffer pointer to inode page */
union lfs_dinode *idp; /* pointer to ifile dinode */
FINFO *fip; /* current fileinfo pointer */
struct vnode *vp; /* vnode being gathered */
void *segsum; /* segment summary info */
u_int32_t ninodes; /* number of inodes in this segment */
int32_t seg_bytes_left; /* bytes left in segment */
int32_t sum_bytes_left; /* bytes left in summary block */
u_int32_t seg_number; /* number of this segment */
union lfs_blocks start_lbp; /* beginning lbn for this set */
#define SEGM_CKP 0x0001 /* doing a checkpoint */
#define SEGM_CLEAN 0x0002 /* cleaner call; don't sort */
#define SEGM_SYNC 0x0004 /* wait for segment */
#define SEGM_PROT 0x0008 /* don't inactivate at segunlock */
#define SEGM_PAGEDAEMON 0x0010 /* pagedaemon called us */
#define SEGM_WRITERD 0x0020 /* LFS writed called us */
#define SEGM_FORCE_CKP 0x0040 /* Force checkpoint right away */
#define SEGM_RECLAIM 0x0080 /* Writing to reclaim vnode */
#define SEGM_SINGLE 0x0100 /* Opportunistic writevnodes */
u_int16_t seg_flags; /* run-time flags for this segment */
u_int32_t seg_iocount; /* number of ios pending */
int ndupino; /* number of duplicate inodes */
};
/* Statistics Counters */
struct lfs_stats { /* Must match sysctl list in lfs_vfsops.h ! */
u_int segsused;
u_int psegwrites;
u_int psyncwrites;
u_int pcleanwrites;
u_int blocktot;
u_int cleanblocks;
u_int ncheckpoints;
u_int nwrites;
u_int nsync_writes;
u_int wait_exceeded;
u_int write_exceeded;
u_int flush_invoked;
u_int vflush_invoked;
u_int clean_inlocked;
u_int clean_vnlocked;
u_int segs_reclaimed;
};
/* Fcntls to take the place of the lfs syscalls */
struct lfs_fcntl_markv {
BLOCK_INFO *blkiov; /* blocks to relocate */
int blkcnt; /* number of blocks (limited to 65536) */
};
#define LFCNSEGWAITALL _FCNR_FSPRIV('L', 14, struct timeval)
#define LFCNSEGWAIT _FCNR_FSPRIV('L', 15, struct timeval)
#define LFCNBMAPV _FCNRW_FSPRIV('L', 16, struct lfs_fcntl_markv)
#define LFCNMARKV _FCNRW_FSPRIV('L', 17, struct lfs_fcntl_markv)
#define LFCNRECLAIM _FCNO_FSPRIV('L', 4)
struct lfs_fhandle {
char space[28]; /* FHANDLE_SIZE_COMPAT (but used from userland too) */
};
#define LFCNREWIND _FCNR_FSPRIV('L', 6, int)
#define LFCNINVAL _FCNR_FSPRIV('L', 7, int)
#define LFCNRESIZE _FCNR_FSPRIV('L', 8, int)
#define LFCNWRAPSTOP _FCNR_FSPRIV('L', 9, int)
#define LFCNWRAPGO _FCNR_FSPRIV('L', 10, int)
#define LFCNIFILEFH _FCNW_FSPRIV('L', 11, struct lfs_fhandle)
#define LFCNWRAPPASS _FCNR_FSPRIV('L', 12, int)
# define LFS_WRAP_GOING 0x0
# define LFS_WRAP_WAITING 0x1
#define LFCNWRAPSTATUS _FCNW_FSPRIV('L', 13, int)
/* Debug segment lock */
#ifdef notyet
# define ASSERT_SEGLOCK(fs) KASSERT(LFS_SEGLOCK_HELD(fs))
# define ASSERT_NO_SEGLOCK(fs) KASSERT(!LFS_SEGLOCK_HELD(fs))
# define ASSERT_DUNNO_SEGLOCK(fs)
# define ASSERT_MAYBE_SEGLOCK(fs)
#else /* !notyet */
# define ASSERT_DUNNO_SEGLOCK(fs) \
DLOG((DLOG_SEG, "lfs func %s seglock wrong (%d)\n", __func__, \
LFS_SEGLOCK_HELD(fs)))
# define ASSERT_SEGLOCK(fs) do { \
if (!LFS_SEGLOCK_HELD(fs)) { \
DLOG((DLOG_SEG, "lfs func %s seglock wrong (0)\n", __func__)); \
} \
} while(0)
# define ASSERT_NO_SEGLOCK(fs) do { \
if (LFS_SEGLOCK_HELD(fs)) { \
DLOG((DLOG_SEG, "lfs func %s seglock wrong (1)\n", __func__)); \
} \
} while(0)
# define ASSERT_MAYBE_SEGLOCK(x)
#endif /* !notyet */
/*
* Arguments to mount LFS filesystems
*/
struct ulfs_args {
char *fspec; /* block special device to mount */
};
__BEGIN_DECLS
void lfs_itimes(struct inode *, const struct timespec *,
const struct timespec *, const struct timespec *);
__END_DECLS
#endif /* !_UFS_LFS_LFS_H_ */
|