1 /* $NetBSD: readufs_lfs.c,v 1.5 2009/03/18 10:22:28 cegger Exp $ */
2 /* from Id: readufs_lfs.c,v 1.8 2003/12/16 13:54:11 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 struct ufs1_dinode ifile_dinode
;
25 #define fsi (*ufsinfo)
26 #define fsi_lfs fsi.fs_u.u_lfs
29 * Read and check superblock.
30 * If it is an LFS, save information from the superblock.
35 struct ufs_info
*ufsinfo
= &ufs_info
;
36 struct dlfs sblk
, sblk2
;
37 struct dlfs
*s
= &sblk
;
41 #ifdef DEBUG_WITH_STDIO
42 printf("trying LFS\n");
44 sbpos
= btodb(LFS_LABELPAD
);
46 /* read primary superblock */
48 #ifdef DEBUG_WITH_STDIO
49 printf("LFS: reading primary sblk at: 0x%x\n", (unsigned)sbpos
);
51 RAW_READ(&sblk
, sbpos
, sizeof sblk
);
53 #ifdef DEBUG_WITH_STDIO
54 printf("LFS: sblk: magic: 0x%x, version: %d\n",
55 sblk
.dlfs_magic
, sblk
.dlfs_version
);
58 if (sblk
.dlfs_magic
!= LFS_MAGIC
)
61 #ifdef DEBUG_WITH_STDIO
62 printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n",
63 sblk
.dlfs_bsize
, sblk
.dlfs_fsize
,
64 sblk
.dlfs_bshift
, sblk
.dlfs_blktodb
, sblk
.dlfs_fsbtodb
,
65 sblk
.dlfs_inopf
, sblk
.dlfs_inopb
);
67 if ((fsi_lfs
.version
= sblk
.dlfs_version
) == 1) {
73 fsbshift
= sblk
.dlfs_bshift
- sblk
.dlfs_blktodb
+ sblk
.dlfs_fsbtodb
- DEV_BSHIFT
;
75 fsbshift
= sblk
.dlfs_fsbtodb
;
76 sbpos1
= sblk
.dlfs_sboffs
[0] << fsbshift
;
79 #ifdef DEBUG_WITH_STDIO
80 printf("LFS: correcting primary sblk location\n");
86 #ifdef DEBUG_WITH_STDIO
87 printf("fsbshift: %d\n", fsbshift
);
88 printf("sboff[1]: %d\n", sblk
.dlfs_sboffs
[1]);
91 if (sblk
.dlfs_sboffs
[1] > 0) {
92 #ifdef DEBUG_WITH_STDIO
93 printf("LFS: reading secondary sblk at: 0x%x\n",
94 sblk
.dlfs_sboffs
[1] << fsbshift
);
96 /* read secondary superblock */
97 RAW_READ(&sblk2
, (daddr_t
) sblk
.dlfs_sboffs
[1] << fsbshift
,
100 #ifdef DEBUG_WITH_STDIO
101 printf("LFS: sblk2: magic: 0x%x, version: %d\n",
102 sblk2
.dlfs_magic
, sblk2
.dlfs_version
);
105 if (sblk2
.dlfs_magic
== LFS_MAGIC
) {
106 if (fsi_lfs
.version
== 1) {
107 if (sblk
.dlfs_otstamp
> sblk2
.dlfs_otstamp
)
110 if (sblk
.dlfs_serial
> sblk2
.dlfs_serial
)
116 /* This partition looks like an LFS. */
118 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
;
130 fsi_lfs
.ibsize
= (fsi_lfs
.version
== 1) ? s
->dlfs_bsize
: s
->dlfs_fsize
;
133 * version 1: number of inode per block
134 * version 2: number of inode per fragment (but in dlfs_inopb)
136 fsi_lfs
.inopb
= s
->dlfs_inopb
;
138 fsi_lfs
.ifpb
= s
->dlfs_ifpb
;
139 fsi_lfs
.ioffset
= s
->dlfs_cleansz
+ s
->dlfs_segtabsz
;
141 /* ifile is always used to look-up other inodes, so keep its inode. */
142 if (get_lfs_inode(LFS_IFILE_INUM
, (union ufs_dinode
*)&ifile_dinode
))
143 return 1; /* OOPS, failed to find inode of ifile! */
145 fsi
.fstype
= UFSTYPE_LFS
;
151 * Get inode from disk.
154 get_lfs_inode(ino32_t ino
, union ufs_dinode
*dibuf
)
156 struct ufs_info
*ufsinfo
= &ufs_info
;
158 char *buf
= alloca(fsi
.bsize
);
159 struct ufs1_dinode
*di
, *diend
;
162 /* Get fs block which contains the specified inode. */
163 if (ino
== LFS_IFILE_INUM
)
164 daddr
= fsi_lfs
.idaddr
;
166 #ifdef DEBUG_WITH_STDIO
167 printf("LFS: ino: %d\nifpb: %d, bsize: %d\n",
168 ino
, fsi_lfs
.ifpb
, fsi
.bsize
);
170 ufs_read((union ufs_dinode
*) &ifile_dinode
, buf
,
171 ino
/ fsi_lfs
.ifpb
+ fsi_lfs
.ioffset
,
173 i
= ino
% fsi_lfs
.ifpb
;
174 daddr
= (fsi_lfs
.version
== 1) ?
175 ((IFILE_V1
*) buf
+ i
)->if_daddr
176 : ((IFILE
*) buf
+ i
)->if_daddr
;
178 #ifdef DEBUG_WITH_STDIO
179 printf("LFS(%d): daddr: %d\n", ino
, (int) daddr
);
182 if (daddr
== LFS_UNUSED_DADDR
)
185 /* Read the inode block. */
186 RAW_READ(buf
, daddr
<< fsi
.fsbtodb
, fsi_lfs
.ibsize
);
188 /* Search for the inode. */
189 di
= (struct ufs1_dinode
*) buf
;
190 diend
= di
+ fsi_lfs
.inopb
;
192 for ( ; di
< diend
; di
++)
193 if (di
->di_inumber
== ino
)
199 #ifdef DEBUG_WITH_STDIO
200 printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, db[0] %d\n",
201 ino
, di
->di_mode
, di
->di_nlink
, di
->di_inumber
,
202 (int) di
->di_size
, di
->di_uid
, di
->di_db
[0]);
205 #if 0 /* currently UFS1 only */
206 #if defined(USE_UFS1) && defined(USE_UFS2)
207 /* XXX for DI_SIZE() macro */
208 if (ufsinfo
->ufstype
!= UFSTYPE_UFS1
)
209 di
->di1
.di_size
= di
->si2
.di_size
;