diff -ur linux-2.6.3/fs/ufs/inode.c linux-2.6.3-ufs2/fs/ufs/inode.c --- linux-2.6.3/fs/ufs/inode.c 2004-02-18 11:39:45.000000000 +0530 +++ linux-2.6.3-ufs2/fs/ufs/inode.c 2004-02-20 11:52:14.911414368 +0530 @@ -82,7 +82,12 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ mark_inode_dirty(inode); UFSD(("EXIT, result %u\n", tmp + blockoff)) return result; + + /* This part : To be implemented .... + Required only for writting ...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 @@ 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 @@ 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 @@ 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 @@ 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) diff -ur linux-2.6.3/fs/ufs/namei.c linux-2.6.3-ufs2/fs/ufs/namei.c --- linux-2.6.3/fs/ufs/namei.c 2004-02-18 11:39:45.000000000 +0530 +++ linux-2.6.3-ufs2/fs/ufs/namei.c 2004-02-18 11:53:12.000000000 +0530 @@ -31,7 +31,10 @@ #include #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; diff -ur linux-2.6.3/fs/ufs/super.c linux-2.6.3-ufs2/fs/ufs/super.c --- linux-2.6.3/fs/ufs/super.c 2004-02-18 11:41:13.000000000 +0530 +++ linux-2.6.3-ufs2/fs/ufs/super.c 2004-02-20 11:40:05.482304448 +0530 @@ -58,6 +58,9 @@ * HP/UX hfs filesystem support added by * Martin K. Petersen , August 1999 * + * UFS2 (of FreeBSD 5.x) support added by + * Niraj Kumar , Jan 2004 + * */ @@ -142,6 +145,28 @@ 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 @@ 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 @@ {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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* * 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 @@ } #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 @@ 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 @@ { 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(); diff -ur linux-2.6.3/fs/ufs/util.c linux-2.6.3-ufs2/fs/ufs/util.c --- linux-2.6.3/fs/ufs/util.c 2004-02-18 11:39:45.000000000 +0530 +++ linux-2.6.3-ufs2/fs/ufs/util.c 2004-02-20 11:41:03.761444672 +0530 @@ -24,10 +24,11 @@ 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 @@ } 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; diff -ur linux-2.6.3/fs/ufs/util.h linux-2.6.3-ufs2/fs/ufs/util.h --- linux-2.6.3/fs/ufs/util.h 2004-02-18 11:39:45.000000000 +0530 +++ linux-2.6.3-ufs2/fs/ufs/util.h 2004-02-18 11:53:12.000000000 +0530 @@ -228,8 +228,8 @@ * 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 *);