patch-2.1.10 linux/fs/ext2/truncate.c
Next file: linux/include/asm-alpha/bitops.h
Previous file: linux/fs/ext2/super.c
Back to the patch index
Back to the overall index
- Lines: 243
- Date:
Thu Nov 14 10:27:38 1996
- Orig file:
v2.1.9/linux/fs/ext2/truncate.c
- Orig date:
Mon Dec 11 06:56:35 1995
diff -u --recursive --new-file v2.1.9/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c
@@ -11,6 +11,9 @@
* linux/fs/minix/truncate.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (davem@caip.rutgers.edu), 1995
*/
/*
@@ -140,7 +143,7 @@
if (i < indirect_block)
goto repeat;
ind = i + (u32 *) ind_bh->b_data;
- tmp = *ind;
+ tmp = le32_to_cpu(*ind);
if (!tmp)
continue;
bh = get_hash_table (inode->i_dev, tmp,
@@ -149,12 +152,12 @@
brelse (bh);
goto repeat;
}
- if ((bh && bh->b_count != 1) || tmp != *ind) {
+ if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
retry = 1;
brelse (bh);
continue;
}
- *ind = 0;
+ *ind = cpu_to_le32(0);
mark_buffer_dirty(ind_bh, 1);
bforget(bh);
if (free_count == 0) {
@@ -175,7 +178,7 @@
ext2_free_blocks (inode, block_to_free, free_count);
ind = (u32 *) ind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
- if (*(ind++))
+ if (le32_to_cpu(*(ind++)))
break;
if (i >= addr_per_block)
if (ind_bh->b_count != 1)
@@ -195,6 +198,93 @@
return retry;
}
+static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p)
+{
+ int i, tmp;
+ struct buffer_head * bh;
+ struct buffer_head * ind_bh;
+ u32 * ind;
+ unsigned long block_to_free = 0;
+ unsigned long free_count = 0;
+ int retry = 0;
+ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ int blocks = inode->i_sb->s_blocksize / 512;
+ int indirect_block = INDIRECT_BLOCK;
+
+ tmp = le32_to_cpu(*p);
+ if (!tmp)
+ return 0;
+ ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
+ if (tmp != le32_to_cpu(*p)) {
+ brelse (ind_bh);
+ return 1;
+ }
+ if (!ind_bh) {
+ *p = cpu_to_le32(0);
+ return 0;
+ }
+repeat:
+ for (i = indirect_block ; i < addr_per_block ; i++) {
+ if (i < 0)
+ i = 0;
+ if (i < indirect_block)
+ goto repeat;
+ ind = i + (u32 *) ind_bh->b_data;
+ tmp = le32_to_cpu(*ind);
+ if (!tmp)
+ continue;
+ bh = get_hash_table (inode->i_dev, tmp,
+ inode->i_sb->s_blocksize);
+ if (i < indirect_block) {
+ brelse (bh);
+ goto repeat;
+ }
+ if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
+ retry = 1;
+ brelse (bh);
+ continue;
+ }
+ *ind = cpu_to_le32(0);
+ mark_buffer_dirty(ind_bh, 1);
+ bforget(bh);
+ if (free_count == 0) {
+ block_to_free = tmp;
+ free_count++;
+ } else if (free_count > 0 && block_to_free == tmp - free_count)
+ free_count++;
+ else {
+ ext2_free_blocks (inode, block_to_free, free_count);
+ block_to_free = tmp;
+ free_count = 1;
+ }
+/* ext2_free_blocks (inode, tmp, 1); */
+ inode->i_blocks -= blocks;
+ inode->i_dirt = 1;
+ }
+ if (free_count > 0)
+ ext2_free_blocks (inode, block_to_free, free_count);
+ ind = (u32 *) ind_bh->b_data;
+ for (i = 0; i < addr_per_block; i++)
+ if (le32_to_cpu(*(ind++)))
+ break;
+ if (i >= addr_per_block)
+ if (ind_bh->b_count != 1)
+ retry = 1;
+ else {
+ tmp = le32_to_cpu(*p);
+ *p = cpu_to_le32(0);
+ inode->i_blocks -= blocks;
+ inode->i_dirt = 1;
+ ext2_free_blocks (inode, tmp, 1);
+ }
+ if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
+ ll_rw_block (WRITE, 1, &ind_bh);
+ wait_on_buffer (ind_bh);
+ }
+ brelse (ind_bh);
+ return retry;
+}
+
static int trunc_dindirect (struct inode * inode, int offset,
u32 * p)
{
@@ -226,16 +316,16 @@
if (i < dindirect_block)
goto repeat;
dind = i + (u32 *) dind_bh->b_data;
- tmp = *dind;
+ tmp = le32_to_cpu(*dind);
if (!tmp)
continue;
- retry |= trunc_indirect (inode, offset + (i * addr_per_block),
- dind);
+ retry |= trunc_indirect_swab32 (inode, offset + (i * addr_per_block),
+ dind);
mark_buffer_dirty(dind_bh, 1);
}
dind = (u32 *) dind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
- if (*(dind++))
+ if (le32_to_cpu(*(dind++)))
break;
if (i >= addr_per_block)
if (dind_bh->b_count != 1)
@@ -255,6 +345,65 @@
return retry;
}
+static int trunc_dindirect_swab32 (struct inode * inode, int offset,
+ u32 * p)
+{
+ int i, tmp;
+ struct buffer_head * dind_bh;
+ u32 * dind;
+ int retry = 0;
+ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ int blocks = inode->i_sb->s_blocksize / 512;
+ int dindirect_block = DINDIRECT_BLOCK;
+
+ tmp = le32_to_cpu(*p);
+ if (!tmp)
+ return 0;
+ dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
+ if (tmp != le32_to_cpu(*p)) {
+ brelse (dind_bh);
+ return 1;
+ }
+ if (!dind_bh) {
+ *p = cpu_to_le32(0);
+ return 0;
+ }
+repeat:
+ for (i = dindirect_block ; i < addr_per_block ; i++) {
+ if (i < 0)
+ i = 0;
+ if (i < dindirect_block)
+ goto repeat;
+ dind = i + (u32 *) dind_bh->b_data;
+ tmp = le32_to_cpu(*dind);
+ if (!tmp)
+ continue;
+ retry |= trunc_indirect_swab32 (inode, offset + (i * addr_per_block),
+ dind);
+ mark_buffer_dirty(dind_bh, 1);
+ }
+ dind = (u32 *) dind_bh->b_data;
+ for (i = 0; i < addr_per_block; i++)
+ if (le32_to_cpu(*(dind++)))
+ break;
+ if (i >= addr_per_block)
+ if (dind_bh->b_count != 1)
+ retry = 1;
+ else {
+ tmp = le32_to_cpu(*p);
+ *p = cpu_to_le32(0);
+ inode->i_blocks -= blocks;
+ inode->i_dirt = 1;
+ ext2_free_blocks (inode, tmp, 1);
+ }
+ if (IS_SYNC(inode) && buffer_dirty(dind_bh)) {
+ ll_rw_block (WRITE, 1, &dind_bh);
+ wait_on_buffer (dind_bh);
+ }
+ brelse (dind_bh);
+ return retry;
+}
+
static int trunc_tindirect (struct inode * inode)
{
int i, tmp;
@@ -287,14 +436,14 @@
if (i < tindirect_block)
goto repeat;
tind = i + (u32 *) tind_bh->b_data;
- retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
- addr_per_block + (i + 1) * addr_per_block * addr_per_block,
- tind);
+ retry |= trunc_dindirect_swab32(inode, EXT2_NDIR_BLOCKS +
+ addr_per_block + (i + 1) * addr_per_block * addr_per_block,
+ tind);
mark_buffer_dirty(tind_bh, 1);
}
tind = (u32 *) tind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
- if (*(tind++))
+ if (le32_to_cpu(*(tind++)))
break;
if (i >= addr_per_block)
if (tind_bh->b_count != 1)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov