}
 
 enum {
-       Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd,
+       Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_sunos, Opt_type_44bsd,
        Opt_type_ufs2, Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
        Opt_type_openstep, Opt_onerror_panic, Opt_onerror_lock,
        Opt_onerror_umount, Opt_onerror_repair, Opt_err
        {Opt_type_old, "ufstype=old"},
        {Opt_type_sunx86, "ufstype=sunx86"},
        {Opt_type_sun, "ufstype=sun"},
+       {Opt_type_sunos, "ufstype=sunos"},
        {Opt_type_44bsd, "ufstype=44bsd"},
        {Opt_type_ufs2, "ufstype=ufs2"},
        {Opt_type_ufs2, "ufstype=5xbsd"},
                        ufs_clear_opt (*mount_options, UFSTYPE);
                        ufs_set_opt (*mount_options, UFSTYPE_SUN);
                        break;
+               case Opt_type_sunos:
+                       ufs_clear_opt(*mount_options, UFSTYPE);
+                       ufs_set_opt(*mount_options, UFSTYPE_SUNOS);
+                       break;
                case Opt_type_44bsd:
                        ufs_clear_opt (*mount_options, UFSTYPE);
                        ufs_set_opt (*mount_options, UFSTYPE_44BSD);
                ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
        }
 
-       sbi->s_uspi = uspi =
-               kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
+       uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL);
+       sbi->s_uspi = uspi;
        if (!uspi)
                goto failed;
        uspi->s_dirblksize = UFS_SECTOR_SIZE;
                uspi->s_fshift = 10;
                uspi->s_sbsize = super_block_size = 2048;
                uspi->s_sbbase = 0;
-               uspi->s_maxsymlinklen = 56;
+               uspi->s_maxsymlinklen = 0; /* Not supported on disk */
                flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
                break;
 
+       case UFS_MOUNT_UFSTYPE_SUNOS:
+               UFSD(("ufstype=sunos\n"))
+               uspi->s_fsize = block_size = 1024;
+               uspi->s_fmask = ~(1024 - 1);
+               uspi->s_fshift = 10;
+               uspi->s_sbsize = 2048;
+               super_block_size = 2048;
+               uspi->s_sbbase = 0;
+               uspi->s_maxsymlinklen = 0; /* Not supported on disk */
+               flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN;
+               break;
+
        case UFS_MOUNT_UFSTYPE_SUNx86:
                UFSD("ufstype=sunx86\n");
                uspi->s_fsize = block_size = 1024;
                uspi->s_fshift = 10;
                uspi->s_sbsize = super_block_size = 2048;
                uspi->s_sbbase = 0;
-               uspi->s_maxsymlinklen = 56;
+               uspi->s_maxsymlinklen = 0; /* Not supported on disk */
                flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN;
                break;
 
        if (!ubh) 
             goto failed;
 
-       
        usb1 = ubh_get_usb_first(uspi);
        usb2 = ubh_get_usb_second(uspi);
        usb3 = ubh_get_usb_third(uspi);
 
