In ufs_change_blocknr() we have called page_buffers() without checking if the page actually had pages attached to it and this could cause a BUG oops. This work was supported by a hardware donation from the CE Linux Forum. Signed-off-by: Alessio Igor Bogani <abogani@xxxxxxxxxx> --- fs/ufs/balloc.c | 62 +++++++++++++++++++++++++++--------------------------- 1 files changed, 31 insertions(+), 31 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 46f7a80..8155ccd 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -276,46 +276,46 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, } else page = locked_page; - head = page_buffers(page); - bh = head; - pos = i & mask; - for (j = 0; j < pos; ++j) - bh = bh->b_this_page; - - if (unlikely(index == last_index)) lblock = end & mask; else lblock = blks_per_page; - do { - if (j >= lblock) - break; - pos = (i - beg) + j; + if (page_has_buffers(page)) { + bh = head = page_buffers(page); + pos = i & mask; + for (j = 0; j < pos; ++j) + bh = bh->b_this_page; - if (!buffer_mapped(bh)) - map_bh(bh, inode->i_sb, oldb + pos); - if (!buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) { - ufs_error(inode->i_sb, __func__, - "read of block failed\n"); + do { + if (j >= lblock) break; + pos = (i - beg) + j; + + if (!buffer_mapped(bh)) + map_bh(bh, inode->i_sb, oldb + pos); + if (!buffer_uptodate(bh)) { + ll_rw_block(READ, 1, &bh); + wait_on_buffer(bh); + if (!buffer_uptodate(bh)) { + ufs_error(inode->i_sb, __func__, + "read of block failed\n"); + break; + } } - } - UFSD(" change from %llu to %llu, pos %u\n", - (unsigned long long)(pos + oldb), - (unsigned long long)(pos + newb), pos); - - bh->b_blocknr = newb + pos; - unmap_underlying_metadata(bh->b_bdev, - bh->b_blocknr); - mark_buffer_dirty(bh); - ++j; - bh = bh->b_this_page; - } while (bh != head); + UFSD(" change from %llu to %llu, pos %u\n", + (unsigned long long)(pos + oldb), + (unsigned long long)(pos + newb), pos); + + bh->b_blocknr = newb + pos; + unmap_underlying_metadata(bh->b_bdev, + bh->b_blocknr); + mark_buffer_dirty(bh); + ++j; + bh = bh->b_this_page; + } while (bh != head); + } if (likely(cur_index != index)) ufs_put_locked_page(page); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html