2.4.0-test9: minixfs causing oopsen when out of inodes

From: Russell King (rmk@arm.linux.org.uk)
Date: Sun Oct 08 2000 - 10:17:43 EDT

  • Next message: Linus Torvalds: "Re: MIME QP encoded good/bad ..."

    Hi,

    There appears to be a nasty problem when a minix filesystem runs out of
    inodes 2.4.0-test9. I've spotted this because I'm using a small ramdisk
    (about 128k with 42 inodes) which contains the contents of /var/run and
    /var/lock on a NFS rooted machine. I've recently changed the user-space
    binaries, and the ramdisk needs enlarging, but before I did this, I was
    getting lots of oopsen from fetchmail.

    I can cause them by doing the following:

    1. Create a small minix ramdisk
    2. mount it
    3. fill it up touching lots of files until it complains about
       "No space left on device"
    4. touch another file - it still complains about no space, and no oops.
    5. touch *the same file* again as you did in (4), and receive an oops
       for your efforts.

    Note that you can repeat (4) as many times as you like, and it will always
    complain with the same error, but no oops. Also note that in step 5, if
    you stat the file, you also get an oops.

    It appears that the above is caused by an uninitialised return value:

            minix_create()
            {
                    int error;
                    inode = minix_new_inode(dir, &error);
                    if (error)
                            return error;
            }

            minix_new_inode(... int *error)
            {
                    inode = get_empty_inode();
                    if (!inode)
                            return NULL;
            }

    The only time that minix_new_inode sets *error is if it succeeds! The
    same applies to minix_mknod, minix_mkdir, and minix_symlink. With this
    fixed, the above oops no longer happens. Here is a patch to fix this.
    This makes minix follow the same "method" as ext2fs towards returning
    errors from *_new_inode:

    diff -u orig/fs/minix/bitmap.c linux/fs/minix/bitmap.c
    --- orig/fs/minix/bitmap.c Mon Oct 2 10:06:36 2000
    +++ linux/fs/minix/bitmap.c Sun Oct 8 14:56:55 2000
    @@ -225,13 +225,16 @@
             int i,j;
     
             inode = get_empty_inode();
    - if (!inode)
    + if (!inode) {
    + *error = -ENOMEM;
                     return NULL;
    + }
             sb = dir->i_sb;
             inode->i_sb = sb;
             inode->i_flags = 0;
             j = 8192;
             bh = NULL;
    + *error = -ENOSPC;
             lock_super(sb);
             for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
                     bh = inode->i_sb->u.minix_sb.s_imap[i];
    diff -u orig/fs/minix/namei.c linux/fs/minix/namei.c
    --- orig/fs/minix/namei.c Mon Oct 2 10:06:36 2000
    +++ linux/fs/minix/namei.c Sun Oct 8 14:55:06 2000
    @@ -210,10 +210,8 @@
             struct minix_dir_entry * de;
     
             inode = minix_new_inode(dir, &error);
    - if (error)
    - return error;
             if (!inode)
    - return -ENOSPC;
    + return error;
             inode->i_op = &minix_file_inode_operations;
             inode->i_fop = &minix_file_operations;
             inode->i_mapping->a_ops = &minix_aops;
    @@ -242,10 +240,8 @@
             struct minix_dir_entry * de;
     
             inode = minix_new_inode(dir, &error);
    - if (error)
    - return error;
             if (!inode)
    - return -ENOSPC;
    + return error;
             inode->i_uid = current->fsuid;
             init_special_inode(inode, mode, rdev);
             mark_inode_dirty(inode);
    @@ -275,10 +271,8 @@
             if (dir->i_nlink >= info->s_link_max)
                     return -EMLINK;
             inode = minix_new_inode(dir, &error);
    - if (error)
    - return error;
             if (!inode)
    - return -ENOSPC;
    + return error;
             inode->i_op = &minix_dir_inode_operations;
             inode->i_fop = &minix_dir_operations;
             inode->i_size = 2 * info->s_dirsize;
    @@ -461,9 +455,6 @@
             if (i>1024)
                     goto out;
             inode = minix_new_inode(dir, &err);
    - if (err)
    - goto out;
    - err = -ENOSPC;
             if (!inode)
                     goto out;
     
       _____
      |_____| ------------------------------------------------- ---+---+-
      | | Russell King rmk@arm.linux.org.uk --- ---
      | | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
      | +-+-+ --- -+-
      / | THE developer of ARM Linux |+| /|\
     / | | | --- |
        +-+-+ ------------------------------------------------- /\\\ |
    -
    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 : Sun Oct 08 2000 - 10:21:44 EDT