patch-2.1.93 linux/fs/ext2/inode.c
Next file: linux/fs/ext2/ioctl.c
Previous file: linux/fs/ext2/ialloc.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Thu Apr 2 13:39:52 1998
- Orig file:
v2.1.92/linux/fs/ext2/inode.c
- Orig date:
Wed Apr 1 20:11:53 1998
diff -u --recursive --new-file v2.1.92/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
@@ -12,9 +12,12 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
- * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ * Goal-directed block allocation by Stephen Tweedie
+ * (sct@dcs.ed.ac.uk), 1993, 1998
* Big-endian to little-endian byte-swapping/bitmaps by
* David S. Miller (davem@caip.rutgers.edu), 1995
+ * 64-bit file support on 64-bit platforms by Jakub Jelinek
+ * (jj@sunsite.ms.mff.cuni.cz)
*/
#include <asm/uaccess.h>
@@ -417,9 +420,44 @@
int create, int *err)
{
struct buffer_head * bh;
-
+ int prev_blocks;
+
+ prev_blocks = inode->i_blocks;
+
bh = ext2_getblk (inode, block, create, err);
- if (!bh || buffer_uptodate(bh))
+ if (!bh)
+ return bh;
+
+ /*
+ * If the inode has grown, and this is a directory, then perform
+ * preallocation of a few more blocks to try to keep directory
+ * fragmentation down.
+ */
+ if (create &&
+ S_ISDIR(inode->i_mode) &&
+ inode->i_blocks > prev_blocks &&
+ EXT2_HAS_COMPAT_FEATURE(inode->i_sb,
+ EXT2_FEATURE_COMPAT_DIR_PREALLOC)) {
+ int i;
+ struct buffer_head *tmp_bh;
+
+ for (i = 1;
+ i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
+ i++) {
+ /*
+ * ext2_getblk will zero out the contents of the
+ * directory for us
+ */
+ tmp_bh = ext2_getblk(inode, block+i, create, err);
+ if (!tmp_bh) {
+ brelse (bh);
+ return 0;
+ }
+ brelse (tmp_bh);
+ }
+ }
+
+ if (buffer_uptodate(bh))
return bh;
ll_rw_block (READ, 1, &bh);
wait_on_buffer (bh);
@@ -447,18 +485,23 @@
inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
ext2_error (inode->i_sb, "ext2_read_inode",
"bad inode number: %lu", inode->i_ino);
- return;
+ goto bad_inode;
}
block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
- if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
- ext2_panic (inode->i_sb, "ext2_read_inode",
+ if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+ ext2_error (inode->i_sb, "ext2_read_inode",
"group >= groups count");
+ goto bad_inode;
+ }
group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
- if (!bh)
- ext2_panic (inode->i_sb, "ext2_read_inode",
+ if (!bh) {
+ ext2_error (inode->i_sb, "ext2_read_inode",
"Descriptor not loaded");
+ goto bad_inode;
+ }
+
gdp = (struct ext2_group_desc *) bh->b_data;
/*
* Figure out the offset within the block group inode table
@@ -467,10 +510,12 @@
EXT2_INODE_SIZE(inode->i_sb);
block = le32_to_cpu(gdp[desc].bg_inode_table) +
(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
- if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
- ext2_panic (inode->i_sb, "ext2_read_inode",
- "unable to read i-node block - "
+ if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+ ext2_error (inode->i_sb, "ext2_read_inode",
+ "unable to read inode block - "
"inode=%lu, block=%lu", inode->i_ino, block);
+ goto bad_inode;
+ }
offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
raw_inode = (struct ext2_inode *) (bh->b_data + offset);
@@ -493,7 +538,20 @@
inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
inode->u.ext2_i.i_osync = 0;
inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
- inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+ if (S_ISDIR(inode->i_mode))
+ inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+ else {
+ inode->u.ext2_i.i_dir_acl = 0;
+ inode->u.ext2_i.i_high_size =
+ le32_to_cpu(raw_inode->i_size_high);
+#if BITS_PER_LONG < 64
+ if (raw_inode->i_size_high)
+ inode->i_size = (__u32)-1;
+#else
+ inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high))
+ << 32;
+#endif
+ }
inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
inode->u.ext2_i.i_block_group = block_group;
inode->u.ext2_i.i_next_alloc_block = 0;
@@ -542,6 +600,11 @@
inode->i_attr_flags |= ATTR_FLAG_NOATIME;
inode->i_flags |= MS_NOATIME;
}
+ return;
+
+bad_inode:
+ make_bad_inode(inode);
+ return;
}
static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -561,18 +624,22 @@
inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
ext2_error (inode->i_sb, "ext2_write_inode",
"bad inode number: %lu", inode->i_ino);
- return 0;
+ return -EIO;
}
block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
- if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
- ext2_panic (inode->i_sb, "ext2_write_inode",
+ if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+ ext2_error (inode->i_sb, "ext2_write_inode",
"group >= groups count");
+ return -EIO;
+ }
group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
- if (!bh)
- ext2_panic (inode->i_sb, "ext2_write_inode",
+ if (!bh) {
+ ext2_error (inode->i_sb, "ext2_write_inode",
"Descriptor not loaded");
+ return -EIO;
+ }
gdp = (struct ext2_group_desc *) bh->b_data;
/*
* Figure out the offset within the block group inode table
@@ -581,10 +648,12 @@
EXT2_INODE_SIZE(inode->i_sb);
block = le32_to_cpu(gdp[desc].bg_inode_table) +
(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
- if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
- ext2_panic (inode->i_sb, "ext2_write_inode",
- "unable to read i-node block - "
+ if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
+ ext2_error (inode->i_sb, "ext2_write_inode",
+ "unable to read inode block - "
"inode=%lu, block=%lu", inode->i_ino, block);
+ return -EIO;
+ }
offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
raw_inode = (struct ext2_inode *) (bh->b_data + offset);
@@ -603,7 +672,16 @@
raw_inode->i_frag = inode->u.ext2_i.i_frag_no;
raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;
raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
- raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+ if (S_ISDIR(inode->i_mode))
+ raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+ else {
+#if BITS_PER_LONG < 64
+ raw_inode->i_size_high =
+ cpu_to_le32(inode->u.ext2_i.i_high_size);
+#else
+ raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
+#endif
+ }
raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
@@ -620,7 +698,7 @@
printk ("IO error syncing ext2 inode ["
"%s:%08lx]\n",
kdevname(inode->i_dev), inode->i_ino);
- err = -1;
+ err = -EIO;
}
}
brelse (bh);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov