static void
raw_read_queue(void *buf, daddr_t blkpos, size_t bytelen)
	/* bytelen:		 must be DEV_BSIZE aligned */
{
	static daddr_t rq_start;
	static char *rq_buf;

	if (rq_len) {
		if (bytelen && blkpos == rq_start + (ssize_t) btodb(rq_len)
				&& buf == rq_buf + rq_len) {
			rq_len += bytelen;
			return;
		} else {
#ifdef DEBUG_WITH_STDIO
			printf("raw_read_queue: read: buf %p, blk %d, len %d\n",
				 rq_buf, (int) rq_start, rq_len);
#endif
			RAW_READ(rq_buf, rq_start, rq_len);
		}
	}
	rq_buf = buf;
	rq_start = blkpos;
	rq_len = bytelen;
}
Exemple #2
0
/*
 * Read and check superblock.
 * If it is an LFS, save information from the superblock.
 */
int
try_lfs(void)
{
	struct ufs_info	*ufsinfo = &ufs_info;
	struct dlfs	sblk, sblk2;
	struct dlfs	*s = &sblk;
	daddr_t		sbpos;
	int		fsbshift;

#ifdef DEBUG_WITH_STDIO
	printf("trying LFS\n");
#endif
	sbpos =  btodb(LFS_LABELPAD);

	/* read primary superblock */
	for (;;) {
#ifdef DEBUG_WITH_STDIO
		printf("LFS: reading primary sblk at: 0x%x\n", (unsigned)sbpos);
#endif
		RAW_READ(&sblk, sbpos, sizeof sblk);

#ifdef DEBUG_WITH_STDIO
		printf("LFS: sblk: magic: 0x%x, version: %d\n",
			sblk.dlfs_magic, sblk.dlfs_version);
#endif

		if (sblk.dlfs_magic != LFS_MAGIC)
			return 1;

#ifdef DEBUG_WITH_STDIO
		printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n",
		    sblk.dlfs_bsize, sblk.dlfs_fsize,
		    sblk.dlfs_bshift, sblk.dlfs_blktodb, sblk.dlfs_fsbtodb,
		    sblk.dlfs_inopf, sblk.dlfs_inopb);
#endif
		if ((fsi_lfs.version = sblk.dlfs_version) == 1) {
			fsbshift = 0;
			break;
		} else {
			daddr_t	sbpos1;
#if 0
			fsbshift = sblk.dlfs_bshift - sblk.dlfs_blktodb + sblk.dlfs_fsbtodb - DEV_BSHIFT;
#endif
			fsbshift = sblk.dlfs_fsbtodb;
			sbpos1 = sblk.dlfs_sboffs[0] << fsbshift;
			if (sbpos == sbpos1)
				break;
#ifdef DEBUG_WITH_STDIO
			printf("LFS: correcting primary sblk location\n");
#endif
			sbpos = sbpos1;
		}
	}

#ifdef DEBUG_WITH_STDIO
	printf("fsbshift: %d\n", fsbshift);
	printf("sboff[1]: %d\n", sblk.dlfs_sboffs[1]);
#endif

	if (sblk.dlfs_sboffs[1] > 0) {
#ifdef DEBUG_WITH_STDIO
		printf("LFS: reading secondary sblk at: 0x%x\n",
		    sblk.dlfs_sboffs[1] << fsbshift);
#endif
		/* read secondary superblock */
		RAW_READ(&sblk2, (daddr_t) sblk.dlfs_sboffs[1] << fsbshift,
		    sizeof sblk2);

#ifdef DEBUG_WITH_STDIO
		printf("LFS: sblk2: magic: 0x%x, version: %d\n",
			sblk2.dlfs_magic, sblk2.dlfs_version);
#endif

		if (sblk2.dlfs_magic == LFS_MAGIC) {
			if (fsi_lfs.version == 1) {
				if (sblk.dlfs_otstamp > sblk2.dlfs_otstamp)
					s = &sblk2;
			} else {
				if (sblk.dlfs_serial > sblk2.dlfs_serial)
					s = &sblk2;
			}
		}
	}

	/* This partition looks like an LFS. */
#if 0
	fsi.get_inode = get_lfs_inode;
#endif
	/*
	 * version 1: disk addr is in disk sector --- no shifting
	 * version 2: disk addr is in fragment
	 */
	fsi.fsbtodb = fsbshift;

	/* Get information from the superblock. */
	fsi.bsize = s->dlfs_bsize;
	fsi.nindir = s->dlfs_nindir;
	fsi_lfs.idaddr = s->dlfs_idaddr;
	fsi_lfs.ibsize = (fsi_lfs.version == 1) ? s->dlfs_bsize : s->dlfs_fsize;

	/*
	 * version 1: number of inode per block
	 * version 2: number of inode per fragment (but in dlfs_inopb)
	 */
	fsi_lfs.inopb = s->dlfs_inopb;

	fsi_lfs.ifpb = s->dlfs_ifpb;
	fsi_lfs.ioffset = s->dlfs_cleansz + s->dlfs_segtabsz;

	/* ifile is always used to look-up other inodes, so keep its inode. */
	if (get_lfs_inode(LFS_IFILE_INUM, (union ufs_dinode *)&ifile_dinode))
		return 1;	/* OOPS, failed to find inode of ifile! */

	fsi.fstype = UFSTYPE_LFS;

	return 0;
}
Exemple #3
0
/*
 * Get inode from disk.
 */
int
get_lfs_inode(ino32_t ino, union ufs_dinode *dibuf)
{
	struct ufs_info *ufsinfo = &ufs_info;
	daddr_t daddr;
	char *buf = alloca(fsi.bsize);
	struct ulfs1_dinode *di, *diend;
	int i;

	/* Get fs block which contains the specified inode. */
	if (ino == LFS_IFILE_INUM)
		daddr = fsi_lfs.idaddr;
	else {
#ifdef DEBUG_WITH_STDIO
		printf("LFS: ino: %d\nifpb: %d, bsize: %d\n",
			ino, fsi_lfs.ifpb, fsi.bsize);
#endif
		ufs_read((union ufs_dinode *) &ifile_dinode, buf,
			 ino / fsi_lfs.ifpb + fsi_lfs.ioffset,
			 fsi.bsize);
		i = ino % fsi_lfs.ifpb;
		daddr = (fsi_lfs.version == 1) ?
		    ((IFILE_V1 *) buf + i)->if_daddr
		    : ((IFILE *) buf + i)->if_daddr;
	}
#ifdef DEBUG_WITH_STDIO
	printf("LFS(%d): daddr: %d\n", ino, (int) daddr);
#endif

	if (daddr == LFS_UNUSED_DADDR)
		return 1;

	/* Read the inode block. */
	RAW_READ(buf, daddr << fsi.fsbtodb, fsi_lfs.ibsize);

	/* Search for the inode. */
	di = (struct ulfs1_dinode *) buf;
	diend = di + fsi_lfs.inopb;

	for ( ; di < diend; di++)
		if (di->di_inumber == ino)
			goto found;
	/* not found */
	return 1;

found:
#ifdef DEBUG_WITH_STDIO
	printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, db[0] %d\n",
		ino, di->di_mode, di->di_nlink, di->di_inumber,
		(int) di->di_size, di->di_uid, di->di_db[0]);
#endif

#if 0	/* currently UFS1 only */
#if defined(USE_UFS1) && defined(USE_UFS2)
	/* XXX for DI_SIZE() macro */
	if (ufsinfo->ufstype != UFSTYPE_UFS1)
		di->di1.di_size = di->si2.di_size;
#endif
#endif

	dibuf->dil1 = *di;

	return 0;
}
static int
ufs_read_indirect(daddr_t blk, int level, void **buf, unsigned *poff, size_t count)
	/* poff:	 position in block */
{
	struct ufs_info *ufsinfo = &fs;
	size_t bsize = ufsinfo->bsize;
	void *idbuf = alloca(bsize);
#ifdef USE_UFS1
	int32_t *idbuf1 = idbuf;
#endif
#ifdef USE_UFS2
	int64_t *idbuf2 = idbuf;
#endif
	daddr_t pos;
	unsigned off = *poff;
	unsigned b;

#ifdef DEBUG_WITH_STDIO
	printf("ufs_read_indirect: off: %d, count %u\n", off, count);
#endif
	if (off) {
		unsigned subindirsize = 1, indirsize;
		int i;

		for (i = level; i > 0; i--)
			subindirsize *= ufsinfo->nindir;
		indirsize = subindirsize * ufsinfo->nindir;
		if (off >= indirsize) {
			/* no need to read any data */
			*poff = off - indirsize;
			return 0;
		}

		b = off / subindirsize;
		off -= b * subindirsize;
		*poff = 0;
	} else
		b = 0;

	/* read the indirect block */
	RAW_READ(idbuf, blk << ufsinfo->fsbtodb, bsize);

	for ( ; b < ufsinfo->nindir && count > 0; b++) {
#if defined(USE_UFS1) && defined(USE_UFS2)
		if (ufsinfo->ufstype == UFSTYPE_UFS1)
#endif
#ifdef USE_UFS1
			pos = idbuf1[b];
#endif
#if defined(USE_UFS1) && defined(USE_UFS2)
		else
#endif
#ifdef USE_UFS2
			pos = idbuf2[b];
#endif

		if (level)
			count = ufs_read_indirect(pos, level - 1, buf, &off, count);
		else {
#if 0
			printf("ufs_read: read: blk: %d\n",
				(int) pos << ufsinfo->fsbtodb);
#endif
			raw_read_queue(*buf, pos << ufsinfo->fsbtodb, bsize);
			*buf += bsize;
			count -= bsize;
		}
	}

	return count;
}