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