1 /* $NetBSD: readufs_lfs.c,v 1.10 2009/03/14 15:36:15 dsl Exp $ */
2 /* from Id: readufs_lfs.c,v 1.7 2003/10/15 14:16:58 itohy Exp */
5 * FS specific support for 4.4BSD Log-structured Filesystem
7 * Written in 1999, 2002, 2003 by ITOH Yasufumi (itohy@NetBSD.org).
10 * Intended to be used for boot programs (first stage).
11 * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
16 #include <sys/mount.h>
17 #include <ufs/lfs/lfs.h>
20 #error LFS currently requires USE_UFS1
23 static int get_lfs_inode(ino32_t ino
, union ufs_dinode
*dibuf
);
25 static struct ufs1_dinode ifile_dinode
;
27 #define fsi (*ufsinfo)
28 #define fsi_lfs fsi.fs_u.u_lfs
31 * Read and check superblock.
32 * If it is an LFS, save information from the superblock.
37 struct ufs_info
*ufsinfo
= &ufs_info
;
38 struct dlfs sblk
, sblk2
;
39 struct dlfs
*s
= &sblk
;
43 #ifdef DEBUG_WITH_STDIO
44 printf("trying LFS\n");
46 sbpos
= btodb(LFS_LABELPAD
);
48 /* read primary superblock */
50 #ifdef DEBUG_WITH_STDIO
51 printf("LFS: reading primary sblk at: 0x%x\n", (unsigned)sbpos
);
53 RAW_READ(&sblk
, sbpos
, sizeof sblk
);
55 #ifdef DEBUG_WITH_STDIO
56 printf("LFS: sblk: magic: 0x%x, version: %d\n",
57 sblk
.dlfs_magic
, sblk
.dlfs_version
);
60 if (sblk
.dlfs_magic
!= LFS_MAGIC
)
63 #ifdef DEBUG_WITH_STDIO
64 printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n",
65 sblk
.dlfs_bsize
, sblk
.dlfs_fsize
,
66 sblk
.dlfs_bshift
, sblk
.dlfs_blktodb
, sblk
.dlfs_fsbtodb
,
67 sblk
.dlfs_inopf
, sblk
.dlfs_inopb
);
69 if ((fsi_lfs
.version
= sblk
.dlfs_version
) == 1) {
75 fsbshift
= sblk
.dlfs_bshift
- sblk
.dlfs_blktodb
+ sblk
.dlfs_fsbtodb
- DEV_BSHIFT
;
77 fsbshift
= sblk
.dlfs_fsbtodb
;
78 sbpos1
= sblk
.dlfs_sboffs
[0] << fsbshift
;
81 #ifdef DEBUG_WITH_STDIO
82 printf("LFS: correcting primary sblk location\n");
88 #ifdef DEBUG_WITH_STDIO
89 printf("fsbshift: %d\n", fsbshift
);
90 printf("sboff[1]: %d\n", sblk
.dlfs_sboffs
[1]);
93 if (sblk
.dlfs_sboffs
[1] > 0) {
94 #ifdef DEBUG_WITH_STDIO
95 printf("LFS: reading secondary sblk at: 0x%x\n",
96 sblk
.dlfs_sboffs
[1] << fsbshift
);
98 /* read secondary superblock */
99 RAW_READ(&sblk2
, (daddr_t
) sblk
.dlfs_sboffs
[1] << fsbshift
,
102 #ifdef DEBUG_WITH_STDIO
103 printf("LFS: sblk2: magic: 0x%x, version: %d\n",
104 sblk2
.dlfs_magic
, sblk2
.dlfs_version
);
107 if (sblk2
.dlfs_magic
== LFS_MAGIC
) {
108 if (fsi_lfs
.version
== 1) {
109 if (sblk
.dlfs_otstamp
> sblk2
.dlfs_otstamp
)
112 if (sblk
.dlfs_serial
> sblk2
.dlfs_serial
)
118 /* This partition looks like an LFS. */
119 fsi
.get_inode
= get_lfs_inode
;
121 * version 1: disk addr is in disk sector --- no shifting
122 * version 2: disk addr is in fragment
124 fsi
.fsbtodb
= fsbshift
;
126 /* Get information from the superblock. */
127 fsi
.bsize
= s
->dlfs_bsize
;
128 fsi
.nindir
= s
->dlfs_nindir
;
129 fsi_lfs
.idaddr
= s
->dlfs_idaddr
;
131 fsi_lfs
.ibsize
= (fsi_lfs
.version
== 1) ? s
->dlfs_bsize
: s
->dlfs_fsize
;
132 #else /* simplify calculation to reduce code size */
133 /* use fsi.bsize (larger then needed for v2, but probably no harm) */
137 * version 1: number of inode per block
138 * version 2: number of inode per fragment (but in dlfs_inopb)
140 fsi_lfs
.inopb
= s
->dlfs_inopb
;
142 fsi_lfs
.ifpb
= s
->dlfs_ifpb
;
143 fsi_lfs
.ioffset
= s
->dlfs_cleansz
+ s
->dlfs_segtabsz
;
145 /* ifile is always used to look-up other inodes, so keep its inode. */
146 if (get_lfs_inode(LFS_IFILE_INUM
, (union ufs_dinode
*)&ifile_dinode
))
147 return 1; /* OOPS, failed to find inode of ifile! */
149 fsi
.fstype
= UFSTYPE_LFS
;
155 * Get inode from disk.
158 get_lfs_inode(ino32_t ino
, union ufs_dinode
*dibuf
)
160 struct ufs_info
*ufsinfo
= &ufs_info
;
162 char *buf
= alloca(fsi
.bsize
);
163 struct ufs1_dinode
*di
, *diend
;
166 /* Get fs block which contains the specified inode. */
167 if (ino
== LFS_IFILE_INUM
)
168 daddr
= fsi_lfs
.idaddr
;
170 #ifdef DEBUG_WITH_STDIO
171 printf("LFS: ino: %d\nifpb: %d, bsize: %d\n",
172 ino
, fsi_lfs
.ifpb
, fsi
.bsize
);
174 ufs_read((union ufs_dinode
*) &ifile_dinode
, buf
,
175 ino
/ fsi_lfs
.ifpb
+ fsi_lfs
.ioffset
,
177 i
= ino
% fsi_lfs
.ifpb
;
178 daddr
= (fsi_lfs
.version
== 1) ?
179 ((IFILE_V1
*) buf
+ i
)->if_daddr
180 : ((IFILE
*) buf
+ i
)->if_daddr
;
182 #ifdef DEBUG_WITH_STDIO
183 printf("LFS(%d): daddr: %d\n", ino
, (int) daddr
);
186 if (daddr
== LFS_UNUSED_DADDR
)
189 /* Read the inode block. */
190 RAW_READ(buf
, daddr
<< fsi
.fsbtodb
,
193 #else /* simplify calculation to reduce code size */
198 /* Search for the inode. */
199 di
= (struct ufs1_dinode
*) buf
;
200 diend
= di
+ fsi_lfs
.inopb
;
202 for ( ; di
< diend
; di
++)
203 if (di
->di_inumber
== ino
)
209 #ifdef DEBUG_WITH_STDIO
210 printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, db[0] %d\n",
211 ino
, di
->di_mode
, di
->di_nlink
, di
->di_inumber
,
212 (int) di
->di_size
, di
->di_uid
, di
->di_db
[0]);
215 #if 0 /* currently UFS1 only */
216 #if defined(USE_UFS1) && defined(USE_UFS2)
217 /* XXX for DI_SIZE() macro */
218 if (ufsinfo
->ufstype
!= UFSTYPE_UFS1
)
219 di
->di1
.di_size
= di
->si2
.di_size
;