hfsplus: avoid crash on failed block map free
Alan Cox [Thu, 20 Dec 2012 23:05:24 +0000 (15:05 -0800)]
If the read fails we kmap an error code.  This doesn't end well.  Instead
print a critical error and pray.  This mirrors the rest of the fs
behaviour with critical error cases.

Acked-by: Vyacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jan Kara <jack@suse.cz>
Acked-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

fs/hfsplus/bitmap.c

index 4cfbe2e..6feefc0 100644 (file)
@@ -176,12 +176,14 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
        dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
        /* are all of the bits in range? */
        if ((offset + count) > sbi->total_blocks)
-               return -2;
+               return -ENOENT;
 
        mutex_lock(&sbi->alloc_mutex);
        mapping = sbi->alloc_file->i_mapping;
        pnr = offset / PAGE_CACHE_BITS;
        page = read_mapping_page(mapping, pnr, NULL);
+       if (IS_ERR(page))
+               goto kaboom;
        pptr = kmap(page);
        curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
        end = pptr + PAGE_CACHE_BITS / 32;
@@ -214,6 +216,8 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
                set_page_dirty(page);
                kunmap(page);
                page = read_mapping_page(mapping, ++pnr, NULL);
+               if (IS_ERR(page))
+                       goto kaboom;
                pptr = kmap(page);
                curr = pptr;
                end = pptr + PAGE_CACHE_BITS / 32;
@@ -232,4 +236,11 @@ out:
        mutex_unlock(&sbi->alloc_mutex);
 
        return 0;
+
+kaboom:
+       printk(KERN_CRIT "hfsplus: unable to mark blocks free: error %ld\n",
+                       PTR_ERR(page));
+       mutex_unlock(&sbi->alloc_mutex);
+
+       return -EIO;
 }