+       /* Sort out mod used on SunOS 4.1.3 for fs_state */
+       uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
+       if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) &&
+           (uspi->s_postblformat != UFS_42POSTBLFMT)) {
+               flags &= ~UFS_ST_MASK;
+               flags |=  UFS_ST_SUN;
+       }
+
        /*
         * Check ufs magic number
         */
        if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) ||
          ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
          (((flags & UFS_ST_MASK) == UFS_ST_SUN || 
+           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
          (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && 
          (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) {
                switch(usb1->fs_clean) {
        uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize);
        uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3);
        uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3);
-       uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
        uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos);
        uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff);
        uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff);
        if (!(sb->s_flags & MS_RDONLY)) {
                usb1->fs_time = cpu_to_fs32(sb, get_seconds());
                if ((flags & UFS_ST_MASK) == UFS_ST_SUN 
+                 || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
                  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
                        ufs_set_fs_state(sb, usb1, usb3,
                                        UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
                ufs_put_super_internal(sb);
                usb1->fs_time = cpu_to_fs32(sb, get_seconds());
                if ((flags & UFS_ST_MASK) == UFS_ST_SUN
+                 || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
                  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 
                        ufs_set_fs_state(sb, usb1, usb3,
                                UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
                return -EINVAL;
 #else
                if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
+                   ufstype != UFS_MOUNT_UFSTYPE_SUNOS &&
                    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
                    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
                    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
 
                 struct ufs_super_block_third *usb3)
 {
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+       case UFS_ST_SUNOS:
+               if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT)
+                       return fs32_to_cpu(sb, usb1->fs_u0.fs_sun.fs_state);
+               /* Fall Through to UFS_ST_SUN */
        case UFS_ST_SUN:
                return fs32_to_cpu(sb, usb3->fs_un2.fs_sun.fs_state);
        case UFS_ST_SUNx86:
                 struct ufs_super_block_third *usb3, s32 value)
 {
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+       case UFS_ST_SUNOS:
+               if (fs32_to_cpu(sb, usb3->fs_postblformat == UFS_42POSTBLFMT)) {
+                       usb1->fs_u0.fs_sun.fs_state = cpu_to_fs32(sb, value);
+                       break;
+               }
+               /* Fall Through to UFS_ST_SUN */
        case UFS_ST_SUN:
                usb3->fs_un2.fs_sun.fs_state = cpu_to_fs32(sb, value);
                break;
        __fs64 tmp;
 
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+       case UFS_ST_SUNOS:
        case UFS_ST_SUN:
                ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qbmask[0];
                ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qbmask[1];
        __fs64 tmp;
 
        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+       case UFS_ST_SUNOS:
        case UFS_ST_SUN:
                ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qfmask[0];
                ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qfmask[1];
 ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode)
 {
        switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
-       case UFS_UID_EFT:
-               return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
        case UFS_UID_44BSD:
                return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_uid);
+       case UFS_UID_EFT:
+               if (inode->ui_u1.oldids.ui_suid == 0xFFFF)
+                       return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
+               /* Fall through */
        default:
                return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid);
        }
 ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value)
 {
        switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
-       case UFS_UID_EFT:
-               inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
-               break;
        case UFS_UID_44BSD:
                inode->ui_u3.ui_44.ui_uid = cpu_to_fs32(sb, value);
+               inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
+               break;
+       case UFS_UID_EFT:
+               inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
+               if (value > 0xFFFF)
+                       value = 0xFFFF;
+               /* Fall through */
+       default:
+               inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
                break;
        }
-       inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value); 
 }
 
 static inline u32
 ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode)
 {
        switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
-       case UFS_UID_EFT:
-               return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
        case UFS_UID_44BSD:
                return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid);
+       case UFS_UID_EFT:
+               if (inode->ui_u1.oldids.ui_suid == 0xFFFF)
+                       return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
+               /* Fall through */
        default:
                return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid);
        }
 ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
 {
        switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
-       case UFS_UID_EFT:
-               inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
-               break;
        case UFS_UID_44BSD:
                inode->ui_u3.ui_44.ui_gid = cpu_to_fs32(sb, value);
+               inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
+               break;
+       case UFS_UID_EFT:
+               inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
+               if (value > 0xFFFF)
+                       value = 0xFFFF;
+               /* Fall through */
+       default:
+               inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
                break;
        }
-       inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
 }
 
 extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
 
 #define UFS_ST_MASK            0x00000700      /* mask for the following */
 #define UFS_ST_OLD             0x00000000
 #define UFS_ST_44BSD           0x00000100
