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