patch-2.1.87 linux/fs/ufs/ufs_super.c
Next file: linux/fs/ufs/ufs_swab.c
Previous file: linux/fs/ufs/ufs_namei.c
Back to the patch index
Back to the overall index
- Lines: 318
- Date:
Thu Feb 12 16:27:15 1998
- Orig file:
v2.1.86/linux/fs/ufs/ufs_super.c
- Orig date:
Fri Dec 5 07:20:44 1997
diff -u --recursive --new-file v2.1.86/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
@@ -19,8 +19,19 @@
*
* Clean swab support on 19970406 by
* Francois-Rene Rideau <rideau@ens.fr>
+ *
+ * 4.4BSD (FreeBSD) support added on February 1st 1998 by
+ * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
+ * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
+ *
+ * NeXTstep support added on February 5th 1998 by
+ * Niels Kristian Bech Jensen <nkbj@image.dk>.
*/
+#undef DEBUG_UFS_SUPER
+/*#define DEBUG_UFS_SUPER 1*/
+/* Uncomment the line above when hacking ufs superblock code */
+
#include <linux/config.h>
#include <linux/module.h>
@@ -42,7 +53,7 @@
NULL, /* XXX - ufs_write_inode() */
ufs_put_inode,
NULL, /* XXX - ufs_delete_inode() */
- NULL, /* notify_change() */
+ NULL, /* XXX - notify_change() */
ufs_put_super,
NULL, /* XXX - ufs_write_super() */
ufs_statfs,
@@ -89,23 +100,26 @@
kdevname(sb->s_dev), function, error_buf);
}
-#if 0 /* unused */
+#ifdef DEBUG_UFS_SUPER
static void
ufs_print_super_stuff(struct super_block * sb, struct ufs_superblock * usb)
{
+ __u32 flags = sb->u.ufs_sb.s_flags;
printk("fs_sblkno: 0x%8.8x\n", usb->fs_sblkno);
- printk("fs_size: 0x%8.8x\n", usb->fs_size);
- printk("fs_ncg: 0x%8.8x\n", usb->fs_ncg);
- printk("fs_bsize: 0x%8.8x\n", usb->fs_bsize);
- printk("fs_frag: 0x%8.8x\n", usb->fs_frag);
+ printk("fs_size: 0x%8.8x\n", usb->fs_size);
+ printk("fs_ncg: 0x%8.8x\n", usb->fs_ncg);
+ printk("fs_bsize: 0x%8.8x\n", usb->fs_bsize);
+ printk("fs_fsize: 0x%8.8x\n", usb->fs_fsize);
+ printk("fs_frag: 0x%8.8x\n", usb->fs_frag);
printk("fs_nindir: 0x%8.8x\n", usb->fs_nindir);
- printk("fs_inopb: 0x%8.8x\n", usb->fs_inopb);
- printk("fs_optim: 0x%8.8x\n", usb->fs_optim);
- printk("fs_ncyl: 0x%8.8x\n", usb->fs_ncyl);
- printk("fs_state: 0x%8.8x\n", usb->fs_state);
- printk("fs_magic: 0x%8.8x\n", usb->fs_magic);
- printk("fs_fsmnt: `%s'\n", usb->fs_fsmnt);
+ printk("fs_inopb: 0x%8.8x\n", usb->fs_inopb);
+ printk("fs_optim: 0x%8.8x\n", usb->fs_optim);
+ printk("fs_ncyl: 0x%8.8x\n", usb->fs_ncyl);
+ printk("fs_clean: 0x%8.8x\n", usb->fs_clean);
+ printk("fs_state: 0x%8.8x\n", UFS_STATE(usb));
+ printk("fs_magic: 0x%8.8x\n", usb->fs_magic);
+ printk("fs_fsmnt: `%s'\n", usb->fs_fsmnt);
return;
}
@@ -116,7 +130,9 @@
{
struct ufs_superblock * usb; /* normalized to local byteorder */
struct buffer_head * bh1, *bh2;
- __u32 bytesex = 0;
+ __u32 flags = UFS_DEBUG_INITIAL; /* for sb->u.ufs_sb.s_flags */
+ static int offsets[] = { 0, 96, 160 }; /* different superblock locations */
+ int i;
/* sb->s_dev and sb->s_flags are set by our caller
* data is the mystery argument to sys_mount()
@@ -127,102 +143,137 @@
MOD_INC_USE_COUNT;
lock_super (sb);
+ set_blocksize (sb->s_dev, BLOCK_SIZE);
/* XXX - make everything read only for testing */
sb->s_flags |= MS_RDONLY;
- if (!(bh1 = bread(sb->s_dev, UFS_SBLOCK/BLOCK_SIZE, BLOCK_SIZE)) ||
- !(bh2 = bread(sb->s_dev, (UFS_SBLOCK + BLOCK_SIZE)/BLOCK_SIZE,
- BLOCK_SIZE))) {
- brelse(bh1);
- printk ("ufs_read_super: unable to read superblock\n");
+ for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) {
+ if (!(bh1 = bread(sb->s_dev, offsets[i] + UFS_SBLOCK/BLOCK_SIZE,
+ BLOCK_SIZE)) ||
+ !(bh2 = bread(sb->s_dev, offsets[i] +
+ UFS_SBLOCK/BLOCK_SIZE + 1, BLOCK_SIZE))) {
+ brelse(bh1);
+ printk ("ufs_read_super: unable to read superblock\n");
+ goto ufs_read_super_lose;
+ }
+ /* XXX - redo this so we can free it later... */
+ usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL);
+ if (usb == NULL) {
+ brelse(bh1);
+ brelse(bh2);
+ printk ("ufs_read_super: get_free_page() failed\n");
+ goto ufs_read_super_lose;
+ }
+
+ memcpy((char *)usb, bh1->b_data, BLOCK_SIZE);
+ memcpy((char *)usb + BLOCK_SIZE, bh2->b_data,
+ sizeof(struct ufs_superblock) - BLOCK_SIZE);
- goto ufs_read_super_lose;
- }
- /* XXX - redo this so we can free it later... */
- usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL);
- if (usb == NULL) {
brelse(bh1);
brelse(bh2);
- printk ("ufs_read_super: get_free_page() failed\n");
- goto ufs_read_super_lose;
- }
-
- memcpy((char *)usb, bh1->b_data, BLOCK_SIZE);
- memcpy((char *)usb + BLOCK_SIZE, bh2->b_data,
- sizeof(struct ufs_superblock) - BLOCK_SIZE);
-
- brelse(bh1);
- brelse(bh2);
-
- switch (le32_to_cpup(&usb->fs_magic)) {
- case UFS_MAGIC:
- bytesex = UFS_LITTLE_ENDIAN;
- ufs_superblock_le_to_cpus(usb);
- break;
- case UFS_CIGAM:
- bytesex = UFS_BIG_ENDIAN;
- ufs_superblock_be_to_cpus(usb);
- break;
- /* usb is now normalized to local byteorder */
- default:
- printk ("ufs_read_super: bad magic number 0x%8.8x "
- "on dev %d/%d\n", usb->fs_magic,
- MAJOR(sb->s_dev), MINOR(sb->s_dev));
- goto ufs_read_super_lose;
+ switch (le32_to_cpup(&usb->fs_magic)) {
+ case UFS_MAGIC:
+ flags |= UFS_LITTLE_ENDIAN;
+ ufs_superblock_le_to_cpus(usb);
+ goto found;
+ case UFS_CIGAM:
+ flags |= UFS_BIG_ENDIAN;
+ ufs_superblock_be_to_cpus(usb);
+ goto found;
+ /* usb is now normalized to local byteorder */
+ default:
+ }
}
-
+ printk ("ufs_read_super: bad magic number 0x%8.8x "
+ "on dev %d/%d\n", usb->fs_magic,
+ MAJOR(sb->s_dev), MINOR(sb->s_dev));
+ goto ufs_read_super_lose;
+found:
+#ifdef DEBUG_UFS_SUPER
+ printk("ufs_read_super: superblock offset 0x%2.2x\n", offsets[i]);
+#endif
/* We found a UFS filesystem on this device. */
/* XXX - parse args */
- if (usb->fs_bsize != UFS_BSIZE) {
- printk("ufs_read_super: fs_bsize %d != %d\n", usb->fs_bsize,
- UFS_BSIZE);
+ if ((usb->fs_bsize != 4096) && (usb->fs_bsize != 8192)) {
+ printk("ufs_read_super: invalid fs_bsize = %d\n",
+ usb->fs_bsize);
goto ufs_read_super_lose;
}
- if (usb->fs_fsize != UFS_FSIZE) {
- printk("ufs_read_super: fs_fsize %d != %d\n", usb->fs_fsize,
- UFS_FSIZE);
+ if ((usb->fs_fsize != 512) && (usb->fs_fsize != 1024)) {
+ printk("ufs_read_super: invalid fs_fsize = %d\n",
+ usb->fs_fsize);
goto ufs_read_super_lose;
}
+ if (usb->fs_fsize != BLOCK_SIZE) {
+ set_blocksize (sb->s_dev, usb->fs_fsize);
+ }
+ flags |= UFS_VANILLA;
+ /* XXX more consistency check */
#ifdef DEBUG_UFS_SUPER
- printk("ufs_read_super: fs last mounted on \"%s\"\n", usb->fs_fsmnt);
+ printk("ufs_read_super: maxsymlinklen 0x%8.8x\n",
+ usb->fs_u.fs_44.fs_maxsymlinklen);
#endif
+ if (usb->fs_u.fs_44.fs_maxsymlinklen >= 0) {
+ if (usb->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) {
+ flags |= UFS_44BSD;
+ } else {
+ flags |= UFS_OLD; /* 4.2BSD */
+ }
+ } else if (offsets[i] > 0) {
+ flags |= UFS_NEXT;
+ } else {
+ flags |= UFS_SUN;
+ }
- if (usb->fs_state == UFS_FSOK - usb->fs_time) {
- switch(usb->fs_clean) {
- case UFS_FSCLEAN:
#ifdef DEBUG_UFS_SUPER
- printk("ufs_read_super: fs is clean\n");
+ ufs_print_super_stuff(sb, usb);
+#endif
+ if ( ((flags&UFS_ST_MASK)==UFS_ST_44BSD)
+ || ((flags&UFS_ST_MASK)==UFS_ST_OLD)
+ || ((flags&UFS_ST_MASK)==UFS_ST_NEXT)
+ || ( ((flags&UFS_ST_MASK)==UFS_ST_SUN)
+ && UFS_STATE(usb) == UFS_FSOK - usb->fs_time)) {
+ switch(usb->fs_clean) {
+ case UFS_FSACTIVE: /* 0x00 */
+ printk("ufs_read_super: fs is active\n");
+ sb->s_flags |= MS_RDONLY;
+ break;
+ case UFS_FSCLEAN: /* 0x01 */
+#ifdef DEBUG_UFS_SUPER
+ printk("ufs_read_super: fs is clean\n");
+#endif
+ break;
+ case UFS_FSSTABLE: /* 0x02 */
+#ifdef DEBUG_UFS_SUPER
+ printk("ufs_read_super: fs is stable\n");
#endif
- break;
- case UFS_FSSTABLE:
+ break;
+ case UFS_FSOSF1: /* 0x03 */
+ /* XXX is this correct for DEC OSF/1? */
#ifdef DEBUG_UFS_SUPER
- printk("ufs_read_super: fs is stable\n");
+ printk("ufs_read_super: fs is clean and stable (OSF/1)\n");
#endif
- break;
- case UFS_FSACTIVE:
- printk("ufs_read_super: fs is active\n");
- sb->s_flags |= MS_RDONLY;
- break;
- case UFS_FSBAD:
- printk("ufs_read_super: fs is bad\n");
- sb->s_flags |= MS_RDONLY;
- break;
- default:
- printk("ufs_read_super: can't grok fs_clean 0x%x\n",
- usb->fs_clean);
- sb->s_flags |= MS_RDONLY;
- break;
- }
+ break;
+ case UFS_FSBAD: /* 0xFF */
+ printk("ufs_read_super: fs is bad\n");
+ sb->s_flags |= MS_RDONLY;
+ break;
+ default:
+ printk("ufs_read_super: can't grok fs_clean 0x%x\n",
+ usb->fs_clean);
+ sb->s_flags |= MS_RDONLY;
+ break;
+ }
} else {
- printk("ufs_read_super: fs needs fsck\n");
- sb->s_flags |= MS_RDONLY;
- /* XXX - make it read only or barf if it's not (/, /usr) */
+ printk("ufs_read_super: fs needs fsck\n");
+ sb->s_flags |= MS_RDONLY;
+ /* XXX - make it read only or barf if it's not (/, /usr) */
}
/* XXX - sanity check sb fields */
@@ -238,7 +289,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 = bytesex | UFS_DEBUG_INITIAL ;
+ sb->u.ufs_sb.s_flags = flags ;
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;
@@ -257,6 +308,7 @@
sb->u.ufs_sb.s_lmask = ~((usb->fs_fmask - usb->fs_bmask)
>> usb->fs_fshift);
sb->u.ufs_sb.s_fsfrag = usb->fs_frag; /* XXX - rename this later */
+ sb->u.ufs_sb.s_blockbase = offsets[i];
sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL);
#ifdef DEBUG_UFS_SUPER
@@ -271,6 +323,7 @@
ufs_read_super_lose:
/* XXX - clean up */
+ set_blocksize (sb->s_dev, BLOCK_SIZE);
sb->s_dev = 0;
unlock_super (sb);
MOD_DEC_USE_COUNT;
@@ -285,6 +338,7 @@
lock_super (sb);
/* XXX - sync fs data, set state to ok, and flush buffers */
+ set_blocksize (sb->s_dev, BLOCK_SIZE);
sb->s_dev = 0;
/* XXX - free allocated kernel memory */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov