spin_lock(&em_tree->lock);
em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
spin_unlock(&em_tree->lock);
- if (!em)
+ if (!em) {
+ __unplug_io_fn(bdi, page);
return;
+ }
+ if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
+ free_extent_map(em);
+ __unplug_io_fn(bdi, page);
+ return;
+ }
offset = offset - em->start;
btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree,
em->block_start + offset, page);
cur + iosize - 1);
}
if (!ret) {
- unsigned long nr = (last_byte >> PAGE_CACHE_SHIFT) + 1;
- nr -= page->index;
+ unsigned long pnr = (last_byte >> PAGE_CACHE_SHIFT) + 1;
+ pnr -= page->index;
ret = submit_extent_page(READ, tree, page,
sector, iosize, page_offset,
- bdev, bio, nr,
+ bdev, bio, pnr,
end_bio_extent_readpage, mirror_num);
+ nr++;
}
if (ret)
SetPageError(page);
cur = cur + iosize;
page_offset += iosize;
- nr++;
}
if (!nr) {
if (!PageError(page))
btrfs_test_flag(inode, NODATASUM))
return 0;
+ /*
+ * It is possible there is an ordered extent that has
+ * not yet finished for this range in the file. If so,
+ * that extent will have a csum cached, and it will insert
+ * the sum after all the blocks in the extent are fully
+ * on disk. So, look for an ordered extent and use the
+ * sum if found. We have to do this before looking in the
+ * btree because csum items are pre-inserted based on
+ * the file size. btrfs_lookup_csum might find an item
+ * that still hasn't been fully filled.
+ */
+ ret = btrfs_find_ordered_sum(inode, start, &csum);
+ if (ret == 0)
+ goto found;
+
+ ret = 0;
path = btrfs_alloc_path();
- mutex_lock(&BTRFS_I(inode)->csum_mutex);
item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0);
if (IS_ERR(item)) {
- /*
- * It is possible there is an ordered extent that has
- * not yet finished for this range in the file. If so,
- * that extent will have a csum cached, and it will insert
- * the sum after all the blocks in the extent are fully
- * on disk. So, look for an ordered extent and use the
- * sum if found.
- */
- ret = btrfs_find_ordered_sum(inode, start, &csum);
- if (ret == 0)
- goto found;
-
ret = PTR_ERR(item);
/* a csum that isn't present is a preallocated region. */
if (ret == -ENOENT || ret == -EFBIG)
found:
set_state_private(io_tree, start, csum);
out:
- mutex_unlock(&BTRFS_I(inode)->csum_mutex);
if (path)
btrfs_free_path(path);
return ret;
}
if (!PageUptodate(page)) {
ret = -EIO;
- goto out;
+ goto out_unlock;
}
}
wait_on_page_writeback(page);
set_page_dirty(page);
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
+out_unlock:
unlock_page(page);
page_cache_release(page);
out: