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