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