Commit 99ac3092 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ufs2_frag_map_fix : fixes wrong content reading in ufs2 code

From: Niraj Kumar <niraj17@iitbombay.org>

This is in continuation of the ufs2 read-only code that went into 2.6.5.

This patch fixes a bug where wrong content was being read off the disk
after around 4 MB mark.
parent 957ce1ab
...@@ -56,13 +56,14 @@ ufs_readdir (struct file * filp, void * dirent, filldir_t filldir) ...@@ -56,13 +56,14 @@ ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
{ {
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
int error = 0; int error = 0;
unsigned long offset, lblk, blk; unsigned long offset, lblk;
int i, stored; int i, stored;
struct buffer_head * bh; struct buffer_head * bh;
struct ufs_dir_entry * de; struct ufs_dir_entry * de;
struct super_block * sb; struct super_block * sb;
int de_reclen; int de_reclen;
unsigned flags; unsigned flags;
u64 blk= 0L;
lock_kernel(); lock_kernel();
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#define UFSD(x) #define UFSD(x)
#endif #endif
static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4]) static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4])
{ {
struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
int ptrs = uspi->s_apb; int ptrs = uspi->s_apb;
...@@ -60,6 +60,8 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4]) ...@@ -60,6 +60,8 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
double_blocks = (1 << (ptrs_bits * 2)); double_blocks = (1 << (ptrs_bits * 2));
int n = 0; int n = 0;
UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%d \n",ptrs,double_blocks));
if (i_block < 0) { if (i_block < 0) {
ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0");
} else if (i_block < direct_blocks) { } else if (i_block < direct_blocks) {
...@@ -87,20 +89,23 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4]) ...@@ -87,20 +89,23 @@ static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
* the begining of the filesystem. * the begining of the filesystem.
*/ */
u64 ufs_frag_map(struct inode *inode, int frag) u64 ufs_frag_map(struct inode *inode, sector_t 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;
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
int mask = uspi->s_apbmask>>uspi->s_fpbshift; u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift;
int shift = uspi->s_apbshift-uspi->s_fpbshift; int shift = uspi->s_apbshift-uspi->s_fpbshift;
int offsets[4], *p; sector_t offsets[4], *p;
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; u64 ret = 0L;
u32 block; u32 block;
u64 u2_block = 0; u64 u2_block = 0L;
unsigned flags = UFS_SB(sb)->s_flags; unsigned flags = UFS_SB(sb)->s_flags;
u64 temp = 0; u64 temp = 0L;
UFSD((": frag = %lu depth = %d\n",frag,depth));
UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask));
if (depth == 0) if (depth == 0)
return 0; return 0;
...@@ -116,7 +121,7 @@ u64 ufs_frag_map(struct inode *inode, int frag) ...@@ -116,7 +121,7 @@ u64 ufs_frag_map(struct inode *inode, int frag)
goto out; goto out;
while (--depth) { while (--depth) {
struct buffer_head *bh; struct buffer_head *bh;
int n = *p++; sector_t n = *p++;
bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift)); bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
if (!bh) if (!bh)
...@@ -126,20 +131,21 @@ u64 ufs_frag_map(struct inode *inode, int frag) ...@@ -126,20 +131,21 @@ u64 ufs_frag_map(struct inode *inode, int frag)
if (!block) if (!block)
goto out; goto out;
} }
ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask); ret = (u64) (uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask));
goto out; goto out;
ufs2: ufs2:
u2_block = ufsi->i_u1.u2_i_data[*p++]; u2_block = ufsi->i_u1.u2_i_data[*p++];
if (!u2_block) if (!u2_block)
goto out; goto out;
temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block);
while (--depth) { while (--depth) {
struct buffer_head *bh; struct buffer_head *bh;
u64 n = *p++; sector_t n = *p++;
bh = sb_bread(sb, temp +(n>>shift));
temp = (u64)(uspi->s_sbbase) + fs64_to_cpu(sb, u2_block);
bh = sb_bread(sb, temp +(u64) (n>>shift));
if (!bh) if (!bh)
goto out; goto out;
u2_block = ((u64*)bh->b_data)[n & mask]; u2_block = ((u64*)bh->b_data)[n & mask];
...@@ -147,7 +153,8 @@ u64 ufs_frag_map(struct inode *inode, int frag) ...@@ -147,7 +153,8 @@ u64 ufs_frag_map(struct inode *inode, int frag)
if (!u2_block) if (!u2_block)
goto out; goto out;
} }
ret = temp + (frag & uspi->s_fpbmask); temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block);
ret = temp + (u64) (frag & uspi->s_fpbmask);
out: out:
unlock_kernel(); unlock_kernel();
...@@ -379,6 +386,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf ...@@ -379,6 +386,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf
if (!create) { if (!create) {
phys64 = ufs_frag_map(inode, fragment); phys64 = ufs_frag_map(inode, fragment);
UFSD(("phys64 = %lu \n",phys64));
if (phys64) if (phys64)
map_bh(bh_result, sb, phys64); map_bh(bh_result, sb, phys64);
return 0; return 0;
......
...@@ -93,6 +93,8 @@ ...@@ -93,6 +93,8 @@
#undef UFS_SUPER_DEBUG #undef UFS_SUPER_DEBUG
#undef UFS_SUPER_DEBUG_MORE #undef UFS_SUPER_DEBUG_MORE
#undef UFS_SUPER_DEBUG_MORE
#ifdef UFS_SUPER_DEBUG #ifdef UFS_SUPER_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;
#else #else
...@@ -157,6 +159,8 @@ void ufs2_print_super_stuff( ...@@ -157,6 +159,8 @@ void ufs2_print_super_stuff(
printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb->fs_magic)); 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_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_dsize: %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize));
printk(" bsize: %u\n", fs32_to_cpu(usb, usb->fs_bsize));
printk(" fsize: %u\n", fs32_to_cpu(usb, usb->fs_fsize));
printk(" fs_volname: %s\n", usb->fs_u11.fs_u2.fs_volname); 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_fsmnt: %s\n", usb->fs_u11.fs_u2.fs_fsmnt);
printk(" fs_sblockloc: %u\n",fs64_to_cpu(sb, printk(" fs_sblockloc: %u\n",fs64_to_cpu(sb,
...@@ -897,6 +901,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -897,6 +901,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift); uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift);
uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
UFSD(("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift,
uspi->s_fshift));
uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift); uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift);
uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb); uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb);
/* s_sbsize already set */ /* s_sbsize already set */
...@@ -929,7 +935,12 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -929,7 +935,12 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
* Compute another frequently used values * Compute another frequently used values
*/ */
uspi->s_fpbmask = uspi->s_fpb - 1; uspi->s_fpbmask = uspi->s_fpb - 1;
uspi->s_apbshift = uspi->s_bshift - 2; if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
uspi->s_apbshift = uspi->s_bshift - 3;
}
else {
uspi->s_apbshift = uspi->s_bshift - 2;
}
uspi->s_2apbshift = uspi->s_apbshift * 2; uspi->s_2apbshift = uspi->s_apbshift * 2;
uspi->s_3apbshift = uspi->s_apbshift * 3; uspi->s_3apbshift = uspi->s_apbshift * 3;
uspi->s_apb = 1 << uspi->s_apbshift; uspi->s_apb = 1 << uspi->s_apbshift;
......
...@@ -896,7 +896,7 @@ extern void ufs_free_inode (struct inode *inode); ...@@ -896,7 +896,7 @@ extern void ufs_free_inode (struct inode *inode);
extern struct inode * ufs_new_inode (struct inode *, int); extern struct inode * ufs_new_inode (struct inode *, int);
/* inode.c */ /* inode.c */
extern u64 ufs_frag_map (struct inode *, int); extern u64 ufs_frag_map (struct inode *, sector_t);
extern void ufs_read_inode (struct inode *); extern void ufs_read_inode (struct inode *);
extern void ufs_put_inode (struct inode *); extern void ufs_put_inode (struct inode *);
extern void ufs_write_inode (struct inode *, int); extern void ufs_write_inode (struct inode *, int);
......
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