-#define UFS_ST_SUN             0x00000200
-#define UFS_ST_SUNx86          0x00000400
+#define UFS_ST_SUN             0x00000200 /* Solaris */
+#define UFS_ST_SUNOS           0x00000300
+#define UFS_ST_SUNx86          0x00000400 /* Solaris x86 */
 /*cylinder group encoding */
 #define UFS_CG_MASK            0x00003000      /* mask for the following */
 #define UFS_CG_OLD             0x00000000
 #define UFS_MOUNT_UFSTYPE_SUNx86       0x00000400
 #define UFS_MOUNT_UFSTYPE_HP           0x00000800
 #define UFS_MOUNT_UFSTYPE_UFS2         0x00001000
+#define UFS_MOUNT_UFSTYPE_SUNOS                0x00002000
 
 #define ufs_clear_opt(o,opt)   o &= ~UFS_MOUNT_##opt
 #define ufs_set_opt(o,opt)     o |= UFS_MOUNT_##opt
  * struct ufs_super_block_(first,second,third) instead.
  */
 struct ufs_super_block {
-       __fs32  fs_link;        /* UNUSED */
+       union {
+               struct {
+                       __fs32  fs_link;        /* UNUSED */
+               } fs_42;
+               struct {
+                       __fs32  fs_state;       /* file system state flag */
+               } fs_sun;
+       } fs_u0;
        __fs32  fs_rlink;       /* UNUSED */
        __fs32  fs_sblkno;      /* addr of super-block in filesys */
        __fs32  fs_cblkno;      /* offset of cyl-block in filesys */
 #define        CG_MAGIC        0x090255
 #define ufs_cg_chkmagic(sb, ucg) \
        (fs32_to_cpu((sb), (ucg)->cg_magic) == CG_MAGIC)
+/*
+ * Macros for access to old cylinder group array structures
+ */
+#define ufs_ocg_blktot(sb, ucg)      fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_btot)
+#define ufs_ocg_blks(sb, ucg, cylno) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_b[cylno])
+#define ufs_ocg_inosused(sb, ucg)    fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_iused)
+#define ufs_ocg_blksfree(sb, ucg)    fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_free)
+#define ufs_ocg_chkmagic(sb, ucg) \
+       (fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_magic) == CG_MAGIC)
 
 /*
  * size of this structure is 172 B
 /* actually longer */
 };
 
+/* Historic Cylinder group info */
+struct ufs_old_cylinder_group {
+       __fs32  cg_link;                /* linked list of cyl groups */
+       __fs32  cg_rlink;               /* for incore cyl groups     */
+       __fs32  cg_time;                /* time last written */
+       __fs32  cg_cgx;                 /* we are the cgx'th cylinder group */
+       __fs16  cg_ncyl;                /* number of cyl's this cg */
+       __fs16  cg_niblk;               /* number of inode blocks this cg */
+       __fs32  cg_ndblk;               /* number of data blocks this cg */
+       struct  ufs_csum cg_cs;         /* cylinder summary information */
+       __fs32  cg_rotor;               /* position of last used block */
+       __fs32  cg_frotor;              /* position of last used frag */
+       __fs32  cg_irotor;              /* position of last used inode */
+       __fs32  cg_frsum[8];            /* counts of available frags */
+       __fs32  cg_btot[32];            /* block totals per cylinder */
+       __fs16  cg_b[32][8];            /* positions of free blocks */
+       __u8    cg_iused[256];          /* used inode map */
+       __fs32  cg_magic;               /* magic number */
+       __u8    cg_free[1];             /* free block map */
+/* actually longer */
+};
+
 /*
  * structure of an on-disk inode
  */
  *     ufs_super_block_third   356
  */
 struct ufs_super_block_first {
-       __fs32  fs_link;
+       union {
+               struct {
+                       __fs32  fs_link;        /* UNUSED */
+               } fs_42;
+               struct {
+                       __fs32  fs_state;       /* file system state flag */
+               } fs_sun;
+       } fs_u0;
        __fs32  fs_rlink;
        __fs32  fs_sblkno;
        __fs32  fs_cblkno;