Theodore Ts'o writes:
> Dr. Michael Weller writes:
> >  Sorry, I've no idea about the ext2 and fs implementation.
> >  However did you read the comment below and convince yourself that 'err' is
> >  always set correctly?
> 
> I looked at it and was convinced.

Ted and I submitted patches to this effect some months ago after I went
through all of the code paths for ext2_new_inode(), and I even thought
we removed all the comments about ext2_new_inode() not setting err.  See
thread http://kernelnotes.org/lnxlists/linux-kernel/lk_0005_05/msg00090.html
for more information.

It looks like it made it into test1-ac4 but was lost in test2...  Some of
the older patch is now irrelevant because ext2_getblk() was rewritten, so
here is a newer version of the patch to fix the error return codes.

Ted, please have a look (it is basically the same as the old patch), and
send it on to Linus.

Cheers, Andreas
---- cut here ----
diff -u linux/fs/ext2/balloc.c~ linux/fs/ext2/balloc.c
--- linux/fs/ext2/balloc.c~     Mon May 29 20:05:45 2000
+++ linux/fs/ext2/balloc.c      Fri Sep 01 13:42:21 2000
@@ -470,10 +470,8 @@
                if (i >= sb->u.ext2_sb.s_groups_count)
                        i = 0;
                gdp = ext2_get_group_desc (sb, i, &bh2);
-               if (!gdp) {
-                       *err = -EIO;
-                       goto out;
-               }
+               if (!gdp)
+                       goto io_error;
                if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
                        break;
        }
diff -u linux/fs/ext2/ialloc.c~ linux/fs/ext2/ialloc.c
--- linux/fs/ext2/ialloc.c~     Mon May 29 20:05:45 2000
+++ linux/fs/ext2/ialloc.c      Fri Sep 01 13:42:21 2000
@@ -286,8 +286,7 @@
        es = sb->u.ext2_sb.s_es;
 repeat:
        gdp = NULL; i=0;
-       
-       *err = -ENOSPC;
+
        if (S_ISDIR(mode)) {
                avefreei = le32_to_cpu(es->s_free_inodes_count) /
                        sb->u.ext2_sb.s_groups_count;
@@ -369,6 +368,7 @@
        if (!gdp) {
                unlock_super (sb);
                iput(inode);
+               *err = -ENOSPC;
                return NULL;
        }
        bitmap_nr = load_inode_bitmap (sb, i);
@@ -416,9 +416,8 @@
                        ext2_error (sb, "ext2_new_inode",
                                    "Free inodes count corrupted in group %d",
                                    i);
-                       unlock_super (sb);
-                       iput (inode);
-                       return NULL;
+                       /* If we continue recover from this case */
+                       gdp->bg_free_inodes_count = 0;
                }
                goto repeat;
        }
@@ -429,6 +428,7 @@
                            "block_group = %d,inode=%d", i, j);
                unlock_super (sb);
                iput (inode);
+               *err = -EIO;     /* Should never happen */
                return NULL;
        }
        gdp->bg_free_inodes_count =
diff -u linux/fs/ext2/inode.c~ linux/fs/ext2/inode.c
--- linux/fs/ext2/inode.c~      Sun Mar 26 21:34:49 2000
+++ linux/fs/ext2/inode.c       Mon May 29 10:36:34 2000
@@ -117,7 +117,7 @@
                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",
@@ -606,13 +606,11 @@
 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)) {
@@ -940,8 +938,23 @@
        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))
diff -u linux/fs/ext2/namei.c~ linux/fs/ext2/namei.c
--- linux/fs/ext2/namei.c~      Thu Apr 27 22:42:20 2000
+++ linux/fs/ext2/namei.c       Fri Sep 01 09:30:51 2000
@@ -366,12 +366,9 @@
        struct inode * inode;
        int err;
 
-       /*
-        * N.B. Several error exits in ext2_new_inode don't set err.
-        */
        inode = ext2_new_inode (dir, mode, &err);
        if (!inode)
-               return -EIO;
+               return err;
 
        inode->i_op = &ext2_file_inode_operations;
        inode->i_fop = &ext2_file_operations;
@@ -397,7 +394,7 @@
 
        inode = ext2_new_inode (dir, mode, &err);
        if (!inode)
-               return -EIO;
+               return err;
 
        inode->i_uid = current->fsuid;
        init_special_inode(inode, mode, rdev);
@@ -428,7 +428,7 @@
 
        inode = ext2_new_inode (dir, S_IFDIR, &err);
        if (!inode)
-               return -EIO;
+               return err;
 
        inode->i_op = &ext2_dir_inode_operations;
        inode->i_fop = &ext2_dir_operations;
@@ -439,7 +439,7 @@
                inode->i_nlink--; /* is this nlink == 0? */
                mark_inode_dirty(inode);
                iput (inode);
-               return -EIO;
+               return err;
        }
        de = (struct ext2_dir_entry_2 *) dir_block->b_data;
        de->inode = cpu_to_le32(inode->i_ino);
@@ -634,7 +631,7 @@
                return -ENAMETOOLONG;
 
        if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
-               return -EIO;
+               return err;
 
        inode->i_mode = S_IFLNK | S_IRWXUGO;
 
---- cut here ----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to