Commit e3459dfb authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] read-only support for UFS2

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 .
parent 202775d6
...@@ -20,6 +20,9 @@ ufstype=type_of_ufs ...@@ -20,6 +20,9 @@ ufstype=type_of_ufs
44bsd used in FreeBSD, NetBSD, OpenBSD 44bsd used in FreeBSD, NetBSD, OpenBSD
supported os read-write supported os read-write
ufs2 used in FreeBSD 5.x
supported os read-only
sun used in SunOS (Solaris) sun used in SunOS (Solaris)
supported as read-write supported as read-write
......
...@@ -1227,6 +1227,9 @@ config UFS_FS ...@@ -1227,6 +1227,9 @@ config UFS_FS
experimental "UFS file system write support", below. Please read the experimental "UFS file system write support", below. Please read the
file <file:Documentation/filesystems/ufs.txt> for more information. 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 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 network using NFS, you don't need the UFS file system support (but
you need NFS file system support obviously). you need NFS file system support obviously).
......
...@@ -82,7 +82,12 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4]) ...@@ -82,7 +82,12 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
return n; 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 ufs_inode_info *ufsi = UFS_I(inode);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
...@@ -93,6 +98,9 @@ int ufs_frag_map(struct inode *inode, int frag) ...@@ -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 depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
int ret = 0; int ret = 0;
u32 block; u32 block;
u64 u2_block = 0;
unsigned flags = UFS_SB(sb)->s_flags;
u64 temp = 0;
if (depth == 0) if (depth == 0)
return 0; return 0;
...@@ -100,6 +108,9 @@ int ufs_frag_map(struct inode *inode, int frag) ...@@ -100,6 +108,9 @@ int ufs_frag_map(struct inode *inode, int frag)
p = offsets; p = offsets;
lock_kernel(); lock_kernel();
if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
goto ufs2;
block = ufsi->i_u1.i_data[*p++]; block = ufsi->i_u1.i_data[*p++];
if (!block) if (!block)
goto out; goto out;
...@@ -116,6 +127,28 @@ int ufs_frag_map(struct inode *inode, int frag) ...@@ -116,6 +127,28 @@ int ufs_frag_map(struct inode *inode, int frag)
goto out; goto out;
} }
ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask); 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: out:
unlock_kernel(); unlock_kernel();
return ret; return ret;
...@@ -132,12 +165,20 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode, ...@@ -132,12 +165,20 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
unsigned block, blockoff, lastfrag, lastblock, lastblockoff; unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
unsigned tmp, goal; unsigned tmp, goal;
u32 * p, * p2; u32 * p, * p2;
unsigned flags = 0;
UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n", UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
inode->i_ino, fragment, new_fragment, required)) inode->i_ino, fragment, new_fragment, required))
sb = inode->i_sb; sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi; 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); block = ufs_fragstoblks (fragment);
blockoff = ufs_fragnum (fragment); blockoff = ufs_fragnum (fragment);
p = ufsi->i_u1.i_data + block; p = ufsi->i_u1.i_data + block;
...@@ -230,6 +271,21 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode, ...@@ -230,6 +271,21 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
mark_inode_dirty(inode); mark_inode_dirty(inode);
UFSD(("EXIT, result %u\n", tmp + blockoff)) UFSD(("EXIT, result %u\n", tmp + blockoff))
return result; 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, static struct buffer_head * ufs_block_getfrag (struct inode *inode,
...@@ -308,21 +364,28 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode, ...@@ -308,21 +364,28 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode,
return result; 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) 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 super_block * sb = inode->i_sb;
struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * bh; struct buffer_head * bh;
int ret, err, new; int ret, err, new;
unsigned long ptr, phys; unsigned long ptr,phys;
u64 phys64 = 0;
if (!create) { if (!create) {
phys = ufs_frag_map(inode, fragment); phys64 = ufs_frag_map(inode, fragment);
if (phys) if (phys64)
map_bh(bh_result, sb, phys); map_bh(bh_result, sb, phys64);
return 0; return 0;
} }
/* This code entered only while writing ....? */
err = -EIO; err = -EIO;
new = 0; new = 0;
ret = 0; ret = 0;
...@@ -474,6 +537,7 @@ void ufs_read_inode (struct inode * inode) ...@@ -474,6 +537,7 @@ void ufs_read_inode (struct inode * inode)
struct super_block * sb; struct super_block * sb;
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info * uspi;
struct ufs_inode * ufs_inode; struct ufs_inode * ufs_inode;
struct ufs2_inode *ufs2_inode;
struct buffer_head * bh; struct buffer_head * bh;
mode_t mode; mode_t mode;
unsigned i; unsigned i;
...@@ -496,6 +560,9 @@ void ufs_read_inode (struct inode * inode) ...@@ -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); ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
goto bad_inode; 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)); 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) ...@@ -564,6 +631,78 @@ void ufs_read_inode (struct inode * inode)
bad_inode: bad_inode:
make_bad_inode(inode); make_bad_inode(inode);
return; 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) static int ufs_update_inode(struct inode * inode, int do_sync)
......
...@@ -31,7 +31,10 @@ ...@@ -31,7 +31,10 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include "swab.h" /* will go away - see comment in mknod() */ #include "swab.h" /* will go away - see comment in mknod() */
/*
#undef UFS_NAMEI_DEBUG #undef UFS_NAMEI_DEBUG
*/
#define UFS_NAMEI_DEBUG
#ifdef UFS_NAMEI_DEBUG #ifdef UFS_NAMEI_DEBUG
#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x; #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
* HP/UX hfs filesystem support added by * HP/UX hfs filesystem support added by
* Martin K. Petersen <mkp@mkp.net>, August 1999 * 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, ...@@ -142,6 +145,28 @@ void ufs_print_super_stuff(struct super_block *sb,
printk("\n"); 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 * Print contents of ufs_cylinder_group, useful for debugging
...@@ -253,7 +278,7 @@ void ufs_warning (struct super_block * sb, const char * function, ...@@ -253,7 +278,7 @@ void ufs_warning (struct super_block * sb, const char * function,
enum { enum {
Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd, 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_type_openstep, Opt_onerror_panic, Opt_onerror_lock,
Opt_onerror_umount, Opt_onerror_repair, Opt_err Opt_onerror_umount, Opt_onerror_repair, Opt_err
}; };
...@@ -263,6 +288,8 @@ static match_table_t tokens = { ...@@ -263,6 +288,8 @@ static match_table_t tokens = {
{Opt_type_sunx86, "ufstype=sunx86"}, {Opt_type_sunx86, "ufstype=sunx86"},
{Opt_type_sun, "ufstype=sun"}, {Opt_type_sun, "ufstype=sun"},
{Opt_type_44bsd, "ufstype=44bsd"}, {Opt_type_44bsd, "ufstype=44bsd"},
{Opt_type_ufs2, "ufstype=ufs2"},
{Opt_type_ufs2, "ufstype=5xbsd"},
{Opt_type_hp, "ufstype=hp"}, {Opt_type_hp, "ufstype=hp"},
{Opt_type_nextstepcd, "ufstype=nextstep-cd"}, {Opt_type_nextstepcd, "ufstype=nextstep-cd"},
{Opt_type_nextstep, "ufstype=nextstep"}, {Opt_type_nextstep, "ufstype=nextstep"},
...@@ -307,6 +334,10 @@ static int ufs_parse_options (char * options, unsigned * mount_options) ...@@ -307,6 +334,10 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
ufs_clear_opt (*mount_options, UFSTYPE); ufs_clear_opt (*mount_options, UFSTYPE);
ufs_set_opt (*mount_options, UFSTYPE_44BSD); ufs_set_opt (*mount_options, UFSTYPE_44BSD);
break; break;
case Opt_type_ufs2:
ufs_clear_opt(*mount_options, UFSTYPE);
ufs_set_opt(*mount_options, UFSTYPE_UFS2);
break;
case Opt_type_hp: case Opt_type_hp:
ufs_clear_opt (*mount_options, UFSTYPE); ufs_clear_opt (*mount_options, UFSTYPE);
ufs_set_opt (*mount_options, UFSTYPE_HP); ufs_set_opt (*mount_options, UFSTYPE_HP);
...@@ -356,13 +387,20 @@ static int ufs_parse_options (char * options, unsigned * mount_options) ...@@ -356,13 +387,20 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
int ufs_read_cylinder_structures (struct super_block * sb) { int ufs_read_cylinder_structures (struct super_block * sb) {
struct ufs_sb_info * sbi = UFS_SB(sb); struct ufs_sb_info * sbi = UFS_SB(sb);
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info * uspi;
struct ufs_super_block *usb;
struct ufs_buffer_head * ubh; struct ufs_buffer_head * ubh;
unsigned char * base, * space; unsigned char * base, * space;
unsigned size, blks, i; unsigned size, blks, i;
unsigned flags = 0;
UFSD(("ENTER\n")) UFSD(("ENTER\n"))
uspi = sbi->s_uspi; 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 * Read cs structures from (usually) first data block
...@@ -377,11 +415,22 @@ int ufs_read_cylinder_structures (struct super_block * sb) { ...@@ -377,11 +415,22 @@ int ufs_read_cylinder_structures (struct super_block * sb) {
size = uspi->s_bsize; size = uspi->s_bsize;
if (i + uspi->s_fpb > blks) if (i + uspi->s_fpb > blks)
size = (blks - i) * uspi->s_fsize; size = (blks - i) * uspi->s_fsize;
ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
if (!ubh) if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
goto failed; ubh = ubh_bread(sb,
ubh_ubhcpymem (space, ubh, size); fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
sbi->s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space; 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; space += size;
ubh_brelse (ubh); ubh_brelse (ubh);
ubh = NULL; ubh = NULL;
...@@ -480,6 +529,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -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_first * usb1;
struct ufs_super_block_second * usb2; struct ufs_super_block_second * usb2;
struct ufs_super_block_third * usb3; struct ufs_super_block_third * usb3;
struct ufs_super_block *usb;
struct ufs_buffer_head * ubh; struct ufs_buffer_head * ubh;
struct inode *inode; struct inode *inode;
unsigned block_size, super_block_size; unsigned block_size, super_block_size;
...@@ -520,7 +570,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -520,7 +570,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
if (!silent) if (!silent)
printk("You didn't specify the type of your ufs filesystem\n\n" printk("You didn't specify the type of your ufs filesystem\n\n"
"mount -t ufs -o ufstype=" "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, " ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
"default is ufstype=old\n"); "default is ufstype=old\n");
ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD); 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) ...@@ -545,6 +595,19 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_sbbase = 0; uspi->s_sbbase = 0;
flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
break; 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: case UFS_MOUNT_UFSTYPE_SUN:
UFSD(("ufstype=sun\n")) UFSD(("ufstype=sun\n"))
...@@ -657,27 +720,37 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -657,27 +720,37 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
/* /*
* read ufs super block from device * 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) if (!ubh)
goto failed; goto failed;
usb1 = ubh_get_usb_first(USPI_UBH); usb1 = ubh_get_usb_first(USPI_UBH);
usb2 = ubh_get_usb_second(USPI_UBH); usb2 = ubh_get_usb_second(USPI_UBH);
usb3 = ubh_get_usb_third(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 * 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 UFS_MAGIC:
case UFS2_MAGIC:
case UFS_MAGIC_LFN: case UFS_MAGIC_LFN:
case UFS_MAGIC_FEA: case UFS_MAGIC_FEA:
case UFS_MAGIC_4GB: case UFS_MAGIC_4GB:
sbi->s_bytesex = BYTESEX_LE; sbi->s_bytesex = BYTESEX_LE;
goto magic_found; 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 UFS_MAGIC:
case UFS2_MAGIC:
case UFS_MAGIC_LFN: case UFS_MAGIC_LFN:
case UFS_MAGIC_FEA: case UFS_MAGIC_FEA:
case UFS_MAGIC_4GB: case UFS_MAGIC_4GB:
...@@ -748,7 +821,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -748,7 +821,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
} }
#ifdef UFS_SUPER_DEBUG_MORE #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 #endif
/* /*
...@@ -802,8 +878,16 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -802,8 +878,16 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno); uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno);
uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset); uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset);
uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask); 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); uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg);
/* s_bsize already set */ /* s_bsize already set */
/* s_fsize already set */ /* s_fsize already set */
...@@ -1021,21 +1105,36 @@ int ufs_statfs (struct super_block * sb, struct kstatfs * buf) ...@@ -1021,21 +1105,36 @@ int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
{ {
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1; struct ufs_super_block_first * usb1;
struct ufs_super_block * usb;
unsigned flags = 0;
lock_kernel(); lock_kernel();
uspi = UFS_SB(sb)->s_uspi; uspi = UFS_SB(sb)->s_uspi;
usb1 = ubh_get_usb_first (USPI_UBH); 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_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_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_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
buf->f_files = uspi->s_ncg * uspi->s_ipg; 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; buf->f_namelen = UFS_MAXNAMLEN;
unlock_kernel(); unlock_kernel();
......
...@@ -24,10 +24,11 @@ ...@@ -24,10 +24,11 @@
struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, 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; struct ufs_buffer_head * ubh;
unsigned i, j, count; unsigned i, j ;
u64 count = 0;
if (size & ~uspi->s_fmask) if (size & ~uspi->s_fmask)
return NULL; return NULL;
count = size >> uspi->s_fshift; count = size >> uspi->s_fshift;
...@@ -53,9 +54,10 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, ...@@ -53,9 +54,10 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
} }
struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi, 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) if (size & ~uspi->s_fmask)
return NULL; return NULL;
count = size >> uspi->s_fshift; count = size >> uspi->s_fshift;
......
...@@ -228,8 +228,8 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value) ...@@ -228,8 +228,8 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
* These functions manipulate ufs buffers * These functions manipulate ufs buffers
*/ */
#define ubh_bread(sb,fragment,size) _ubh_bread_(uspi,sb,fragment,size) #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_(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 *, unsigned, unsigned); 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 (struct ufs_buffer_head *);
extern void ubh_brelse_uspi (struct ufs_sb_private_info *); extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *); extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *);
......
This diff is collapsed.
...@@ -17,6 +17,7 @@ struct ufs_inode_info { ...@@ -17,6 +17,7 @@ struct ufs_inode_info {
union { union {
__u32 i_data[15]; __u32 i_data[15];
__u8 i_symlink[4*15]; __u8 i_symlink[4*15];
__u64 u2_i_data[15];
} i_u1; } i_u1;
__u32 i_flags; __u32 i_flags;
__u32 i_gen; __u32 i_gen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment