UFS improvements

Gordon Chaffee (chaffee@odie.cs.berkeley.edu)
Sun, 12 May 1996 14:10:06 -0700


I've done some work getting the ufs filesystem to work with bytes swapped
filesystems as well as getting it to read various sized files properly.
It can now read files up to 16875520 bytes. Over that, it fails because
I did my work without any documentation, and I don't know how indirect
blocks work after the first indirect block page is used up.

I did my testing on a Pentium based system with a SunOS 4.1.3/Solaris 2.3
disk attached to it. The patch was made against 1.3.100, but it will
also work against pre2.0.1 and pre2.0.1.

Gordon Chaffee
chaffee@bugs-bunny.cs.berkeley.edu

diff -u --new-file --recursive linux-1.3.100 linux
diff -u --new-file --recursive linux-1.3.100/fs/ufs/Makefile linux/fs/ufs/Makefile
--- linux-1.3.100/fs/ufs/Makefile Tue Apr 23 01:13:25 1996
+++ linux/fs/ufs/Makefile Wed May 8 01:06:13 1996
@@ -9,7 +9,7 @@

O_TARGET := ufs.o
O_OBJS := ufs_dir.o ufs_file.o ufs_inode.o ufs_namei.o \
- ufs_super.o ufs_symlink.o
+ ufs_super.o ufs_symlink.o ufs_swap.o
M_OBJS := $(O_TARGET)

include $(TOPDIR)/Rules.make
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_dir.c linux/fs/ufs/ufs_dir.c
--- linux-1.3.100/fs/ufs/ufs_dir.c Sun May 5 16:50:08 1996
+++ linux/fs/ufs/ufs_dir.c Sun May 12 10:11:22 1996
@@ -10,7 +10,10 @@
*
*/

+#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/ufs_fs.h>
+#include "ufs_swap.h"

/* XXX */
extern int ufs_lookup (struct inode *, const char *, int, struct inode **);
@@ -30,10 +33,12 @@
struct buffer_head * bh;
struct direct * de;
struct super_block * sb;
+ int swap;

if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
sb = inode->i_sb;
+ swap = inode->i_sb->u.ufs_sb.s_flags & UFS_SWAP_FLAG;

if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_readdir: ino %lu f_pos %lu\n",
@@ -47,7 +52,6 @@

while (!error && !stored && filp->f_pos < inode->i_size) {
lblk = (filp->f_pos) >> sb->s_blocksize_bits;
- blk = ufs_bmap(inode, lblk);
/* XXX - ufs_bmap() call needs error checking */
blk = ufs_bmap(inode, lblk);
bh = bread (sb->s_dev, blk, sb->s_blocksize);
@@ -66,17 +70,24 @@
* to make sure. */
if (filp->f_version != inode->i_version) {
for (i = 0; i < sb->s_blocksize && i < offset; ) {
+ int reclen;
de = (struct direct *)
(bh->b_data + i);
+ if (swap) {
+ reclen = ufs_swap32(de->d_reclen);
+ } else {
+ reclen = de->d_reclen;
+ }
+
/* It's too expensive to do a full
* dirent test each time round this
* loop, but we do have to test at
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
- if (de->d_reclen < 1)
+ if (reclen < 1)
break;
- i += de->d_reclen;
+ i += reclen;
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -87,9 +98,15 @@
while (!error && filp->f_pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct direct *) (bh->b_data + offset);
+ if (swap) {
+ ufs_swap_direct(de); /* Swap forward */
+ }
/* XXX - put in a real ufs_check_dir_entry() */
if ((de->d_reclen == 0) || (de->d_namlen == 0)) {
filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize;
+ if (swap) {
+ ufs_swap_direct(de); /* Swap back */
+ }
brelse(bh);
return stored;
}
@@ -100,6 +117,9 @@
next block. */
filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
+ sb->s_blocksize;
+ if (swap) {
+ ufs_swap_direct(de); /* Swap back */
+ }
brelse (bh);
return stored;
}
@@ -121,13 +141,24 @@
de->d_name, de->d_ino);
}
error = filldir(dirent, de->d_name, de->d_namlen, filp->f_pos, de->d_ino);
- if (error)
+ if (error) {
+ if (swap) {
+ ufs_swap_direct(de); /* Swap back */
+ }
break;
- if (version != inode->i_version)
+ }
+ if (version != inode->i_version) {
+ if (swap) {
+ ufs_swap_direct(de); /* Swap back */
+ }
goto revalidate;
+ }
stored ++;
}
filp->f_pos += de->d_reclen;
+ if (swap) {
+ ufs_swap_direct(de); /* Swap back */
+ }
}
offset = 0;
brelse (bh);
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_file.c linux/fs/ufs/ufs_file.c
--- linux-1.3.100/fs/ufs/ufs_file.c Sun May 5 16:50:09 1996
+++ linux/fs/ufs/ufs_file.c Sun May 12 13:25:55 1996
@@ -10,7 +10,10 @@
*
*/

+#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/ufs_fs.h>
+#include "ufs_swap.h"

/*
* Return values:
@@ -20,7 +23,9 @@
int ufs_bmap (struct inode * inode, int block)
{
unsigned long int fsblkno, phys_block, lfsblkno;
- struct buffer_head * bh;
+ struct buffer_head * bh, *bh_ib;
+ unsigned long int size, page, offset;
+ int swap;

/*
* Note that contrary to what the BSD source calls these things,
@@ -52,16 +57,18 @@
* fsblkno is the physical 8192-block
* phys_block is the 1024-block
*/
+
+ swap = inode->i_sb->u.ufs_sb.s_flags & UFS_SWAP_FLAG;
lfsblkno = block>>3;

- if (block < UFS_NDADDR) {
+ if (lfsblkno < UFS_NDADDR) {
/* It's a direct block */
fsblkno = inode->u.ufs_i.ui_db[lfsblkno]; /* XXX */
#if 0
phys_block = ufs_cgdmin(inode->i_sb, ufs_ino2cg(inode)) +
blkno%(inode->i_sb->u.ufs_sb.s_fpg);
#endif
- phys_block = fsblkno + ((block & 0x7)<<10); /* XXX */
+ phys_block = fsblkno + (block & 0x7); /* XXX */
if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
printk("ufs_bmap: mapped ino %lu logical %u to %lu (phys %lu)\n",
inode->i_ino, block, fsblkno, phys_block);
@@ -69,25 +76,76 @@
return(phys_block);
} else {
/* Need to use indirect blocks */
- /* XXX - bmap through indirect blocks not implemented */
- block -= UFS_NDADDR;
- if (block < (inode->i_sb->s_blocksize/sizeof(__u32))) {
- bh = bread(inode->i_dev, inode->u.ufs_i.ui_ib[0],
+ lfsblkno -= UFS_NDADDR;
+
+ size = inode->i_sb->s_blocksize/sizeof(__u32);
+ if (lfsblkno < size * (UFS_BSIZE / inode->i_sb->s_blocksize)) {
+ page = lfsblkno / size; /* XXX */
+ offset = lfsblkno & (size - 1);
+ bh = bread(inode->i_dev, inode->u.ufs_i.ui_ib[0] +page,
BLOCK_SIZE);
if (bh == NULL) {
printk("ufs_bmap: can't map block %u, ino %lu\n",
- block + UFS_NDADDR, inode->i_ino);
+ block, inode->i_ino);
return(0);
}
- phys_block = ((__u32 *)bh->b_data)[block];
+ phys_block = ((__u32 *)bh->b_data)[offset];
+ if (swap) {
+ phys_block = ufs_swap32(phys_block);
+ }
+ phys_block += block & 0x7;
brelse(bh);
- printk("ufs_bmap: imap ino %lu block %u phys %lu\n",
- inode->i_ino, block + UFS_NDADDR, phys_block);
+ if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
+ printk("ufs_bmap: imap ino %lu block %u phys %lu\n",
+ inode->i_ino, block, phys_block);
+ }
return(phys_block);
- } else {
- printk("ufs_bmap: ino %lu: indirect blocks not implemented\n",
- inode->i_ino);
- return(0);
+ }
+ else {
+ /* XXX - bmap through anything beyond the first
+ * block not working. This code was guesswork
+ * that tried to read with a double indirect
+ * block scheme. */
+ lfsblkno -= size;
+ if (lfsblkno < size * size) {
+ bh_ib = bread(inode->i_dev, inode->u.ufs_i.ui_ib[1],
+ BLOCK_SIZE);
+ if (bh_ib == NULL) {
+ printk("ufs_bmap: 1. can't map block %u, ino %lu\n",
+ block, inode->i_ino);
+ return(0);
+ }
+ phys_block = ((__u32 *)bh_ib->b_data)[lfsblkno/size];
+ if (swap) {
+ phys_block = ufs_swap32(phys_block);
+ }
+
+ bh = bread(inode->i_dev, phys_block, BLOCK_SIZE);
+ if (bh == NULL) {
+ printk("ufs_bmap: 2. can't map block %u, ino %lu, phys_block %lu\n",
+ block, inode->i_ino, phys_block);
+ return(0);
+ }
+ phys_block = ((__u32 *)bh->b_data)[lfsblkno&(size-1)];
+ if (swap) {
+ phys_block = ufs_swap32(phys_block);
+ }
+ phys_block += block & 0x7;
+ brelse(bh);
+ brelse(bh_ib);
+ printk("ufs_bmap: imap ino %lu block %u phys %lu\n",
+ inode->i_ino, block, phys_block);
+#if 1
+ return(0);
+#else
+ return(phys_block);
+#endif
+
+ } else {
+ printk("ufs_bmap: ino %lu: indirect blocks not implemented\n",
+ inode->i_ino);
+ return(0);
+ }
}
}

diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_inode.c linux/fs/ufs/ufs_inode.c
--- linux-1.3.100/fs/ufs/ufs_inode.c Sun May 5 16:50:09 1996
+++ linux/fs/ufs/ufs_inode.c Sun May 12 10:12:48 1996
@@ -13,6 +13,7 @@
#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/sched.h>
+#include "ufs_swap.h"

extern struct inode_operations ufs_file_inode_operations;
extern struct inode_operations ufs_dir_inode_operations;
@@ -43,8 +44,10 @@
struct super_block * sb;
struct ufs_inode * ufsip;
struct buffer_head * bh;
+ int swap;

sb = inode->i_sb;
+ swap = inode->i_sb->u.ufs_sb.s_flags & UFS_SWAP_FLAG;

if (ufs_ino_ok(inode)) {
printk("ufs_read_inode: bad inum %lu", inode->i_ino);
@@ -70,6 +73,9 @@

ufsip = (struct ufs_inode *)bh->b_data;
ufsip += (inode->i_ino%(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag));
+ if (swap) {
+ ufs_swap_inode(ufsip); /* Swap forward */
+ }

/*
* Copy data to the in-core inode.
@@ -127,9 +133,10 @@
* for the rw code, we may want to mark these inodes as read-only.
* XXX - bug Linus to make i_size a __u64 instead of a __u32.
*/
- inode->u.ufs_i.ui_size = ((__u64)(ufsip->ui_size.val[0])<<32) | (__u64)(ufsip->ui_size.val[1]);
- inode->i_size = ufsip->ui_size.val[1]; /* XXX - endianity */
- if (ufsip->ui_size.val[0] != 0) {
+ /* XXX: Need endian fix here */
+ inode->u.ufs_i.ui_size = ufsip->ui_size;
+ inode->i_size = inode->u.ufs_i.ui_size & 0xffffffff;
+ if ((ufsip->ui_size & ~0xffffffff) != 0) {
inode->i_size = 0xffffffff;
printk("ufs_read_inode: file too big ino %lu dev %u/%u, faking size\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
@@ -197,6 +204,10 @@
inode->u.ufs_i.ui_gid = ufsip->ui_gid;
inode->u.ufs_i.ui_oeftflag = ufsip->ui_oeftflag;

+ if (swap) {
+ ufs_swap_inode(ufsip); /* Swap back */
+ }
+
brelse(bh);

if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_INODE)) {
@@ -208,20 +219,29 @@

void ufs_put_inode (struct inode * inode)
{
+ int swap;
if (inode->i_nlink)
return;

printk("ufs_put_inode: nlink == 0 for inum %lu on dev %d/%d\n",
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
+
+ swap = inode->i_sb->u.ufs_sb.s_flags & UFS_SWAP_FLAG;
+
ufs_print_inode(inode);
panic("ufs_put_inode: fs is read only, and nlink == 0");

- /* XXX - this code goes here eventually
+#if 0
+ /* XXX - this code goes here eventually */
+ if (swap) {
+ ufs_swap_inode(ufsip);
+ }
+
inode->i_size = 0;
if (inode->i_blocks)
ufs_truncate(inode);
ufs_free_inode(inode);
- */
+#endif

return;
}
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_namei.c linux/fs/ufs/ufs_namei.c
--- linux-1.3.100/fs/ufs/ufs_namei.c Sun May 5 16:50:09 1996
+++ linux/fs/ufs/ufs_namei.c Sun May 12 10:10:16 1996
@@ -10,7 +10,10 @@
*
*/

+#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/ufs_fs.h>
+#include "ufs_swap.h"

extern unsigned int ufs_bmap(struct inode * inode, int block); /* XXX */

@@ -39,7 +42,8 @@
{
unsigned long int lfragno, fragno;
struct buffer_head * bh;
- struct direct * d;
+ struct direct * d, *dold;
+ int swap;

/*
* Touching /xyzzy in a filesystem toggles debugging messages.
@@ -50,6 +54,7 @@
printk("UFS debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) ?
"on": "off");
+ iput(dir);
return(-ENOENT);
}

@@ -62,6 +67,7 @@
printk("UFS inode debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_INODE) ?
"on": "off");
+ iput(dir);
return(-ENOENT);
}

@@ -71,6 +77,7 @@
printk("UFS namei debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_NAMEI) ?
"on": "off");
+ iput(dir);
return(-ENOENT);
}

@@ -80,6 +87,7 @@
printk("UFS symlink debugging %s\n",
(dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_LINKS) ?
"on": "off");
+ iput(dir);
return(-ENOENT);
}

@@ -88,6 +96,8 @@
dir->i_ino, name);
}

+ swap = dir->i_sb->u.ufs_sb.s_flags & UFS_SWAP_FLAG;
+
/* XXX - do I want i_blocks in 512-blocks or 1024-blocks? */
for (lfragno = 0; lfragno < (dir->i_blocks)>>1; lfragno++) {
fragno = ufs_bmap(dir, lfragno);
@@ -99,15 +109,20 @@
}
if (fragno == 0) {
/* XXX - bug bug bug */
+ iput(dir);
return(-ENOENT);
}
bh = bread(dir->i_dev, fragno, dir->i_sb->s_blocksize);
if (bh == NULL) {
printk("ufs_lookup: bread failed: ino %lu, lfragno %lu",
dir->i_ino, lfragno);
+ iput(dir);
return(-EIO);
}
d = (struct direct *)(bh->b_data);
+ if (swap) {
+ ufs_swap_direct(d); /* Initial swap */
+ }
while (((char *)d - bh->b_data + d->d_reclen) <=
dir->i_sb->s_blocksize) {
/* XXX - skip block if d_reclen or d_namlen is 0 */
@@ -127,7 +142,11 @@
(ufs_match(len, name, d))) {
/* We have a match */
*result = iget(dir->i_sb, d->d_ino);
+ if (swap) {
+ ufs_swap_direct(d); /* Swap back */
+ }
brelse(bh);
+ iput(dir);
return(0);
} else {
/* XXX - bounds checking */
@@ -136,10 +155,19 @@
name, len, d->d_name, d->d_namlen);
}
}
+ dold = d;
d = (struct direct *)((char *)d + d->d_reclen);
+ if (swap) {
+ ufs_swap_direct(dold); /* Swap back */
+ ufs_swap_direct(d); /* Initial swap */
+ }
}
+ if (swap) {
+ ufs_swap_direct(d); /* Swap back */
+ }
brelse(bh);
}
+ iput(dir);
return(-ENOENT);
}

diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- linux-1.3.100/fs/ufs/ufs_super.c Sun May 12 13:28:43 1996
+++ linux/fs/ufs/ufs_super.c Sun May 12 08:57:17 1996
@@ -25,6 +25,7 @@
#include <linux/ufs_fs.h>
#include <linux/module.h>
#include <linux/locks.h>
+#include "ufs_swap.h"

#include <asm/segment.h>

@@ -99,6 +100,7 @@
{
struct ufs_superblock * usb;
struct buffer_head * bh1, *bh2;
+ int swap;

/* sb->s_dev and sb->s_flags are set by our caller
* data is the mystery argument to sys_mount()
@@ -139,13 +141,18 @@
brelse(bh1);
brelse(bh2);

- if (usb->fs_magic != UFS_MAGIC) {
- /* XXX - replace hard-coded constant with a byte-swap macro */
- if (usb->fs_magic == 0x54190100) {
- printk ("ufs_read_super: can't grok byteswapped fs on dev %d/%d\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev));
- silent = 1;
- }
+ swap = 0;
+ if (usb->fs_magic == UFS_MAGIC_SWAP) {
+ printk("ufs_read_super: handling a byte swapped filesystem\n");
+ swap = 1;
+ ufs_swap_superblock(usb); /* Swap forward */
+ } else if (usb->fs_magic != UFS_MAGIC) {
+#if 0
+ printk ("ufs_read_super: can't grok byteswapped fs on dev %d/%d\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev));
+ silent = 1;
+#endif
+
sb->s_dev = 0;
unlock_super (sb);
if (!silent)
@@ -220,7 +227,7 @@
/* sb->s_wait */
/* XXX - sb->u.ufs_sb */
sb->u.ufs_sb.s_raw_sb = usb; /* XXX - maybe move this to the top */
- sb->u.ufs_sb.s_flags = 0;
+ sb->u.ufs_sb.s_flags = swap ? UFS_SWAP_FLAG : 0;
sb->u.ufs_sb.s_ncg = usb->fs_ncg;
sb->u.ufs_sb.s_ipg = usb->fs_ipg;
sb->u.ufs_sb.s_fpg = usb->fs_fpg;
@@ -280,6 +287,7 @@
tmp.f_fsid.val[0] = sb->u.ufs_sb.s_raw_sb->fs_id[0];
tmp.f_fsid.val[1] = sb->u.ufs_sb.s_raw_sb->fs_id[1];
tmp.f_namelen = MAXNAMLEN;
+
/* tmp.f_spare[6] */

memcpy_tofs(buf, &tmp, bufsiz);
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_swap.c linux/fs/ufs/ufs_swap.c
--- linux-1.3.100/fs/ufs/ufs_swap.c Wed Dec 31 16:00:00 1969
+++ linux/fs/ufs/ufs_swap.c Sun May 12 10:09:01 1996
@@ -0,0 +1,137 @@
+/*
+ * linux/fs/ufs/ufs_swap.c
+ *
+ * Copyright (C) 1996
+ * Gordon Chaffee (chaffee@plateau.cs.berkeley.edu)
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/ufs_fs.h>
+#include "ufs_swap.h"
+
+void
+ufs_swap_csum(struct csum * x)
+{
+ x->cs_ndir = ufs_swap32(x->cs_ndir); /* number of directories */
+ x->cs_nbfree = ufs_swap32(x->cs_nbfree); /* number of free blocks */
+ x->cs_nifree = ufs_swap32(x->cs_nifree); /* number of free inodes */
+ x->cs_nffree = ufs_swap32(x->cs_nffree); /* number of free frags */
+};
+
+void
+ufs_swap_timeval(struct timeval * x)
+{
+ x->tv_sec = ufs_swap32(x->tv_sec);
+ x->tv_usec = ufs_swap32(x->tv_usec);
+};
+
+
+void
+ufs_swap_superblock(struct ufs_superblock * x)
+{
+ x->fs_link = ufs_swap32(x->fs_link); /* UNUSED */
+ x->fs_rlink = ufs_swap32(x->fs_rlink); /* UNUSED */
+ x->fs_sblkno = ufs_swap32(x->fs_sblkno);
+ x->fs_cblkno = ufs_swap32(x->fs_cblkno);
+ x->fs_iblkno = ufs_swap32(x->fs_iblkno);
+ x->fs_dblkno = ufs_swap32(x->fs_dblkno);
+ x->fs_cgoffset = ufs_swap32(x->fs_cgoffset);
+ x->fs_cgmask = ufs_swap32(x->fs_cgmask);
+
+ /* XXX: Questionable since this was declared as time_t */
+ x->fs_time = ufs_swap32(x->fs_time);
+
+ x->fs_size = ufs_swap32(x->fs_size);
+ x->fs_dsize = ufs_swap32(x->fs_dsize);
+ x->fs_ncg = ufs_swap32(x->fs_ncg);
+ x->fs_bsize = ufs_swap32(x->fs_bsize);
+ x->fs_fsize = ufs_swap32(x->fs_fsize);
+ x->fs_frag = ufs_swap32(x->fs_frag);
+ x->fs_minfree = ufs_swap32(x->fs_minfree);
+ x->fs_rotdelay = ufs_swap32(x->fs_rotdelay);
+ x->fs_rps = ufs_swap32(x->fs_rps);
+ x->fs_bmask = ufs_swap32(x->fs_bmask);
+ x->fs_fmask = ufs_swap32(x->fs_fmask);
+ x->fs_bshift = ufs_swap32(x->fs_bshift);
+ x->fs_fshift = ufs_swap32(x->fs_fshift);
+ x->fs_maxcontig = ufs_swap32(x->fs_maxcontig);
+ x->fs_maxbpg = ufs_swap32(x->fs_maxbpg);
+ x->fs_fragshift = ufs_swap32(x->fs_fragshift);
+ x->fs_fsbtodb = ufs_swap32(x->fs_fsbtodb);
+ x->fs_sbsize = ufs_swap32(x->fs_sbsize);
+ x->fs_csmask = ufs_swap32(x->fs_csmask);
+ x->fs_csshift = ufs_swap32(x->fs_csshift);
+ x->fs_nindir = ufs_swap32(x->fs_nindir);
+ x->fs_inopb = ufs_swap32(x->fs_inopb);
+ x->fs_nspf = ufs_swap32(x->fs_nspf);
+ x->fs_optim = ufs_swap32(x->fs_optim);
+ x->fs_XXX1 = ufs_swap32(x->fs_XXX1);
+ x->fs_interleave = ufs_swap32(x->fs_interleave);
+ x->fs_trackskew = ufs_swap32(x->fs_trackskew);
+ x->fs_id[0] = ufs_swap32(x->fs_id[0]);
+ x->fs_id[1] = ufs_swap32(x->fs_id[1]);
+ x->fs_csaddr = ufs_swap32(x->fs_csaddr);
+ x->fs_cssize = ufs_swap32(x->fs_cssize);
+ x->fs_cgsize = ufs_swap32(x->fs_cgsize);
+ x->fs_ntrak = ufs_swap32(x->fs_ntrak);
+ x->fs_nsect = ufs_swap32(x->fs_nsect);
+ x->fs_spc = ufs_swap32(x->fs_spc);
+ x->fs_ncyl = ufs_swap32(x->fs_ncyl);
+ x->fs_cpg = ufs_swap32(x->fs_cpg);
+ x->fs_ipg = ufs_swap32(x->fs_ipg);
+ x->fs_fpg = ufs_swap32(x->fs_fpg);
+
+ ufs_swap_csum(&x->fs_cstotal);
+
+ x->fs_cgrotor = ufs_swap32(x->fs_cgrotor);
+ x->fs_cpc = ufs_swap32(x->fs_cpc);
+ x->fs_state = ufs_swap32(x->fs_state);
+
+ x->fs_qbmask = ufs_swap64(x->fs_qbmask);
+ x->fs_qfmask = ufs_swap64(x->fs_qfmask);
+
+ x->fs_postblformat = ufs_swap32(x->fs_postblformat);
+ x->fs_nrpos = ufs_swap32(x->fs_nrpos);
+ x->fs_postbloff = ufs_swap32(x->fs_postbloff);
+ x->fs_rotbloff = ufs_swap32(x->fs_rotbloff);
+ x->fs_magic = ufs_swap32(x->fs_magic);
+}
+
+void
+ufs_swap_inode(struct ufs_inode *x)
+{
+ int i;
+
+ x->ui_mode = ufs_swap16(x->ui_mode);
+ x->ui_nlink = ufs_swap16(x->ui_nlink);
+ x->ui_suid = ufs_swap16(x->ui_suid);
+ x->ui_sgid = ufs_swap16(x->ui_sgid);
+ x->ui_size = ufs_swap64(x->ui_size);
+
+ ufs_swap_timeval(&x->ui_atime);
+ ufs_swap_timeval(&x->ui_mtime);
+ ufs_swap_timeval(&x->ui_ctime);
+
+ for (i = 0; i < UFS_NDADDR; i++) {
+ x->ui_db[i] = ufs_swap32(x->ui_db[i]);
+ }
+ for (i = 0; i < UFS_NINDIR; i++) {
+ x->ui_ib[i] = ufs_swap32(x->ui_ib[i]);
+ }
+
+ x->ui_flags = ufs_swap32(x->ui_flags);
+ x->ui_blocks = ufs_swap32(x->ui_blocks);
+ x->ui_gen = ufs_swap32(x->ui_gen);
+ x->ui_shadow = ufs_swap32(x->ui_shadow);
+ x->ui_uid = ufs_swap32(x->ui_uid);
+ x->ui_gid = ufs_swap32(x->ui_gid);
+ x->ui_oeftflag = ufs_swap32(x->ui_oeftflag);
+}
+
+void
+ufs_swap_direct(struct direct *x)
+{
+ x->d_ino = ufs_swap32(x->d_ino);
+ x->d_reclen = ufs_swap16(x->d_reclen);
+ x->d_namlen = ufs_swap16(x->d_namlen);
+};
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_swap.h linux/fs/ufs/ufs_swap.h
--- linux-1.3.100/fs/ufs/ufs_swap.h Wed Dec 31 16:00:00 1969
+++ linux/fs/ufs/ufs_swap.h Sun May 12 00:57:41 1996
@@ -0,0 +1,33 @@
+/*
+ * linux/fs/ufs/ufs_swap.h
+ *
+ * Copyright (C) 1996
+ * Gordon Chaffee (chaffee@plateau.cs.berkeley.edu)
+ */
+#define ufs_swap32(x) \
+ ((__u32)((((x) & 0x000000ffUL) << 24) | \
+ (((x) & 0x0000ff00UL) << 8) | \
+ (((x) & 0x00ff0000UL) >> 8) | \
+ (((x) & 0xff000000UL) >> 24)))
+
+#define ufs_swap16(x) \
+ ((__u16)((((unsigned short int)(x) & 0x00ff) << 8) | \
+ (((__u16)(x) & 0xff00) >> 8)))
+
+static __inline__ __u64 ufs_swap64(__u64 x)
+{
+ __u32 *ip, *op;
+ __u64 y;
+
+ ip = (__u32 *) &x;
+ op = (__u32 *) &y;
+ op[0] = ufs_swap32(ip[1]);
+ op[1] = ufs_swap32(ip[0]);
+ return y;
+}
+
+extern void ufs_swap_csum(struct csum *x);
+extern void ufs_swap_timeval(struct timeval *x);
+extern void ufs_swap_superblock(struct ufs_superblock *x);
+extern void ufs_swap_inode(struct ufs_inode *x);
+extern void ufs_swap_direct(struct direct *x);
diff -u --new-file --recursive linux-1.3.100/fs/ufs/ufs_symlink.c linux/fs/ufs/ufs_symlink.c
--- linux-1.3.100/fs/ufs/ufs_symlink.c Sun May 5 16:50:09 1996
+++ linux/fs/ufs/ufs_symlink.c Wed May 8 01:40:33 1996
@@ -11,6 +11,7 @@
*/

#include <linux/fs.h>
+#include <linux/ufs_fs.h>
#include <linux/sched.h>

#include <asm/segment.h>
diff -u --new-file --recursive linux-1.3.100/include/linux/ufs_fs.h linux/include/linux/ufs_fs.h
--- linux-1.3.100/include/linux/ufs_fs.h Sun May 5 17:09:01 1996
+++ linux/include/linux/ufs_fs.h Sun May 12 00:40:15 1996
@@ -24,6 +24,7 @@
#define UFS_SBSIZE 8192

#define UFS_MAGIC 0x00011954
+#define UFS_MAGIC_SWAP 0x54190100

#define UFS_FSIZE 1024
#define UFS_BSIZE 8192
@@ -46,6 +47,7 @@
#define UFS_DEBUG_INODE 0x00000002
#define UFS_DEBUG_NAMEI 0x00000004
#define UFS_DEBUG_LINKS 0x00000008
+#define UFS_SWAP_FLAG 0x00000010


/* Test if the inode number is valid. */
@@ -83,10 +85,6 @@
__u32 cs_nffree; /* number of free frags */
};

-typedef struct _ufsquad {
- __u32 val[2];
-} ufsquad;
-
/*
* This is the actual superblock, as it is laid out on the disk.
*/
@@ -150,8 +148,8 @@
__u16 fs_opostbl[16][8]; /* old rotation block list head */
__s32 fs_sparecon[55]; /* reserved for future constants */
__s32 fs_state; /* file system state time stamp */
- ufsquad fs_qbmask; /* ~usb_bmask - for use with __s64 size */
- ufsquad fs_qfmask; /* ~usb_fmask - for use with __s64 size */
+ __u64 fs_qbmask; /* ~usb_bmask - for use with __s64 size */
+ __u64 fs_qfmask; /* ~usb_fmask - for use with __s64 size */
__s32 fs_postblformat; /* format of positional layout tables */
__s32 fs_nrpos; /* number of rotational positions */
__s32 fs_postbloff; /* (__s16) rotation block list head */
@@ -169,7 +167,7 @@
__u16 ui_nlink; /* 0x2 */
__u16 ui_suid; /* 0x4 */
__u16 ui_sgid; /* 0x6 */
- ufsquad ui_size; /* 0x8 */ /* XXX - should be __u64 */
+ __u64 ui_size; /* 0x8 */ /* XXX - should be __u64 */
struct timeval ui_atime; /* 0x10 */
struct timeval ui_mtime; /* 0x18 */
struct timeval ui_ctime; /* 0x20 */
diff -u --new-file --recursive linux-1.3.100/include/linux/ufs_fs.h.save linux/include/linux/ufs_fs.h.save
--- linux-1.3.100/include/linux/ufs_fs.h.save Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ufs_fs.h.save Sun May 5 17:09:01 1996
@@ -0,0 +1,198 @@
+/*
+ * linux/include/linux/ufs_fs.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * $Id: ufs_fs.h,v 1.1 1996/04/21 14:45:11 davem Exp $
+ *
+ */
+
+#ifndef __LINUX_UFS_FS_H
+#define __LINUX_UFS_FS_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/stat.h>
+
+#define UFS_BBLOCK 0
+#define UFS_BBSIZE 8192
+#define UFS_SBLOCK 8192
+#define UFS_SBSIZE 8192
+
+#define UFS_MAGIC 0x00011954
+
+#define UFS_FSIZE 1024
+#define UFS_BSIZE 8192
+
+#define UFS_NDADDR 12
+#define UFS_NINDIR 3
+
+#define UFS_ROOTINO 2
+
+#define UFS_USEEFT ((__u16)65535)
+
+#define UFS_FSOK 0x7c269d38
+#define UFS_FSACTIVE ((char)0x00)
+#define UFS_FSCLEAN ((char)0x01)
+#define UFS_FSSTABLE ((char)0x02)
+#define UFS_FSBAD ((char)0xff)
+
+/* Flags for ufs_sb_info */
+#define UFS_DEBUG 0x00000001
+#define UFS_DEBUG_INODE 0x00000002
+#define UFS_DEBUG_NAMEI 0x00000004
+#define UFS_DEBUG_LINKS 0x00000008
+
+
+/* Test if the inode number is valid. */
+#define ufs_ino_ok(inode) ((inode->i_ino < 2) && \
+ (inode->i_ino > (inode->i_sb->u.ufs_sb.s_ncg * inode->i_sb->u.ufs_sb.s_ipg - 1)))
+
+/* Convert (sb,cg) to the first physical block number for that cg. */
+#define ufs_cgstart(sb, cg) \
+ (((sb)->u.ufs_sb.s_fpg * (cg)) + (sb)->u.ufs_sb.s_cgoffset * ((cg) & ~((sb)->u.ufs_sb.s_cgmask)))
+
+/* Convert (sb,cg) to the first phys. block number for inodes in that cg. */
+#define ufs_cgimin(sb, cg) (ufs_cgstart((sb), (cg)) + (sb)->u.ufs_sb.s_iblkno)
+#define ufs_cgdmin(sb, cg) (ufs_cgstart((sb), (cg)) + (sb)->u.ufs_sb.s_dblkno)
+
+/* Convert an inode number to a cg number. */
+/* XXX - this can be optimized if s_ipg is a power of 2. */
+#define ufs_ino2cg(inode) ((inode)->i_ino/(inode)->i_sb->u.ufs_sb.s_ipg)
+
+#define MAXNAMLEN 255
+
+struct direct {
+ __u32 d_ino; /* inode number of this entry */
+ __u16 d_reclen; /* length of this entry */
+ __u16 d_namlen; /* actual length of d_name */
+ char d_name[MAXNAMLEN + 1]; /* file name */
+};
+
+#define MAXMNTLEN 512
+#define MAXCSBUFS 32
+
+struct csum {
+ __u32 cs_ndir; /* number of directories */
+ __u32 cs_nbfree; /* number of free blocks */
+ __u32 cs_nifree; /* number of free inodes */
+ __u32 cs_nffree; /* number of free frags */
+};
+
+typedef struct _ufsquad {
+ __u32 val[2];
+} ufsquad;
+
+/*
+ * This is the actual superblock, as it is laid out on the disk.
+ */
+struct ufs_superblock {
+ __u32 fs_link; /* UNUSED */
+ __u32 fs_rlink; /* UNUSED */
+ __u32 fs_sblkno;
+ __u32 fs_cblkno;
+ __u32 fs_iblkno;
+ __u32 fs_dblkno;
+ __u32 fs_cgoffset;
+ __u32 fs_cgmask;
+ time_t fs_time; /* XXX - check type */
+ __u32 fs_size;
+ __u32 fs_dsize;
+ __u32 fs_ncg;
+ __u32 fs_bsize;
+ __u32 fs_fsize;
+ __u32 fs_frag;
+ __u32 fs_minfree;
+ __u32 fs_rotdelay;
+ __u32 fs_rps;
+ __u32 fs_bmask;
+ __u32 fs_fmask;
+ __u32 fs_bshift;
+ __u32 fs_fshift;
+ __u32 fs_maxcontig;
+ __u32 fs_maxbpg;
+ __u32 fs_fragshift;
+ __u32 fs_fsbtodb;
+ __u32 fs_sbsize;
+ __u32 fs_csmask;
+ __u32 fs_csshift;
+ __u32 fs_nindir;
+ __u32 fs_inopb;
+ __u32 fs_nspf;
+ __u32 fs_optim;
+ __u32 fs_XXX1;
+ __u32 fs_interleave;
+ __u32 fs_trackskew;
+ __u32 fs_id[2];
+ __u32 fs_csaddr;
+ __u32 fs_cssize;
+ __u32 fs_cgsize;
+ __u32 fs_ntrak;
+ __u32 fs_nsect;
+ __u32 fs_spc;
+ __u32 fs_ncyl;
+ __u32 fs_cpg;
+ __u32 fs_ipg;
+ __u32 fs_fpg;
+ struct csum fs_cstotal;
+ __u8 fs_fmod;
+ __u8 fs_clean;
+ __u8 fs_ronly;
+ __u8 fs_flags;
+ __u8 fs_fsmnt[MAXMNTLEN];
+ __u32 fs_cgrotor;
+ struct csum * fs_csp[MAXCSBUFS];
+ __u32 fs_cpc;
+ __u16 fs_opostbl[16][8]; /* old rotation block list head */
+ __s32 fs_sparecon[55]; /* reserved for future constants */
+ __s32 fs_state; /* file system state time stamp */
+ ufsquad fs_qbmask; /* ~usb_bmask - for use with __s64 size */
+ ufsquad fs_qfmask; /* ~usb_fmask - for use with __s64 size */
+ __s32 fs_postblformat; /* format of positional layout tables */
+ __s32 fs_nrpos; /* number of rotational positions */
+ __s32 fs_postbloff; /* (__s16) rotation block list head */
+ __s32 fs_rotbloff; /* (__u8) blocks for each rotation */
+ __s32 fs_magic; /* magic number */
+ __u8 fs_space[1]; /* list of blocks for each rotation */
+
+};
+
+/*
+ * structure of an on-disk inode
+ */
+struct ufs_inode {
+ __u16 ui_mode; /* 0x0 */
+ __u16 ui_nlink; /* 0x2 */
+ __u16 ui_suid; /* 0x4 */
+ __u16 ui_sgid; /* 0x6 */
+ ufsquad ui_size; /* 0x8 */ /* XXX - should be __u64 */
+ struct timeval ui_atime; /* 0x10 */
+ struct timeval ui_mtime; /* 0x18 */
+ struct timeval ui_ctime; /* 0x20 */
+ __u32 ui_db[UFS_NDADDR]; /* 0x28 data blocks */
+ __u32 ui_ib[UFS_NINDIR]; /* 0x58 indirect blocks */
+ __u32 ui_flags; /* 0x64 unused */
+ __u32 ui_blocks; /* 0x68 blocks in use */
+ __u32 ui_gen; /* 0x6c generation number XXX - what is this? */
+ __u32 ui_shadow; /* 0x70 shadow inode XXX - what is this?*/
+ __u32 ui_uid; /* 0x74 long EFT version of uid */
+ __u32 ui_gid; /* 0x78 long EFT version of gid */
+ __u32 ui_oeftflag; /* 0x7c reserved */
+};
+
+extern int init_ufs_fs(void);
+
+#endif /* __LINUX_UFS_FS_H */
+/*
+ * Local Variables: ***
+ * c-indent-level: 8 ***
+ * c-continued-statement-offset: 8 ***
+ * c-brace-offset: -8 ***
+ * c-argdecl-indent: 0 ***
+ * c-label-offset: -8 ***
+ * End: ***
+ */
diff -u --new-file --recursive linux-1.3.100/include/linux/ufs_fs_i.h.save linux/include/linux/ufs_fs_i.h.save
--- linux-1.3.100/include/linux/ufs_fs_i.h.save Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ufs_fs_i.h.save Sun May 5 17:09:01 1996
@@ -0,0 +1,30 @@
+/*
+ * linux/include/linux/ufs_fs_i.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * $Id: ufs_fs_i.h,v 1.1 1996/04/21 14:45:13 davem Exp $
+ *
+ */
+
+#ifndef _LINUX_UFS_FS_I_H
+#define _LINUX_UFS_FS_I_H
+
+#include <linux/ufs_fs.h>
+
+struct ufs_inode_info {
+ __u64 ui_size;
+ __u32 ui_flags;
+ __u32 ui_gen;
+ __u32 ui_shadow;
+ __u32 ui_uid;
+ __u32 ui_gid;
+ __u32 ui_oeftflag;
+ __u32 ui_db[UFS_NDADDR];
+ __u32 ui_ib[UFS_NINDIR];
+};
+
+#endif /* _LINUX_UFS_FS_I_H */
diff -u --new-file --recursive linux-1.3.100/include/linux/ufs_fs_sb.h.save linux/include/linux/ufs_fs_sb.h.save
--- linux-1.3.100/include/linux/ufs_fs_sb.h.save Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ufs_fs_sb.h.save Tue Apr 23 01:13:29 1996
@@ -0,0 +1,43 @@
+/*
+ * linux/include/linux/ufs_fs_sb.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * $Id: ufs_fs_sb.h,v 1.1 1996/04/21 14:45:15 davem Exp $
+ *
+ */
+
+#ifndef __LINUX_UFS_FS_SB_H
+#define __LINUX_UFS_FS_SB_H
+
+
+struct ufs_sb_info {
+ struct ufs_superblock * s_raw_sb;
+ __u32 s_flags; /* internal flags for UFS code */
+ __u32 s_ncg; /* used in ufs_read_inode */
+ __u32 s_ipg; /* used in ufs_read_inode */
+ __u32 s_fpg;
+ __u32 s_fsize;
+ __u32 s_bsize;
+ __u32 s_iblkno;
+ __u32 s_dblkno;
+ __u32 s_cgoffset;
+ __u32 s_cgmask;
+ __u32 s_inopb;
+ __u32 s_fsfrag;
+};
+
+#endif /* __LINUX_UFS_FS_SB_H */
+
+/*
+ * Local Variables: ***
+ * c-indent-level: 8 ***
+ * c-continued-statement-offset: 8 ***
+ * c-brace-offset: -8 ***
+ * c-argdecl-indent: 0 ***
+ * c-label-offset: -8 ***
+ * End: ***
+ */