]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] read-only support for UFS2
authorAndrew Morton <akpm@osdl.org>
Fri, 12 Mar 2004 00:12:15 +0000 (16:12 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 12 Mar 2004 00:12:15 +0000 (16:12 -0800)
From: Niraj Kumar <niraj17@iitbombay.org>

This patch adds read-only support for ufs2 (used in FreeBSD 5.x) variant of
ufs filesystem.  For filesystem specific tools, see
http://ufs-linux.sourceforge.com .

Documentation/filesystems/ufs.txt
fs/Kconfig
fs/ufs/inode.c
fs/ufs/namei.c
fs/ufs/super.c
fs/ufs/util.c
fs/ufs/util.h
include/linux/ufs_fs.h
include/linux/ufs_fs_i.h

index 0e2b243ff4451ffb7fc0f6b140038709b0e054c2..bdedb9fff4daf2e4a9da985e859babf693374a19 100644 (file)
@@ -20,6 +20,9 @@ ufstype=type_of_ufs
        44bsd   used in FreeBSD, NetBSD, OpenBSD
                supported os read-write
 
+       ufs2    used in FreeBSD 5.x
+               supported os read-only
+
        sun     used in SunOS (Solaris)
                supported as read-write
 
index 80bc94106b7220f5889c22d81a5ac352a2ee087e..c15342186b59f9c4cbb969eb4d1dd423513a82f3 100644 (file)
@@ -1227,6 +1227,9 @@ config UFS_FS
          experimental "UFS file system write support", below. Please read the
          file <file:Documentation/filesystems/ufs.txt> for more information.
 
+          The recently released UFS2 variant (used in FreeBSD 5.x) is
+          READ-ONLY supported.
+
          If you only intend to mount files from some other Unix over the
          network using NFS, you don't need the UFS file system support (but
          you need NFS file system support obviously).
index 647c7bef96800b25a5e11bddaed1fe2bb6b91ec6..57ca3070c10fa7b61354fddee740e378ec293f7c 100644 (file)
@@ -82,7 +82,12 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
        return n;
 }
 
-int ufs_frag_map(struct inode *inode, int frag)
+/*
+ * Returns the location of the fragment from
+ * the begining of the filesystem.
+ */
+
+u64  ufs_frag_map(struct inode *inode, int frag)
 {
        struct ufs_inode_info *ufsi = UFS_I(inode);
        struct super_block *sb = inode->i_sb;
@@ -93,6 +98,9 @@ int ufs_frag_map(struct inode *inode, int frag)
        int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
        int ret = 0;
        u32 block;
+       u64 u2_block = 0;
+       unsigned flags = UFS_SB(sb)->s_flags;
+       u64 temp = 0;
 
        if (depth == 0)
                return 0;
@@ -100,6 +108,9 @@ int ufs_frag_map(struct inode *inode, int frag)
        p = offsets;
 
        lock_kernel();
+       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+               goto ufs2;
+
        block = ufsi->i_u1.i_data[*p++];
        if (!block)
                goto out;
@@ -116,6 +127,28 @@ int ufs_frag_map(struct inode *inode, int frag)
                        goto out;
        }
        ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask);
+       goto out;
+ufs2:
+       u2_block = ufsi->i_u1.u2_i_data[*p++];
+       if (!u2_block)
+               goto out;
+
+       temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block);
+
+       while (--depth) {
+               struct buffer_head *bh;
+               u64 n = *p++;
+
+               bh = sb_bread(sb, temp +(n>>shift));
+               if (!bh)
+                       goto out;
+               u2_block = ((u64*)bh->b_data)[n & mask];
+               brelse(bh);
+               if (!u2_block)
+                       goto out;
+       }
+       ret = temp + (frag & uspi->s_fpbmask);
+
 out:
        unlock_kernel();
        return ret;
@@ -132,12 +165,20 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
        unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
        unsigned tmp, goal;
        u32 * p, * p2;
+       unsigned flags = 0;
 
        UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
                inode->i_ino, fragment, new_fragment, required))         
 
        sb = inode->i_sb;
        uspi = UFS_SB(sb)->s_uspi;
+
+       flags = UFS_SB(sb)->s_flags;
+        /* TODO : to be done for write support
+        if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+             goto ufs2;
+         */
+
        block = ufs_fragstoblks (fragment);
        blockoff = ufs_fragnum (fragment);
        p = ufsi->i_u1.i_data + block;
@@ -230,6 +271,21 @@ repeat:
        mark_inode_dirty(inode);
        UFSD(("EXIT, result %u\n", tmp + blockoff))
        return result;
+
+     /* This part : To be implemented ....
+        Required only for writing, not required for READ-ONLY.
+ufs2:
+
+       u2_block = ufs_fragstoblks(fragment);
+       u2_blockoff = ufs_fragnum(fragment);
+       p = ufsi->i_u1.u2_i_data + block;
+       goal = 0;
+
+repeat2:
+       tmp = fs32_to_cpu(sb, *p);
+       lastfrag = ufsi->i_lastfrag;
+
+     */
 }
 
 static struct buffer_head * ufs_block_getfrag (struct inode *inode,
@@ -308,21 +364,28 @@ out:
        return result;
 }
 
+/*
+ * This function gets the block which contains the fragment.
+ */
+
 static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
 {
        struct super_block * sb = inode->i_sb;
        struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
        struct buffer_head * bh;
        int ret, err, new;
-       unsigned long ptr, phys;
+       unsigned long ptr,phys;
+       u64 phys64 = 0;
        
        if (!create) {
-               phys = ufs_frag_map(inode, fragment);
-               if (phys)
-                       map_bh(bh_result, sb, phys);
+               phys64 = ufs_frag_map(inode, fragment);
+               if (phys64)
+                       map_bh(bh_result, sb, phys64);
                return 0;
        }
 
+        /* This code entered only while writing ....? */
+
        err = -EIO;
        new = 0;
        ret = 0;
@@ -474,6 +537,7 @@ void ufs_read_inode (struct inode * inode)
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
        struct ufs_inode * ufs_inode;   
+       struct ufs2_inode *ufs2_inode;
        struct buffer_head * bh;
        mode_t mode;
        unsigned i;
@@ -496,6 +560,9 @@ void ufs_read_inode (struct inode * inode)
                ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
                goto bad_inode;
        }
+       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+               goto ufs2_inode;
+
        ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
 
        /*
@@ -564,6 +631,78 @@ void ufs_read_inode (struct inode * inode)
 bad_inode:
        make_bad_inode(inode);
        return;
+
+ufs2_inode :
+       UFSD(("Reading ufs2 inode, ino %lu\n", inode->i_ino))
+
+       ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino));
+
+       /*
+        * Copy data to the in-core inode.
+        */
+       inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
+       inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink);
+       if (inode->i_nlink == 0)
+               ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
+
+        /*
+         * Linux now has 32-bit uid and gid, so we can support EFT.
+         */
+       inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid);
+       inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid);
+
+       inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size);
+       inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_atime.tv_sec);
+       inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_ctime.tv_sec);
+       inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_mtime.tv_sec);
+       inode->i_mtime.tv_nsec = 0;
+       inode->i_atime.tv_nsec = 0;
+       inode->i_ctime.tv_nsec = 0;
+       inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
+       inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/
+
+       inode->i_version++;
+       ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
+       ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
+       /*
+       ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
+       ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
+       */
+       ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift;
+
+       if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
+               for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
+                       ufsi->i_u1.u2_i_data[i] =
+                               ufs2_inode->ui_u2.ui_addr.ui_db[i];
+       }
+       else {
+               for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
+                       ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i];
+       }
+       ufsi->i_osync = 0;
+
+       if (S_ISREG(inode->i_mode)) {
+               inode->i_op = &ufs_file_inode_operations;
+               inode->i_fop = &ufs_file_operations;
+               inode->i_mapping->a_ops = &ufs_aops;
+       } else if (S_ISDIR(inode->i_mode)) {
+               inode->i_op = &ufs_dir_inode_operations;
+               inode->i_fop = &ufs_dir_operations;
+       } else if (S_ISLNK(inode->i_mode)) {
+               if (!inode->i_blocks)
+                       inode->i_op = &ufs_fast_symlink_inode_operations;
+               else {
+                       inode->i_op = &page_symlink_inode_operations;
+                       inode->i_mapping->a_ops = &ufs_aops;
+               }
+       } else   /* TODO  : here ...*/
+               init_special_inode(inode, inode->i_mode,
+                       old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+
+       brelse(bh);
+
+       UFSD(("EXIT\n"))
+       return;
 }
 
 static int ufs_update_inode(struct inode * inode, int do_sync)
index 4b4d5af34c691d84bb30e38e76baf5189b080afc..2fbba03981b4426beb68789b4e9a7b39de6ee8a4 100644 (file)
 #include <linux/buffer_head.h>
 #include "swab.h"      /* will go away - see comment in mknod() */
 
+/*
 #undef UFS_NAMEI_DEBUG
+*/
+#define UFS_NAMEI_DEBUG
 
 #ifdef UFS_NAMEI_DEBUG
 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
index 8ef47ddc7d6635a6f8ef675eb727c62e89903690..8d5f1c21bc63a085bb81261baa8bd2e432b2557d 100644 (file)
@@ -58,6 +58,9 @@
  * HP/UX hfs filesystem support added by
  * Martin K. Petersen <mkp@mkp.net>, August 1999
  *
+ * UFS2 (of FreeBSD 5.x) support added by
+ * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
+ *
  */
 
 
@@ -142,6 +145,28 @@ void ufs_print_super_stuff(struct super_block *sb,
        printk("\n");
 }
 
+/*
+ * Print contents of ufs2 ufs_super_block, useful for debugging
+ */
+void ufs2_print_super_stuff(
+     struct super_block *sb,
+      struct ufs_super_block *usb)
+{
+       printk("ufs_print_super_stuff\n");
+       printk("size of usb:     %u\n", sizeof(struct ufs_super_block));
+       printk("  magic:         0x%x\n", fs32_to_cpu(sb, usb->fs_magic));
+       printk("  fs_size:   %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size));
+       printk("  fs_dsize:  %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize));
+       printk("  fs_volname:  %s\n", usb->fs_u11.fs_u2.fs_volname);
+       printk("  fs_fsmnt:  %s\n", usb->fs_u11.fs_u2.fs_fsmnt);
+       printk("  fs_sblockloc: %u\n",fs64_to_cpu(sb,
+                       usb->fs_u11.fs_u2.fs_sblockloc));
+       printk("  cs_ndir(No of dirs):  %u\n",fs64_to_cpu(sb,
+                       usb->fs_u11.fs_u2.fs_cstotal.cs_ndir));
+       printk("  cs_nbfree(No of free blocks):  %u\n",fs64_to_cpu(sb,
+                       usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree));
+       printk("\n");
+}
 
 /*
  * Print contents of ufs_cylinder_group, useful for debugging
@@ -253,7 +278,7 @@ void ufs_warning (struct super_block * sb, const char * function,
 
 enum {
        Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd,
-       Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
+       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
 };
@@ -263,6 +288,8 @@ static match_table_t tokens = {
        {Opt_type_sunx86, "ufstype=sunx86"},
        {Opt_type_sun, "ufstype=sun"},
        {Opt_type_44bsd, "ufstype=44bsd"},
+       {Opt_type_ufs2, "ufstype=ufs2"},
+       {Opt_type_ufs2, "ufstype=5xbsd"},
        {Opt_type_hp, "ufstype=hp"},
        {Opt_type_nextstepcd, "ufstype=nextstep-cd"},
        {Opt_type_nextstep, "ufstype=nextstep"},
@@ -307,6 +334,10 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
                        ufs_clear_opt (*mount_options, UFSTYPE);
                        ufs_set_opt (*mount_options, UFSTYPE_44BSD);
                        break;
+               case Opt_type_ufs2:
+                       ufs_clear_opt(*mount_options, UFSTYPE);
+                       ufs_set_opt(*mount_options, UFSTYPE_UFS2);
+                       break;
                case Opt_type_hp:
                        ufs_clear_opt (*mount_options, UFSTYPE);
                        ufs_set_opt (*mount_options, UFSTYPE_HP);
@@ -356,13 +387,20 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
 int ufs_read_cylinder_structures (struct super_block * sb) {
        struct ufs_sb_info * sbi = UFS_SB(sb);
        struct ufs_sb_private_info * uspi;
+       struct ufs_super_block *usb;
        struct ufs_buffer_head * ubh;
        unsigned char * base, * space;
        unsigned size, blks, i;
+       unsigned flags = 0;
        
        UFSD(("ENTER\n"))
        
        uspi = sbi->s_uspi;
+
+       usb  = (struct ufs_super_block *)
+               ((struct ufs_buffer_head *)uspi)->bh[0]->b_data;
+
+        flags = UFS_SB(sb)->s_flags;
        
        /*
         * Read cs structures from (usually) first data block
@@ -377,11 +415,22 @@ int ufs_read_cylinder_structures (struct super_block * sb) {
                size = uspi->s_bsize;
                if (i + uspi->s_fpb > blks)
                        size = (blks - i) * uspi->s_fsize;
-               ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
-               if (!ubh)
-                       goto failed;
-               ubh_ubhcpymem (space, ubh, size);
-               sbi->s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space;
+
+               if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+                       ubh = ubh_bread(sb,
+                               fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
+                       if (!ubh)
+                               goto failed;
+                       ubh_ubhcpymem (space, ubh, size);
+                       sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
+               }
+               else {
+                       ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+                       if (!ubh)
+                               goto failed;
+                       ubh_ubhcpymem(space, ubh, size);
+                       sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
+               }
                space += size;
                ubh_brelse (ubh);
                ubh = NULL;
@@ -480,6 +529,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        struct ufs_super_block_first * usb1;
        struct ufs_super_block_second * usb2;
        struct ufs_super_block_third * usb3;
+       struct ufs_super_block *usb;
        struct ufs_buffer_head * ubh;   
        struct inode *inode;
        unsigned block_size, super_block_size;
@@ -520,7 +570,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
                if (!silent)
                        printk("You didn't specify the type of your ufs filesystem\n\n"
                        "mount -t ufs -o ufstype="
-                       "sun|sunx86|44bsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n"
+                       "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n"
                        ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
                        "default is ufstype=old\n");
                ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
@@ -545,6 +595,19 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
                uspi->s_sbbase = 0;
                flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
                break;
+       case UFS_MOUNT_UFSTYPE_UFS2:
+               UFSD(("ufstype=ufs2\n"))
+               uspi->s_fsize = block_size = 512;
+               uspi->s_fmask = ~(512 - 1);
+               uspi->s_fshift = 9;
+               uspi->s_sbsize = super_block_size = 1536;
+               uspi->s_sbbase =  0;
+               flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
+               if (!(sb->s_flags & MS_RDONLY)) {
+                       printk(KERN_INFO "ufstype=ufs2 is supported read-only\n");
+                       sb->s_flags |= MS_RDONLY;
+               }
+               break;
                
        case UFS_MOUNT_UFSTYPE_SUN:
                UFSD(("ufstype=sun\n"))
@@ -657,27 +720,37 @@ again:
        /*
         * read ufs super block from device
         */
-       ubh = ubh_bread_uspi (uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
+       if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+               ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size);
+       }
+       else {
+               ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
+       }
        if (!ubh) 
-               goto failed;
+            goto failed;
+
        
        usb1 = ubh_get_usb_first(USPI_UBH);
        usb2 = ubh_get_usb_second(USPI_UBH);
        usb3 = ubh_get_usb_third(USPI_UBH);
+       usb  = (struct ufs_super_block *)
+               ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
 
        /*
         * Check ufs magic number
         */
-       switch (__constant_le32_to_cpu(usb3->fs_magic)) {
+       switch ((uspi->fs_magic = __constant_le32_to_cpu(usb3->fs_magic))) {
                case UFS_MAGIC:
+               case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
                case UFS_MAGIC_4GB:
                        sbi->s_bytesex = BYTESEX_LE;
                        goto magic_found;
        }
-       switch (__constant_be32_to_cpu(usb3->fs_magic)) {
+       switch ((uspi->fs_magic = __constant_be32_to_cpu(usb3->fs_magic))) {
                case UFS_MAGIC:
+               case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
                case UFS_MAGIC_4GB:
@@ -748,7 +821,10 @@ magic_found:
        }
 
 #ifdef UFS_SUPER_DEBUG_MORE
-       ufs_print_super_stuff(sb, usb1, usb2, usb3);
+        if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+               ufs2_print_super_stuff(sb,usb);
+        else
+               ufs_print_super_stuff(sb, usb1, usb2, usb3);
 #endif
 
        /*
@@ -802,8 +878,16 @@ magic_found:
        uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno);
        uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset);
        uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
-       uspi->s_size = fs32_to_cpu(sb, usb1->fs_size);
-       uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize);
+
+       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+               uspi->s_u2_size  = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size);
+               uspi->s_u2_dsize = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
+       }
+       else {
+               uspi->s_size  =  fs32_to_cpu(sb, usb1->fs_size);
+               uspi->s_dsize =  fs32_to_cpu(sb, usb1->fs_dsize);
+       }
+
        uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg);
        /* s_bsize already set */
        /* s_fsize already set */
@@ -1021,21 +1105,36 @@ int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
+       struct ufs_super_block * usb;
+       unsigned  flags = 0;
 
        lock_kernel();
 
        uspi = UFS_SB(sb)->s_uspi;
        usb1 = ubh_get_usb_first (USPI_UBH);
+       usb  = (struct ufs_super_block *)
+               ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
        
-       buf->f_type = UFS_MAGIC;
+       flags = UFS_SB(sb)->s_flags;
+       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+               buf->f_type = UFS2_MAGIC;
+               buf->f_blocks = usb->fs_u11.fs_u2.fs_dsize;
+               buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
+                       fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
+               buf->f_ffree = fs64_to_cpu(sb,
+                       usb->fs_u11.fs_u2.fs_cstotal.cs_nifree);
+       }
+       else {
+               buf->f_type = UFS_MAGIC;
+               buf->f_blocks = uspi->s_dsize;
+               buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
+                       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
+               buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
+       }
        buf->f_bsize = sb->s_blocksize;
-       buf->f_blocks = uspi->s_dsize;
-       buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
-               fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
        buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree))
                ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
        buf->f_files = uspi->s_ncg * uspi->s_ipg;
-       buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
        buf->f_namelen = UFS_MAXNAMLEN;
 
        unlock_kernel();
index 7656699c165d020aecab83e996e4720d4b532872..80728750c2e6b1787d28667645077af6959d0cfc 100644 (file)
 
 
 struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
-       struct super_block *sb, unsigned fragment, unsigned size)
+       struct super_block *sb, u64 fragment, u64 size)
 {
        struct ufs_buffer_head * ubh;
-       unsigned i, j, count;
+       unsigned i, j ;
+       u64  count = 0;
        if (size & ~uspi->s_fmask)
                return NULL;
        count = size >> uspi->s_fshift;
@@ -53,9 +54,10 @@ failed:
 }
 
 struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
-       struct super_block *sb, unsigned fragment, unsigned size)
+       struct super_block *sb, u64 fragment, u64 size)
 {
-       unsigned i, j, count;
+       unsigned i, j;
+       u64 count = 0;
        if (size & ~uspi->s_fmask)
                return NULL;
        count = size >> uspi->s_fshift;
index edb6793af954e0afc46fe49a639df573d74d16d7..ad72b7fbe2fe516302cbc38479eb31981577a39d 100644 (file)
@@ -228,8 +228,8 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
  * These functions manipulate ufs buffers
  */
 #define ubh_bread(sb,fragment,size) _ubh_bread_(uspi,sb,fragment,size)  
-extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, unsigned, unsigned);
-extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, unsigned, unsigned);
+extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, u64 , u64);
+extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, u64, u64);
 extern void ubh_brelse (struct ufs_buffer_head *);
 extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
 extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *);
index cc3ddd5f680f99991619683576c84d16c6b99222..507187f51c58a51d4e67864b0a3d3684843389d7 100644 (file)
@@ -22,6 +22,9 @@
  * HP/UX hfs filesystem support added by
  * Martin K. Petersen <mkp@mkp.net>, August 1999
  *
+ * UFS2 (of FreeBSD 5.x) support added by
+ * Niraj Kumar <niraj17@iitbombay.org>  , Jan 2004
+ *
  */
 
 #ifndef __LINUX_UFS_FS_H
 
 #define UFS_SECTOR_SIZE 512
 #define UFS_SECTOR_BITS 9
-#define UFS_MAGIC 0x00011954
-#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */
+#define UFS_MAGIC  0x00011954
+#define UFS2_MAGIC 0x19540119
+#define UFS_CIGAM  0x54190100 /* byteswapped MAGIC */
+
+/* Copied from FreeBSD */
+/*
+ * Each disk drive contains some number of filesystems.
+ * A filesystem consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A filesystem is described by its super-block, which in turn
+ * describes the cylinder groups.  The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss.  This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For filesystem fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ *      [fs->fs_sblkno]         Super-block
+ *      [fs->fs_cblkno]         Cylinder group block
+ *      [fs->fs_iblkno]         Inode blocks
+ *      [fs->fs_dblkno]         Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * Depending on the architecture and the media, the superblock may
+ * reside in any one of four places. For tiny media where every block
+ * counts, it is placed at the very front of the partition. Historically,
+ * UFS1 placed it 8K from the front to leave room for the disk label and
+ * a small bootstrap. For UFS2 it got moved to 64K from the front to leave
+ * room for the disk label and a bigger bootstrap, and for really piggy
+ * systems we check at 256K from the front if the first three fail. In
+ * all cases the size of the superblock will be SBLOCKSIZE. All values are
+ * given in byte-offset form, so they do not imply a sector size. The
+ * SBLOCKSEARCH specifies the order in which the locations should be searched.
+ */
+#define SBLOCK_FLOPPY        0
+#define SBLOCK_UFS1       8192
+#define SBLOCK_UFS2      65536
+#define SBLOCK_PIGGY    262144
+#define SBLOCKSIZE        8192
+#define SBLOCKSEARCH \
+        { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
 
 
 /* HP specific MAGIC values */
 #define UFS_CG_OLD             0x00000000
 #define UFS_CG_44BSD           0x00002000
 #define UFS_CG_SUN             0x00001000
+/* filesystem type encoding */
+#define UFS_TYPE_MASK          0x00010000      /* mask for the following */
+#define UFS_TYPE_UFS1          0x00000000
+#define UFS_TYPE_UFS2          0x00010000
+
 
 /* fs_inodefmt options */
 #define UFS_42INODEFMT -1
 #define UFS_MOUNT_ONERROR_UMOUNT       0x00000004
 #define UFS_MOUNT_ONERROR_REPAIR       0x00000008
 
-#define UFS_MOUNT_UFSTYPE              0x00000FF0
+#define UFS_MOUNT_UFSTYPE              0x0000FFF0
 #define UFS_MOUNT_UFSTYPE_OLD          0x00000010
 #define UFS_MOUNT_UFSTYPE_44BSD                0x00000020
 #define UFS_MOUNT_UFSTYPE_SUN          0x00000040
 #define UFS_MOUNT_UFSTYPE_OPENSTEP     0x00000200
 #define UFS_MOUNT_UFSTYPE_SUNx86       0x00000400
 #define UFS_MOUNT_UFSTYPE_HP           0x00000800
+#define UFS_MOUNT_UFSTYPE_UFS2         0x00001000
 
 #define ufs_clear_opt(o,opt)   o &= ~UFS_MOUNT_##opt
 #define ufs_set_opt(o,opt)     o |= UFS_MOUNT_##opt
  * They calc file system addresses of cylinder group data structures.
  */
 #define        ufs_cgbase(c)   (uspi->s_fpg * (c))
-#define ufs_cgstart(c) (ufs_cgbase(c)  + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))
+#define ufs_cgstart(c) ((uspi)->fs_magic == UFS2_MAGIC ?  ufs_cgbase(c) : \
+       (ufs_cgbase(c)  + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask)))
 #define        ufs_cgsblock(c) (ufs_cgstart(c) + uspi->s_sblkno)       /* super blk */
 #define        ufs_cgcmin(c)   (ufs_cgstart(c) + uspi->s_cblkno)       /* cg block */
 #define        ufs_cgimin(c)   (ufs_cgstart(c) + uspi->s_iblkno)       /* inode blk */
 
 #define        UFS_MAXNAMLEN 255
 #define UFS_MAXMNTLEN 512
