Merge to Fedora kernel-2.6.18-1.2257_FC5 patched with stable patch-2.6.18.5-vs2.0...
[linux-2.6.git] / fs / squashfs / squashfs2_0.c
index f163523..38ee736 100644 (file)
@@ -73,13 +73,12 @@ static int read_fragment_index_table_2(struct super_block *s)
        }
    
        if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
-                       !squashfs_read_data(s, (char *)
-                       msblk->fragment_index_2,
-                       sblk->fragment_table_start,
-                       SQUASHFS_FRAGMENT_INDEX_BYTES_2
-                       (sblk->fragments) |
-                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
-                       SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
+                                       !squashfs_read_data(s, (char *)
+                                       msblk->fragment_index_2,
+                                       sblk->fragment_table_start,
+                                       SQUASHFS_FRAGMENT_INDEX_BYTES_2
+                                       (sblk->fragments) |
+                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
                ERROR("unable to read fragment index table\n");
                return 0;
        }
@@ -136,42 +135,35 @@ out:
 }
 
 
-static struct inode *squashfs_new_inode(struct super_block *s,
+static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
                struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
 {
-       struct squashfs_sb_info *msblk = s->s_fs_info;
        struct squashfs_super_block *sblk = &msblk->sblk;
-       struct inode *i = new_inode(s);
-
-       if (i) {
-               i->i_ino = ino;
-               i->i_mtime.tv_sec = sblk->mkfs_time;
-               i->i_atime.tv_sec = sblk->mkfs_time;
-               i->i_ctime.tv_sec = sblk->mkfs_time;
-               i->i_uid = msblk->uid[inodeb->uid];
-               i->i_mode = inodeb->mode;
-               i->i_nlink = 1;
-               i->i_size = 0;
-               if (inodeb->guid == SQUASHFS_GUIDS)
-                       i->i_gid = i->i_uid;
-               else
-                       i->i_gid = msblk->guid[inodeb->guid];
-       }
 
-       return i;
+       i->i_ino = ino;
+       i->i_mtime.tv_sec = sblk->mkfs_time;
+       i->i_atime.tv_sec = sblk->mkfs_time;
+       i->i_ctime.tv_sec = sblk->mkfs_time;
+       i->i_uid = msblk->uid[inodeb->uid];
+       i->i_mode = inodeb->mode;
+       i->i_nlink = 1;
+       i->i_size = 0;
+       if (inodeb->guid == SQUASHFS_GUIDS)
+               i->i_gid = i->i_uid;
+       else
+               i->i_gid = msblk->guid[inodeb->guid];
 }
 
 
-static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
+static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
 {
-       struct inode *i;
+       struct super_block *s = i->i_sb;
        struct squashfs_sb_info *msblk = s->s_fs_info;
        struct squashfs_super_block *sblk = &msblk->sblk;
        unsigned int block = SQUASHFS_INODE_BLK(inode) +
                sblk->inode_table_start;
        unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
-       unsigned int ino = SQUASHFS_MK_VFS_INODE(block
-               - sblk->inode_table_start, offset);
+       unsigned int ino = i->i_ino;
        long long next_block;
        unsigned int next_offset;
        union squashfs_inode_header_2 id, sid;
@@ -193,6 +185,8 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                        &next_offset))
                        goto failed_read;
 
+       squashfs_new_inode(msblk, i, inodeb, ino);
+
        switch(inodeb->inode_type) {
                case SQUASHFS_FILE_TYPE: {
                        struct squashfs_reg_inode_header_2 *inodep = &id.reg;
@@ -220,9 +214,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                        inodep->fragment, &frag_blk, &frag_size))
                                goto failed_read;
                                
-                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
-
                        i->i_size = inodep->file_size;
                        i->i_fop = &generic_ro_fops;
                        i->i_mode |= S_IFREG;
@@ -266,9 +257,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                                &next_offset))
                                        goto failed_read;
 
-                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
-
                        i->i_size = inodep->file_size;
                        i->i_op = &squashfs_dir_inode_ops_2;
                        i->i_fop = &squashfs_dir_ops_2;
@@ -306,9 +294,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                                &next_offset))
                                        goto failed_read;
 
-                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
-
                        i->i_size = inodep->file_size;
                        i->i_op = &squashfs_dir_inode_ops_2;
                        i->i_fop = &squashfs_dir_ops_2;
@@ -352,9 +337,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                                &next_offset))
                                        goto failed_read;
 
-                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
-
                        i->i_size = inodep->symlink_size;
                        i->i_op = &page_symlink_inode_operations;
                        i->i_data.a_ops = &squashfs_symlink_aops;
