summaryrefslogtreecommitdiffstats
path: root/fs/ext2/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2/inode.c')
-rw-r--r--fs/ext2/inode.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 7e5263fb1..d3abb7cb2 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -117,7 +117,7 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
inode->u.ext2_i.i_prealloc_count--;
ext2_debug ("preallocation hit (%lu/%lu).\n",
++alloc_hits, ++alloc_attempts);
-
+ *err = 0;
} else {
ext2_discard_prealloc (inode);
ext2_debug ("preallocation miss (%lu/%lu).\n",
@@ -200,6 +200,7 @@ out:
return ret;
}
+/* returns NULL and sets *err on error */
static struct buffer_head * inode_getblk (struct inode * inode, int nr,
int new_block, int * err, int metadata, long *phys, int *new)
{
@@ -223,7 +224,6 @@ repeat:
return NULL;
}
}
- *err = -EFBIG;
/* Check file limits.. */
{
@@ -311,7 +311,7 @@ repeat:
* can fail due to: - not present
* - out of space
*
- * NULL return in the data case is mandatory.
+ * NULL return in the data case, or an error, is mandatory.
*/
static struct buffer_head * block_getblk (struct inode * inode,
struct buffer_head * bh, int nr,
@@ -341,6 +341,7 @@ repeat:
if (tmp == le32_to_cpu(*p))
goto out;
brelse (result);
+ result = NULL;
goto repeat;
} else {
*phys = tmp;
@@ -402,11 +403,9 @@ repeat:
*new = 1;
}
*p = le32_to_cpu(tmp);
- mark_buffer_dirty(bh, 1);
- if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
+ mark_buffer_dirty_inode(bh, 1, inode);
+ if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)
ll_rw_block (WRITE, 1, &bh);
- wait_on_buffer (bh);
- }
inode->i_ctime = CURRENT_TIME;
inode->i_blocks += blocksize/512;
mark_inode_dirty(inode);
@@ -487,9 +486,9 @@ static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *
#define GET_INODE_PTR(x) \
inode_getblk(inode, x, iblock, &err, 1, NULL, NULL)
#define GET_INDIRECT_DATABLOCK(x) \
- block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new);
+ block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new)
#define GET_INDIRECT_PTR(x) \
- block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL);
+ block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL)
if (ptr < direct_blocks) {
bh = GET_INODE_DATABLOCK(ptr);
@@ -547,13 +546,11 @@ abort_too_big:
struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err)
{
struct buffer_head dummy;
- int error;
dummy.b_state = 0;
dummy.b_blocknr = -1000;
- error = ext2_get_block(inode, block, &dummy, create);
- *err = error;
- if (!error && buffer_mapped(&dummy)) {
+ *err = ext2_get_block(inode, block, &dummy, create);
+ if (!*err && buffer_mapped(&dummy)) {
struct buffer_head *bh;
bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
if (buffer_new(&dummy)) {
@@ -881,8 +878,23 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
if (S_ISDIR(inode->i_mode))
raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
- else
+ else {
raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
+ if (inode->i_size >> 31) {
+ struct super_block *sb = inode->i_sb;
+ struct ext2_super_block *es = sb->u.ext2_sb.s_es;
+ if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+ /* If this is the first large file
+ * created, add a flag to the superblock
+ * SMP Note: we're currently protected by the
+ * big kernel lock here, so this will need
+ * to be changed if that's no longer true.
+ */
+ es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+ ext2_write_super(sb);
+ }
+ }
+ }
raw_inode->i_generation = cpu_to_le32(inode->i_generation);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
@@ -904,10 +916,10 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
return err;
}
-void ext2_write_inode (struct inode * inode)
+void ext2_write_inode (struct inode * inode, int wait)
{
lock_kernel();
- ext2_update_inode (inode, 0);
+ ext2_update_inode (inode, wait);
unlock_kernel();
}