readufs_lfs.c revision 1.18 1 1.18 isaki /* $NetBSD: readufs_lfs.c,v 1.18 2024/01/07 07:58:33 isaki Exp $ */
2 1.5 itohy /* from Id: readufs_lfs.c,v 1.7 2003/10/15 14:16:58 itohy Exp */
3 1.1 minoura
4 1.1 minoura /*
5 1.1 minoura * FS specific support for 4.4BSD Log-structured Filesystem
6 1.1 minoura *
7 1.12 itohy * Written in 1999, 2002, 2003 by ITOH Yasufumi.
8 1.1 minoura * Public domain.
9 1.1 minoura *
10 1.1 minoura * Intended to be used for boot programs (first stage).
11 1.1 minoura * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
12 1.1 minoura */
13 1.1 minoura
14 1.4 itohy #include "readufs.h"
15 1.4 itohy
16 1.1 minoura #include <sys/mount.h>
17 1.1 minoura
18 1.4 itohy #ifndef USE_UFS1
19 1.4 itohy #error LFS currently requires USE_UFS1
20 1.4 itohy #endif
21 1.1 minoura
22 1.9 dsl static int get_lfs_inode(ino32_t ino, union ufs_dinode *dibuf);
23 1.1 minoura
24 1.17 christos static struct lfs32_dinode ifile_dinode;
25 1.1 minoura
26 1.1 minoura #define fsi (*ufsinfo)
27 1.1 minoura #define fsi_lfs fsi.fs_u.u_lfs
28 1.1 minoura
29 1.1 minoura /*
30 1.1 minoura * Read and check superblock.
31 1.1 minoura * If it is an LFS, save information from the superblock.
32 1.1 minoura */
33 1.1 minoura int
34 1.11 cegger try_lfs(void)
35 1.1 minoura {
36 1.2 minoura struct ufs_info *ufsinfo = &ufs_info;
37 1.1 minoura struct dlfs sblk, sblk2;
38 1.1 minoura struct dlfs *s = &sblk;
39 1.4 itohy daddr_t sbpos;
40 1.2 minoura int fsbshift;
41 1.1 minoura
42 1.1 minoura #ifdef DEBUG_WITH_STDIO
43 1.1 minoura printf("trying LFS\n");
44 1.1 minoura #endif
45 1.2 minoura sbpos = btodb(LFS_LABELPAD);
46 1.2 minoura
47 1.1 minoura /* read primary superblock */
48 1.2 minoura for (;;) {
49 1.2 minoura #ifdef DEBUG_WITH_STDIO
50 1.4 itohy printf("LFS: reading primary sblk at: 0x%x\n", (unsigned)sbpos);
51 1.2 minoura #endif
52 1.2 minoura RAW_READ(&sblk, sbpos, sizeof sblk);
53 1.1 minoura
54 1.1 minoura #ifdef DEBUG_WITH_STDIO
55 1.2 minoura printf("LFS: sblk: magic: 0x%x, version: %d\n",
56 1.2 minoura sblk.dlfs_magic, sblk.dlfs_version);
57 1.1 minoura #endif
58 1.1 minoura
59 1.2 minoura if (sblk.dlfs_magic != LFS_MAGIC)
60 1.2 minoura return 1;
61 1.2 minoura
62 1.2 minoura #ifdef DEBUG_WITH_STDIO
63 1.2 minoura printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n",
64 1.2 minoura sblk.dlfs_bsize, sblk.dlfs_fsize,
65 1.2 minoura sblk.dlfs_bshift, sblk.dlfs_blktodb, sblk.dlfs_fsbtodb,
66 1.2 minoura sblk.dlfs_inopf, sblk.dlfs_inopb);
67 1.2 minoura #endif
68 1.2 minoura if ((fsi_lfs.version = sblk.dlfs_version) == 1) {
69 1.2 minoura fsbshift = 0;
70 1.2 minoura break;
71 1.2 minoura } else {
72 1.3 fvdl daddr_t sbpos1;
73 1.2 minoura #if 0
74 1.2 minoura fsbshift = sblk.dlfs_bshift - sblk.dlfs_blktodb + sblk.dlfs_fsbtodb - DEV_BSHIFT;
75 1.2 minoura #endif
76 1.2 minoura fsbshift = sblk.dlfs_fsbtodb;
77 1.2 minoura sbpos1 = sblk.dlfs_sboffs[0] << fsbshift;
78 1.2 minoura if (sbpos == sbpos1)
79 1.2 minoura break;
80 1.2 minoura #ifdef DEBUG_WITH_STDIO
81 1.2 minoura printf("LFS: correcting primary sblk location\n");
82 1.2 minoura #endif
83 1.2 minoura sbpos = sbpos1;
84 1.2 minoura }
85 1.2 minoura }
86 1.1 minoura
87 1.1 minoura #ifdef DEBUG_WITH_STDIO
88 1.2 minoura printf("fsbshift: %d\n", fsbshift);
89 1.1 minoura printf("sboff[1]: %d\n", sblk.dlfs_sboffs[1]);
90 1.1 minoura #endif
91 1.1 minoura
92 1.1 minoura if (sblk.dlfs_sboffs[1] > 0) {
93 1.2 minoura #ifdef DEBUG_WITH_STDIO
94 1.2 minoura printf("LFS: reading secondary sblk at: 0x%x\n",
95 1.2 minoura sblk.dlfs_sboffs[1] << fsbshift);
96 1.2 minoura #endif
97 1.1 minoura /* read secondary superblock */
98 1.4 itohy RAW_READ(&sblk2, (daddr_t) sblk.dlfs_sboffs[1] << fsbshift,
99 1.4 itohy sizeof sblk2);
100 1.1 minoura
101 1.1 minoura #ifdef DEBUG_WITH_STDIO
102 1.1 minoura printf("LFS: sblk2: magic: 0x%x, version: %d\n",
103 1.1 minoura sblk2.dlfs_magic, sblk2.dlfs_version);
104 1.1 minoura #endif
105 1.1 minoura
106 1.2 minoura if (sblk2.dlfs_magic == LFS_MAGIC) {
107 1.2 minoura if (fsi_lfs.version == 1) {
108 1.16 christos if (sblk.dlfs_inopf > sblk2.dlfs_inopf)
109 1.2 minoura s = &sblk2;
110 1.2 minoura } else {
111 1.2 minoura if (sblk.dlfs_serial > sblk2.dlfs_serial)
112 1.2 minoura s = &sblk2;
113 1.2 minoura }
114 1.2 minoura }
115 1.1 minoura }
116 1.1 minoura
117 1.1 minoura /* This partition looks like an LFS. */
118 1.1 minoura fsi.get_inode = get_lfs_inode;
119 1.2 minoura /*
120 1.2 minoura * version 1: disk addr is in disk sector --- no shifting
121 1.2 minoura * version 2: disk addr is in fragment
122 1.2 minoura */
123 1.2 minoura fsi.fsbtodb = fsbshift;
124 1.1 minoura
125 1.1 minoura /* Get information from the superblock. */
126 1.1 minoura fsi.bsize = s->dlfs_bsize;
127 1.1 minoura fsi.nindir = s->dlfs_nindir;
128 1.2 minoura fsi_lfs.idaddr = s->dlfs_idaddr;
129 1.2 minoura #if 0
130 1.2 minoura fsi_lfs.ibsize = (fsi_lfs.version == 1) ? s->dlfs_bsize : s->dlfs_fsize;
131 1.2 minoura #else /* simplify calculation to reduce code size */
132 1.15 wiz /* use fsi.bsize (larger than needed for v2, but probably no harm) */
133 1.2 minoura #endif
134 1.1 minoura
135 1.2 minoura /*
136 1.2 minoura * version 1: number of inode per block
137 1.2 minoura * version 2: number of inode per fragment (but in dlfs_inopb)
138 1.2 minoura */
139 1.1 minoura fsi_lfs.inopb = s->dlfs_inopb;
140 1.2 minoura
141 1.1 minoura fsi_lfs.ifpb = s->dlfs_ifpb;
142 1.2 minoura fsi_lfs.ioffset = s->dlfs_cleansz + s->dlfs_segtabsz;
143 1.1 minoura
144 1.1 minoura /* ifile is always used to look-up other inodes, so keep its inode. */
145 1.4 itohy if (get_lfs_inode(LFS_IFILE_INUM, (union ufs_dinode *)&ifile_dinode))
146 1.1 minoura return 1; /* OOPS, failed to find inode of ifile! */
147 1.1 minoura
148 1.1 minoura fsi.fstype = UFSTYPE_LFS;
149 1.1 minoura
150 1.1 minoura return 0;
151 1.1 minoura }
152 1.1 minoura
153 1.1 minoura /*
154 1.1 minoura * Get inode from disk.
155 1.1 minoura */
156 1.1 minoura static int
157 1.10 dsl get_lfs_inode(ino32_t ino, union ufs_dinode *dibuf)
158 1.1 minoura {
159 1.1 minoura struct ufs_info *ufsinfo = &ufs_info;
160 1.3 fvdl daddr_t daddr;
161 1.1 minoura char *buf = alloca(fsi.bsize);
162 1.17 christos struct lfs32_dinode *di, *diend;
163 1.2 minoura int i;
164 1.1 minoura
165 1.1 minoura /* Get fs block which contains the specified inode. */
166 1.1 minoura if (ino == LFS_IFILE_INUM)
167 1.1 minoura daddr = fsi_lfs.idaddr;
168 1.1 minoura else {
169 1.1 minoura #ifdef DEBUG_WITH_STDIO
170 1.2 minoura printf("LFS: ino: %d\nifpb: %d, bsize: %d\n",
171 1.2 minoura ino, fsi_lfs.ifpb, fsi.bsize);
172 1.1 minoura #endif
173 1.18 isaki ufs_read((union ufs_dinode *) &ifile_dinode, buf,
174 1.2 minoura ino / fsi_lfs.ifpb + fsi_lfs.ioffset,
175 1.1 minoura fsi.bsize);
176 1.2 minoura i = ino % fsi_lfs.ifpb;
177 1.2 minoura daddr = (fsi_lfs.version == 1) ?
178 1.2 minoura ((IFILE_V1 *) buf + i)->if_daddr
179 1.17 christos : ((IFILE32 *) buf + i)->if_daddr;
180 1.1 minoura }
181 1.1 minoura #ifdef DEBUG_WITH_STDIO
182 1.4 itohy printf("LFS(%d): daddr: %d\n", ino, (int) daddr);
183 1.1 minoura #endif
184 1.1 minoura
185 1.1 minoura if (daddr == LFS_UNUSED_DADDR)
186 1.1 minoura return 1;
187 1.1 minoura
188 1.1 minoura /* Read the inode block. */
189 1.2 minoura RAW_READ(buf, daddr << fsi.fsbtodb,
190 1.2 minoura #if 0
191 1.2 minoura fsi_lfs.ibsize
192 1.2 minoura #else /* simplify calculation to reduce code size */
193 1.2 minoura fsi.bsize
194 1.2 minoura #endif
195 1.2 minoura );
196 1.1 minoura
197 1.1 minoura /* Search for the inode. */
198 1.17 christos di = (struct lfs32_dinode *) buf;
199 1.2 minoura diend = di + fsi_lfs.inopb;
200 1.1 minoura
201 1.2 minoura for ( ; di < diend; di++)
202 1.1 minoura if (di->di_inumber == ino)
203 1.1 minoura goto found;
204 1.1 minoura /* not found */
205 1.1 minoura return 1;
206 1.1 minoura
207 1.1 minoura found:
208 1.1 minoura #ifdef DEBUG_WITH_STDIO
209 1.5 itohy printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, db[0] %d\n",
210 1.1 minoura ino, di->di_mode, di->di_nlink, di->di_inumber,
211 1.5 itohy (int) di->di_size, di->di_uid, di->di_db[0]);
212 1.4 itohy #endif
213 1.4 itohy
214 1.4 itohy #if 0 /* currently UFS1 only */
215 1.4 itohy #if defined(USE_UFS1) && defined(USE_UFS2)
216 1.4 itohy /* XXX for DI_SIZE() macro */
217 1.4 itohy if (ufsinfo->ufstype != UFSTYPE_UFS1)
218 1.4 itohy di->di1.di_size = di->si2.di_size;
219 1.4 itohy #endif
220 1.1 minoura #endif
221 1.1 minoura
222 1.17 christos dibuf->dil32 = *di;
223 1.1 minoura
224 1.1 minoura return 0;
225 1.1 minoura }
226