PERFORCE change 93014 for review
Kip Macy
kmacy at FreeBSD.org
Wed Mar 8 21:39:21 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=93014
Change 93014 by kmacy at kmacy_storage:sun4v_work on 2006/03/09 05:38:25
hacked up loader for booting off of solaris' UFS
Affected files ...
.. //depot/projects/kmacy_sun4v/src/lib/libstand/ufs.c#3 edit
Differences ...
==== //depot/projects/kmacy_sun4v/src/lib/libstand/ufs.c#3 (text+ko) ====
@@ -81,6 +81,7 @@
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/time.h>
+#include <sys/stddef.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
@@ -110,6 +111,134 @@
ufs_readdir
};
+typedef int32_t daddr32_t;
+typedef int32_t time32_t;
+typedef unsigned char uchar_t;
+#define MAXCSBUFS 32
+typedef struct _quad { int val[2]; } squad_t;
+struct solaris_fs {
+ uint32_t fs_link; /* linked list of file systems */
+ uint32_t fs_rolled; /* logging only: fs fully rolled */
+ daddr32_t fs_sblkno; /* addr of super-block in filesys */
+ daddr32_t fs_cblkno; /* offset of cyl-block in filesys */
+ daddr32_t fs_iblkno; /* offset of inode-blocks in filesys */
+ daddr32_t fs_dblkno; /* offset of first data after cg */
+ int32_t fs_cgoffset; /* cylinder group offset in cylinder */
+ int32_t fs_cgmask; /* used to calc mod fs_ntrak */
+ time32_t fs_time; /* last time written */
+ int32_t fs_size; /* number of blocks in fs */
+ int32_t fs_dsize; /* number of data blocks in fs */
+ int32_t fs_ncg; /* number of cylinder groups */
+ int32_t fs_bsize; /* size of basic blocks in fs */
+ int32_t fs_fsize; /* size of frag blocks in fs */
+ int32_t fs_frag; /* number of frags in a block in fs */
+/* these are configuration parameters */
+ int32_t fs_minfree; /* minimum percentage of free blocks */
+ int32_t fs_rotdelay; /* num of ms for optimal next block */
+ int32_t fs_rps; /* disk revolutions per second */
+/* these fields can be computed from the others */
+ int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
+ int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
+ int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
+ int32_t fs_fshift; /* ``numfrags'' calc number of frags */
+/* these are configuration parameters */
+ int32_t fs_maxcontig; /* max number of contiguous blks */
+ int32_t fs_maxbpg; /* max number of blks per cyl group */
+/* these fields can be computed from the others */
+ int32_t fs_fragshift; /* block to frag shift */
+ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ int32_t fs_sbsize; /* actual size of super block */
+ int32_t fs_csmask; /* csum block offset */
+ int32_t fs_csshift; /* csum block number */
+ int32_t fs_nindir; /* value of NINDIR */
+ int32_t fs_inopb; /* value of INOPB */
+ int32_t fs_nspf; /* value of NSPF */
+/* yet another configuration parameter */
+ int32_t fs_optim; /* optimization preference, see below */
+/* these fields are derived from the hardware */
+ /* USL SVR4 compatibility */
+#ifdef _LITTLE_ENDIAN
+ /*
+ * USL SVR4 compatibility
+ *
+ * There was a significant divergence here between Solaris and
+ * SVR4 for x86. By swapping these two members in the superblock,
+ * we get read-only compatibility of SVR4 filesystems. Otherwise
+ * there would be no compatibility. This change was introduced
+ * during bootstrapping of Solaris on x86. By making this ifdef'ed
+ * on byte order, we provide ongoing compatibility across all
+ * platforms with the same byte order, the highest compatibility
+ * that can be achieved.
+ */
+ int32_t fs_state; /* file system state time stamp */
+#else
+ int32_t fs_npsect; /* # sectors/track including spares */
+#endif
+ int32_t fs_si; /* summary info state - lufs only */
+ int32_t fs_trackskew; /* sector 0 skew, per track */
+/* a unique id for this filesystem (currently unused and unmaintained) */
+/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
+/* Neither of those fields is used in the Tahoe code right now but */
+/* there could be problems if they are. */
+ int32_t fs_id[2]; /* file system id */
+/* sizes determined by number of cylinder groups and their sizes */
+ daddr32_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int32_t fs_cssize; /* size of cyl grp summary area */
+ int32_t fs_cgsize; /* cylinder group size */
+/* these fields are derived from the hardware */
+ int32_t fs_ntrak; /* tracks per cylinder */
+ int32_t fs_nsect; /* sectors per track */
+ int32_t fs_spc; /* sectors per cylinder */
+/* this comes from the disk driver partitioning */
+ int32_t fs_ncyl; /* cylinders in file system */
+/* these fields can be computed from the others */
+ int32_t fs_cpg; /* cylinders per group */
+ int32_t fs_ipg; /* inodes per group */
+ int32_t fs_fpg; /* blocks per group * fs_frag */
+/* this data must be re-computed after crashes */
+ struct csum fs_cstotal; /* cylinder summary information */
+/* these fields are cleared at mount time */
+ char fs_fmod; /* super block modified flag */
+ char fs_clean; /* file system state flag */
+ char fs_ronly; /* mounted read-only flag */
+ char fs_flags; /* largefiles flag, etc. */
+ char fs_fsmnt[512]; /* name mounted on */
+/* these fields retain the current block allocation info */
+ int32_t fs_cgrotor; /* last cg searched */
+ /*
+ * The following used to be fs_csp[MAXCSBUFS]. It was not
+ * used anywhere except in old utilities. We removed this
+ * in 5.6 and expect fs_u.fs_csp to be used instead.
+ * We no longer limit fs_cssize based on MAXCSBUFS.
+ */
+ union { /* fs_cs (csum) info */
+ uint32_t fs_csp_pad[MAXCSBUFS];
+ struct csum *fs_csp;
+ } fs_u;
+ int32_t fs_cpc; /* cyl per cycle in postbl */
+ short fs_opostbl[16*8]; /* old rotation block list head */
+ int32_t fs_sparecon[51]; /* reserved for future constants */
+ int32_t fs_version; /* minor version of MTB ufs */
+ int32_t fs_logbno; /* block # of embedded log */
+ int32_t fs_reclaim; /* reclaim open, deleted files */
+ int32_t fs_sparecon2; /* reserved for future constant */
+#ifdef _LITTLE_ENDIAN
+ /* USL SVR4 compatibility */
+ int32_t fs_npsect; /* # sectors/track including spares */
+#else
+ int32_t fs_state; /* file system state time stamp */
+#endif
+ squad_t fs_qbmask; /* ~fs_bmask - for use with quad size */
+ squad_t fs_qfmask; /* ~fs_fmask - for use with quad size */
+ int32_t fs_postblformat; /* format of positional layout tables */
+ int32_t fs_nrpos; /* number of rotaional positions */
+ int32_t fs_postbloff; /* (short) rotation block list head */
+ int32_t fs_rotbloff; /* (uchar_t) blocks for each rotation */
+ int32_t fs_magic; /* magic number */
+ uchar_t fs_space[1]; /* list of blocks for each rotation */
+/* actually longer */
+};
+
/*
* In-core open file.
*/
@@ -142,7 +271,49 @@
static int buf_write_file(struct open_file *, char *, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
+
/*
+ * Search a directory for a name and return its
+ * i_number.
+ */
+
+static void hdump(uint8_t *bp, int size)
+{
+ int i;
+ int f = 1;
+ uint8_t tmp[17];
+
+ tmp[16] = '\0';
+
+ for (i=0; i<size; i++) {
+ uint8_t c;
+
+ c = bp[i];
+ if (f) {
+ printf("%04x : ", i);
+ f=0;
+ }
+ printf(" 0x%02x", c);
+
+ if (c<32 || c>126) c='.';
+ tmp[i&15] = c;
+
+ if ((i&15)==15) {
+ printf(" : %s\n", tmp);
+ f=1;
+ }
+ }
+ if (!f) {
+ for (i=(i&15); i<16; i++) {
+ printf(" --");
+ tmp[i]=' ';
+ }
+ printf(" : %s\n", tmp);
+ }
+}
+
+
+/*
* Read a new inode into a file structure.
*/
static int
@@ -159,6 +330,11 @@
if (fs == NULL)
panic("fs == NULL");
+ printf("read_inode : inumber=0x%llx fsba=0x%llx dba=0x%llx\n",
+ (uint64_t)inumber,
+ (uint64_t)ino_to_fsba(fs, inumber),
+ (uint64_t)fsbtodb(fs, ino_to_fsba(fs, inumber)) );
+
/*
* Read inode and save it.
*/
@@ -327,6 +503,7 @@
file_block = lblkno(fs, fp->f_seekp);
block_size = sblksize(fs, DIP(fp, di_size), file_block);
+
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
@@ -393,6 +570,7 @@
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
+ size_t file_size;
ufs_lbn_t file_block;
ufs2_daddr_t disk_block;
size_t block_size;
@@ -400,8 +578,24 @@
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
- block_size = sblksize(fs, DIP(fp, di_size), file_block);
+ file_size = DIP(fp, di_size);
+ block_size = sblksize(fs, file_size, file_block);
+#if 0
+ printf("buf_read_file: fs->f_seekp=0x%llx : off=0x%lx : file_block=0x%lx : block_size=0x%llx\n",
+ (uint64_t)fp->f_seekp, off, file_block, (uint64_t)block_size);
+ printf("\tfile_size=0x%llx : fs_bsize=0x%llx\n", (uint64_t)file_size, (uint64_t)fs->fs_bsize);
+ printf("fragroundup[blkoff[%lld]=%lld]=%lld\n", file_size, blkoff(fs, file_size),
+ fragroundup(fs, blkoff(fs, file_size)));
+ printf("fs->fs_qbmask=%llx fs->fs_qfmask=%llx fs->fs_fmask=%lx\n", fs->fs_qbmask, fs->fs_qfmask, fs->fs_fmask);
+#endif
+ if (block_size > 8192) {
+ block_size=8192;
+ printf("FORCE ROUND block_size\n");
+ }
+#if 0
+ printf("\tfp->f_buf_blkno = 0x%lx\n", fp->f_buf_blkno);
+#endif
if (file_block != fp->f_buf_blkno) {
if (fp->f_buf == (char *)0)
fp->f_buf = malloc(fs->fs_bsize);
@@ -409,17 +603,27 @@
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
-
+#if 0
+ printf("\tblock_map : disk_block = 0x%lx\n", disk_block);
+#endif
if (disk_block == 0) {
bzero(fp->f_buf, block_size);
fp->f_buf_size = block_size;
} else {
twiddle();
+#if 0
+ printf("\tcalling dev_strategy for block read fsbtodb[0x%lx]=0x%lx\n",
+ disk_block, fsbtodb(fs, disk_block));
+#endif
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, disk_block),
block_size, fp->f_buf, &fp->f_buf_size);
if (rc)
return (rc);
+#if 0
+ printf("\treturned from block read with 0x%lx bytes\n", fp->f_buf_size);
+ hdump(fp->f_buf, fp->f_buf_size);
+#endif
}
fp->f_buf_blkno = file_block;
@@ -442,10 +646,35 @@
return (0);
}
-/*
- * Search a directory for a name and return its
- * i_number.
- */
+static void
+test_disk(struct open_file *f)
+{
+ int i, rc;
+ char *buf;
+ uint64_t read_size;
+
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct fs *fs = fp->f_fs;
+
+ buf = (char *)malloc(512);
+
+ for (i = 0; i < 10; i++) {
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fs, i),
+ 512, buf, &read_size);
+
+
+ if (rc || read_size != 512)
+ printf("strategy failed\n");
+ printf("%04d\n", i);
+#if 0
+ hdump(buf, 512);
+#endif
+
+ }
+
+}
+
static int
search_directory(name, f, inumber_p)
char *name;
@@ -459,18 +688,33 @@
size_t buf_size;
int namlen, length;
int rc;
+#if 0
+ test_disk(f);
+#endif
+ length = strlen(name);
- length = strlen(name);
+ printf("search_directory: name=%s\n", name);
fp->f_seekp = 0;
while (fp->f_seekp < DIP(fp, di_size)) {
+ int i;
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
return (rc);
+ printf("scan directory entries: @ 0x%llx (size=0x%llx)\n",
+ (uint64_t)buf, (uint64_t)buf_size);
dp = (struct direct *)buf;
edp = (struct direct *)(buf + buf_size);
+ i = 0;
+#if 0
+ hdump(buf, buf_size);
+#endif
while (dp < edp) {
+#if 0
+ printf("\tdirent# %d (dp=0x%llx edp=0x%llx\n", i,
+ (uint64_t)dp, (uint64_t)edp);
+#endif
if (dp->d_ino == (ino_t)0)
goto next;
#if BYTE_ORDER == LITTLE_ENDIAN
@@ -479,6 +723,9 @@
else
#endif
namlen = dp->d_namlen;
+#if 0
+ printf("namlen: %d dp->d_name: %s\n", namlen, dp->d_name);
+#endif
if (namlen == length &&
!strcmp(name, dp->d_name)) {
/* found entry */
@@ -487,6 +734,7 @@
}
next:
dp = (struct direct *)((char *)dp + dp->d_reclen);
+ i++;
}
fp->f_seekp += buf_size;
}
@@ -494,7 +742,31 @@
}
static int sblock_try[] = SBLOCKSEARCH;
+#define SOLARIS_SBLOCK_CONVERT 1
+void map_sblock(struct fs *fsp)
+{
+ struct solaris_fs sfs = *(struct solaris_fs *)fsp;
+
+ printf("fbsd fs_qfmask offset %lx solaris fs_qfmask offset %lx\n",
+ offsetof(struct fs, fs_qfmask), offsetof(struct solaris_fs, fs_qfmask));
+ printf("fbsd fs_qbmask offset %lx solaris fs_qbmask offset %lx\n",
+ offsetof(struct fs, fs_qbmask), offsetof(struct solaris_fs, fs_qbmask));
+
+ printf(" fsp->fs_qbmask: %llx = sfs.fs_qbmask %08lx%08lx;\n",
+ fsp->fs_qbmask, sfs.fs_qbmask.val[0], sfs.fs_qbmask.val[1]);
+ fsp->fs_qbmask = ((uint64_t)sfs.fs_qbmask.val[0]) << 32 | sfs.fs_qbmask.val[1];
+ printf(" fsp->fs_qfmask: %llx = sfs.fs_qfmask %08lx%08lx;\n",
+ fsp->fs_qfmask, sfs.fs_qfmask.val[0], sfs.fs_qfmask.val[1]);
+ fsp->fs_qfmask = ((uint64_t)sfs.fs_qfmask.val[0]) << 32 | sfs.fs_qfmask.val[1];
+
+}
+
+
+
+
+
+
/*
* Open a file.
*/
@@ -533,6 +805,16 @@
(char *)fs, &buf_size);
if (rc)
goto out;
+
+
+
+
+#if 0
+ printf("fs->fs_magic: %x fs->fs_bsize: %x fs->fs_sblockloc: %lx\n",
+ fs->fs_magic, fs->fs_bsize, fs->fs_sblockloc);
+ printf("sblock_try[i]: %x buf_size %lx\n",
+ sblock_try[i], buf_size);
+#endif
if ((fs->fs_magic == FS_UFS1_MAGIC ||
(fs->fs_magic == FS_UFS2_MAGIC &&
fs->fs_sblockloc == sblock_try[i])) &&
@@ -545,6 +827,9 @@
rc = EINVAL;
goto out;
}
+#if 1
+ map_sblock(fs);
+#endif
/*
* Calculate indirect block levels.
*/
@@ -560,9 +845,13 @@
}
inumber = ROOTINO;
- if ((rc = read_inode(inumber, f)) != 0)
- goto out;
+ if ((rc = read_inode(inumber, f)) != 0) {
+ printf("failed to read root inode \n");
+ goto out;
+ }
+ printf("read root inode \n");
+
cp = path = strdup(upath);
if (path == NULL) {
rc = ENOMEM;
@@ -609,6 +898,8 @@
* symbolic link.
*/
parent_inumber = inumber;
+ printf("-- searching %s @ inode = 0x%x - found @ 0x%x\n",
+ ncp, parent_inumber, inumber);
rc = search_directory(ncp, f, &inumber);
*cp = c;
if (rc)
More information about the p4-projects
mailing list