Re: Small bugfix in ext2/namei.c

From: Andreas Dilger (adilger@turbolinux.com)
Date: Fri Sep 01 2000 - 16:20:00 EDT

  • Next message: Rasmus Andersen: "Re: [patchlet] Removing unneeded line in vmtruncate() (2.4.0-t8p1)"

    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 majordomo@vger.kernel.org
    Please read the FAQ at http://www.tux.org/lkml/



    This archive was generated by hypermail 2b29 : Fri Sep 01 2000 - 16:22:58 EDT