@@ -387,9 +369,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                                                &next_offset))
                                        goto failed_read;
 
-                       if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
-
                        i->i_mode |= (inodeb->inode_type ==
                                        SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
                                        S_IFBLK;
@@ -403,8 +382,6 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                 }
                 case SQUASHFS_FIFO_TYPE:
                 case SQUASHFS_SOCKET_TYPE: {
-                       if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
-                               goto failed_read1;
 
                        i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
                                                        ? S_IFIFO : S_IFSOCK;
@@ -417,14 +394,13 @@ static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t ino
                        goto failed_read1;
        }
        
-       insert_inode_hash(i);
-       return i;
+       return 1;
 
 failed_read:
        ERROR("Unable to read inode [%x:%x]\n", block, offset);
 
 failed_read1:
-       return NULL;
+       return 0;
 }
 
 
@@ -486,12 +462,18 @@ static int get_dir_index_using_name(struct super_block *s, long long
        struct squashfs_sb_info *msblk = s->s_fs_info;
        struct squashfs_super_block *sblk = &msblk->sblk;
        int i, length = 0;
-       char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
-       struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
-       char str[SQUASHFS_NAME_LEN + 1];
+       struct squashfs_dir_index_2 *index;
+       char *str;
 
        TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
 
+       if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
+               (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
+               ERROR("Failed to allocate squashfs_dir_index\n");
+               goto failure;
+       }
+
+       index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
        strncpy(str, name, size);
        str[size] = '\0';
 
@@ -523,6 +505,8 @@ static int get_dir_index_using_name(struct super_block *s, long long
        }
 
        *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+       kfree(str);
+failure:
        return length;
 }
 
@@ -534,14 +518,19 @@ static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir
        struct squashfs_super_block *sblk = &msblk->sblk;
        long long next_block = SQUASHFS_I(i)->start_block +
                sblk->directory_table_start;
-       int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+       int next_offset = SQUASHFS_I(i)->offset, length = 0,
                dir_count;
        struct squashfs_dir_header_2 dirh;
-       char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
-       struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+       struct squashfs_dir_entry_2 *dire;
 
        TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
 
+       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
+               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
+               ERROR("Failed to allocate squashfs_dir_entry\n");
+               goto finish;
+       }
+
        length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
                                SQUASHFS_I(i)->u.s2.directory_index_start,
                                SQUASHFS_I(i)->u.s2.directory_index_offset,
@@ -619,16 +608,17 @@ static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir
                                goto finish;
                        }
                        file->f_pos = length;
-                       dirs_read++;
                }
        }
 
 finish:
-       return dirs_read;
+       kfree(dire);
+       return 0;
 
 failed_read:
        ERROR("Unable to read directory block [%llx:%x]\n", next_block,
                next_offset);
+       kfree(dire);
        return 0;
 }
 
@@ -646,11 +636,16 @@ static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
        int next_offset = SQUASHFS_I(i)->offset, length = 0,
                                dir_count;
        struct squashfs_dir_header_2 dirh;
-       char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
-       struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+       struct squashfs_dir_entry_2 *dire;
        int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
 
-       TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+       TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
+
+       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
+               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
+               ERROR("Failed to allocate squashfs_dir_entry\n");
+               goto exit_loop;
+       }
 
        if (len > SQUASHFS_NAME_LEN)
                goto exit_loop;
@@ -718,12 +713,14 @@ static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
                                squashfs_inode_t ino =
                                        SQUASHFS_MKINODE(dirh.start_block,
                                        dire->offset);
+                               unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
+                                       dire->offset);
 
                                TRACE("calling squashfs_iget for directory "
                                        "entry %s, inode %x:%x, %lld\n", name,
                                        dirh.start_block, dire->offset, ino);
 
-                               inode = (msblk->iget)(i->i_sb, ino);
+                               inode = squashfs_iget(i->i_sb, ino, inode_number);
 
                                goto exit_loop;
                        }
@@ -731,6 +728,7 @@ static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
        }
 
 exit_loop:
+       kfree(dire);
        d_add(dentry, inode);
        return ERR_PTR(0);
 
@@ -745,7 +743,7 @@ int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
 {
        struct squashfs_super_block *sblk = &msblk->sblk;
 
-       msblk->iget = squashfs_iget_2;
+       msblk->read_inode = squashfs_read_inode_2;
        msblk->read_fragment_index_table = read_fragment_index_table_2;
 
        sblk->bytes_used = sblk->bytes_used_2;