+#define UFS2_MAXMNTLEN 468
+#define UFS2_MAXVOLLEN 32
 /* #define UFS_MAXCSBUFS 31 */
 #define UFS_LINK_MAX 32000
+/*
+#define        UFS2_NOCSPTRS   ((128 / sizeof(void *)) - 4)
+*/
+#define        UFS2_NOCSPTRS   28
 
 /*
  * UFS_DIR_PAD defines the directory entries boundaries
@@ -262,6 +320,14 @@ struct ufs_csum {
        __u32   cs_nifree;      /* number of free inodes */
        __u32   cs_nffree;      /* number of free frags */
 };
+struct ufs2_csum_total {
+       __u64   cs_ndir;        /* number of directories */
+       __u64   cs_nbfree;      /* number of free blocks */
+       __u64   cs_nifree;      /* number of free inodes */
+       __u64   cs_nffree;      /* number of free frags */
+       __u64   cs_numclusters; /* number of free clusters */
+       __u64   cs_spare[3];    /* future expansion */
+};
 
 /*
  * This is the actual superblock, as it is laid out on the disk.
@@ -333,7 +399,7 @@ struct ufs_super_block {
        __u32   fs_ncyl;        /* cylinders in file system */
 /* these fields can be computed from the others */
        __u32   fs_cpg;         /* cylinders per group */
