Home | History | Annotate | Line # | Download | only in boot_ufs
readufs_lfs.c revision 1.14.2.1
      1  1.14.2.1     rmind /*	$NetBSD: readufs_lfs.c,v 1.14.2.1 2014/05/18 17:45:29 rmind 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.13  christos static struct ulfs1_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.2   minoura 				if (sblk.dlfs_otstamp > sblk2.dlfs_otstamp)
    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.14.2.1     rmind 	/* 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.13  christos 	struct ulfs1_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.4     itohy 		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.2   minoura 		    : ((IFILE *) 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.13  christos 	di = (struct ulfs1_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.13  christos 	dibuf->dil1 = *di;
    223       1.1   minoura 
    224       1.1   minoura 	return 0;
    225       1.1   minoura }
    226