Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[pandora-kernel.git] / fs / hfsplus / super.c
index 84a47b7..d24a9b6 100644 (file)
@@ -73,11 +73,13 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
 
        if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
            inode->i_ino == HFSPLUS_ROOT_CNID) {
-               hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
-               err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-               if (!err)
-                       err = hfsplus_cat_read_inode(inode, &fd);
-               hfs_find_exit(&fd);
+               err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+               if (!err) {
+                       err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+                       if (!err)
+                               err = hfsplus_cat_read_inode(inode, &fd);
+                       hfs_find_exit(&fd);
+               }
        } else {
                err = hfsplus_system_read_inode(inode);
        }
@@ -133,9 +135,13 @@ static int hfsplus_system_write_inode(struct inode *inode)
 static int hfsplus_write_inode(struct inode *inode,
                struct writeback_control *wbc)
 {
+       int err;
+
        dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
 
-       hfsplus_ext_write_extent(inode);
+       err = hfsplus_ext_write_extent(inode);
+       if (err)
+               return err;
 
        if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
            inode->i_ino == HFSPLUS_ROOT_CNID)
@@ -197,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
                write_backup = 1;
        }
 
-       error2 = hfsplus_submit_bio(sb->s_bdev,
+       error2 = hfsplus_submit_bio(sb,
                                   sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
-                                  sbi->s_vhdr, WRITE_SYNC);
+                                  sbi->s_vhdr_buf, NULL, WRITE_SYNC);
        if (!error)
                error = error2;
        if (!write_backup)
                goto out;
 
-       error2 = hfsplus_submit_bio(sb->s_bdev,
+       error2 = hfsplus_submit_bio(sb,
                                  sbi->part_start + sbi->sect_count - 2,
-                                 sbi->s_backup_vhdr, WRITE_SYNC);
+                                 sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC);
        if (!error)
                error2 = error;
 out:
@@ -251,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb)
        hfs_btree_close(sbi->ext_tree);
        iput(sbi->alloc_file);
        iput(sbi->hidden_dir);
-       kfree(sbi->s_vhdr);
-       kfree(sbi->s_backup_vhdr);
+       kfree(sbi->s_vhdr_buf);
+       kfree(sbi->s_backup_vhdr_buf);
        unload_nls(sbi->nls);
        kfree(sb->s_fs_info);
        sb->s_fs_info = NULL;
@@ -338,6 +344,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *root, *inode;
        struct qstr str;
        struct nls_table *nls = NULL;
+       u64 last_fs_block, last_fs_page;
        int err;
 
        err = -EINVAL;
@@ -393,6 +400,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi->rsrc_clump_blocks)
                sbi->rsrc_clump_blocks = 1;
 
+       err = -EFBIG;
+       last_fs_block = sbi->total_blocks - 1;
+       last_fs_page = (last_fs_block << sbi->alloc_blksz_shift) >>
+                       PAGE_CACHE_SHIFT;
+
+       if ((last_fs_block > (sector_t)(~0ULL) >> (sbi->alloc_blksz_shift - 9)) ||
+           (last_fs_page > (pgoff_t)(~0ULL))) {
+               printk(KERN_ERR "hfs: filesystem size too large.\n");
+               goto out_free_vhdr;
+       }
+
        /* Set up operations so we can load metadata */
        sb->s_op = &hfsplus_sops;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -417,6 +435,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                sb->s_flags |= MS_RDONLY;
        }
 
+       err = -EINVAL;
+
        /* Load metadata objects (B*Trees) */
        sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
        if (!sbi->ext_tree) {
@@ -447,7 +467,9 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 
        str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
        str.name = HFSP_HIDDENDIR_NAME;
-       hfs_find_init(sbi->cat_tree, &fd);
+       err = hfs_find_init(sbi->cat_tree, &fd);
+       if (err)
+               goto out_put_root;
        hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
        if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
                hfs_find_exit(&fd);
@@ -508,8 +530,8 @@ out_close_cat_tree:
 out_close_ext_tree:
        hfs_btree_close(sbi->ext_tree);
 out_free_vhdr:
-       kfree(sbi->s_vhdr);
-       kfree(sbi->s_backup_vhdr);
+       kfree(sbi->s_vhdr_buf);
+       kfree(sbi->s_backup_vhdr_buf);
 out_unload_nls:
        unload_nls(sbi->nls);
        unload_nls(nls);