-       __u32   fs_ipg;         /* inodes per group */
+       __u32   fs_ipg;         /* inodes per cylinder group */
        __u32   fs_fpg;         /* blocks per group * fs_frag */
 /* this data must be re-computed after crashes */
        struct ufs_csum fs_cstotal;     /* cylinder summary information */
@@ -342,13 +408,39 @@ struct ufs_super_block {
        __s8    fs_clean;       /* file system is clean flag */
        __s8    fs_ronly;       /* mounted read-only flag */
        __s8    fs_flags;       /* currently unused flag */
-       __s8    fs_fsmnt[UFS_MAXMNTLEN];        /* name mounted on */
-/* these fields retain the current block allocation info */
-       __u32   fs_cgrotor;     /* last cg searched */
-       __u32   fs_csp[UFS_MAXCSBUFS];  /* list of fs_cs info buffers */
-       __u32   fs_maxcluster;
-       __u32   fs_cpc;         /* cyl per cycle in postbl */
-       __u16   fs_opostbl[16][8];      /* old rotation block list head */      
+       union {
+               struct {
+                       __s8    fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
+                       __u32   fs_cgrotor;     /* last cg searched */
+                       __u32   fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
+                       __u32   fs_maxcluster;
+                       __u32   fs_cpc;         /* cyl per cycle in postbl */
+                       __u16   fs_opostbl[16][8]; /* old rotation block list head */
+               } fs_u1;
+               struct {
+                       __s8  fs_fsmnt[UFS2_MAXMNTLEN]; /* name mounted on */
+                       __u8   fs_volname[UFS2_MAXVOLLEN]; /* volume name */
+                       __u64  fs_swuid;                /* system-wide uid */
+                       __s32  fs_pad;  /* due to alignment of fs_swuid */
+                       __u32   fs_cgrotor;     /* last cg searched */
+                       __u32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
+                       __u32   fs_contigdirs;/*# of contiguously allocated dirs */
+                       __u32   fs_csp; /* cg summary info buffer for fs_cs */
+                       __u32   fs_maxcluster;
+                       __u32   fs_active;/* used by snapshots to track fs */
+                       __s32   fs_old_cpc;     /* cyl per cycle in postbl */
+                       __s32   fs_maxbsize;/*maximum blocking factor permitted */
+                       __s64   fs_sparecon64[17];/*old rotation block list head */
+                       __s64   fs_sblockloc; /* byte offset of standard superblock */
+                       struct  ufs2_csum_total fs_cstotal;/*cylinder summary information*/
+                       struct  ufs_timeval    fs_time;         /* last time written */
+                       __s64    fs_size;               /* number of blocks in fs */
+                       __s64    fs_dsize;      /* number of data blocks in fs */
+                       __u64    fs_csaddr;     /* blk addr of cyl grp summary area */
+                       __s64    fs_pendingblocks;/* blocks in process of being freed */
+                       __s32    fs_pendinginodes;/*inodes in process of being freed */
+               } fs_u2;
+       }  fs_u11;
        union {
                struct {
                        __s32   fs_sparecon[53];/* reserved for future constants */
@@ -441,6 +533,16 @@ struct     ufs_cylinder_group {
                        __u32   cg_nclusterblks;        /* number of clusters this cg */
                        __u32   cg_sparecon[13];        /* reserved for future use */
                } cg_44;
+               struct {
+                       __u32   cg_clustersumoff;/* (u_int32) counts of avail clusters */
+                       __u32   cg_clusteroff;  /* (u_int8) free cluster map */
+                       __u32   cg_nclusterblks;/* number of clusters this cg */
+                       __u32   cg_niblk; /* number of inode blocks this cg */
+                       __u32   cg_initediblk;  /* last initialized inode */
+                       __u32   cg_sparecon32[3];/* reserved for future use */
+                       __u64   cg_time;        /* time last written */
+                       __u64   cg_sparecon[3]; /* reserved for future use */
+               } cg_u2;
                __u32   cg_sparecon[16];        /* reserved for future use */
        } cg_u;
        __u8    cg_space[1];            /* space for cylinder group maps */
@@ -497,6 +599,39 @@ struct ufs_inode {
        } ui_u3;
 };
 
+#define UFS_NXADDR  2            /* External addresses in inode. */
+struct ufs2_inode {
+       __u16     ui_mode;        /*   0: IFMT, permissions; see below. */
+       __s16     ui_nlink;       /*   2: File link count. */
+       __u32     ui_uid;         /*   4: File owner. */
+       __u32     ui_gid;         /*   8: File group. */
+       __u32     ui_blksize;     /*  12: Inode blocksize. */
+       __u64     ui_size;        /*  16: File byte count. */
+       __u64     ui_blocks;      /*  24: Bytes actually held. */
+       struct ufs_timeval   ui_atime;       /*  32: Last access time. */
+       struct ufs_timeval   ui_mtime;       /*  40: Last modified time. */
+       struct ufs_timeval   ui_ctime;       /*  48: Last inode change time. */
+       struct ufs_timeval   ui_birthtime;   /*  56: Inode creation time. */
+       __s32     ui_mtimensec;   /*  64: Last modified time. */
+       __s32     ui_atimensec;   /*  68: Last access time. */
+       __s32     ui_ctimensec;   /*  72: Last inode change time. */
+       __s32     ui_birthnsec;   /*  76: Inode creation time. */
+       __s32     ui_gen;         /*  80: Generation number. */
+       __u32     ui_kernflags;   /*  84: Kernel flags. */
+       __u32     ui_flags;       /*  88: Status flags (chflags). */
+       __s32     ui_extsize;     /*  92: External attributes block. */
+       __s64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
+       union {
+               struct {
+                       __s64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
+                       __s64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
+               } ui_addr;
+       __u8    ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
+       } ui_u2;
+       __s64     ui_spare[3];    /* 232: Reserved; currently unused */
+};
+
+
 /* FreeBSD has these in sys/stat.h */
 /* ui_flags that can be set by a file owner */
 #define UFS_UF_SETTABLE   0x0000ffff
@@ -517,8 +652,8 @@ struct ufs_inode {
  * than the size of fragment.
  */
 struct ufs_buffer_head {
-       unsigned fragment;                      /* first fragment */
-       unsigned count;                         /* number of fragments */
+       __u64 fragment;                 /* first fragment */
+       __u64 count;                            /* number of fragments */
        struct buffer_head * bh[UFS_MAXFRAG];   /* buffers */
 };
 
@@ -551,6 +686,8 @@ struct ufs_sb_private_info {
        __u32   s_cgmask;       /* used to calc mod fs_ntrak */
        __u32   s_size;         /* number of blocks (fragments) in fs */
        __u32   s_dsize;        /* number of data blocks in fs */
+       __u64   s_u2_size;      /* ufs2: number of blocks (fragments) in fs */
+       __u64   s_u2_dsize;     /*ufs2:  number of data blocks in fs */
        __u32   s_ncg;          /* number of cylinder groups */
        __u32   s_bsize;        /* size of basic blocks */
        __u32   s_fsize;        /* size of fragments */
@@ -577,7 +714,7 @@ struct ufs_sb_private_info {
        __u32   s_ntrak;        /* tracks per cylinder */
        __u32   s_nsect;        /* sectors per track */
        __u32   s_spc;          /* sectors per cylinder */
-       __u32   s_ipg;          /* inodes per group */
+       __u32   s_ipg;          /* inodes per cylinder group */
        __u32   s_fpg;          /* fragments per group */
        __u32   s_cpc;          /* cyl per cycle in postbl */
        __s32   s_contigsumsize;/* size of cluster summary array, 44bsd */
@@ -605,6 +742,7 @@ struct ufs_sb_private_info {
        __u32   s_bpfmask;      /* bits per fragment mask */
 
        __u32   s_maxsymlinklen;/* upper limit on fast symlinks' size */
+       __s32   fs_magic;       /* filesystem magic */
 };
 
 /*
@@ -758,7 +896,7 @@ extern void ufs_free_inode (struct inode *inode);
 extern struct inode * ufs_new_inode (struct inode *, int);
 
 /* inode.c */
-extern int ufs_frag_map (struct inode *, int);
+extern u64  ufs_frag_map (struct inode *, int);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
 extern void ufs_write_inode (struct inode *, int);
index 1b75864418223ee66b95848e351e422686604f89..c4ef0dfa9f460badad8fe9be5d9531ba2f641981 100644 (file)
@@ -17,6 +17,7 @@ struct ufs_inode_info {
        union {
                __u32   i_data[15];
                __u8    i_symlink[4*15];
+               __u64   u2_i_data[15];
        } i_u1;
        __u32   i_flags;
        __u32   i_gen;