|
@@ -244,62 +244,87 @@ failed:
|
|
|
* We can come here from ufs_writepage or ufs_prepare_write,
|
|
|
* locked_page is argument of these functions, so we already lock it.
|
|
|
*/
|
|
|
-static void ufs_change_blocknr(struct inode *inode, unsigned int beg,
|
|
|
- unsigned int count, unsigned int oldb,
|
|
|
- unsigned int newb, struct page *locked_page)
|
|
|
+static void ufs_change_blocknr(struct inode *inode, sector_t beg,
|
|
|
+ unsigned int count, sector_t oldb,
|
|
|
+ sector_t newb, struct page *locked_page)
|
|
|
{
|
|
|
- const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1;
|
|
|
+ const unsigned blks_per_page =
|
|
|
+ 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
|
|
+ const unsigned mask = blks_per_page - 1;
|
|
|
struct address_space * const mapping = inode->i_mapping;
|
|
|
- pgoff_t index, cur_index;
|
|
|
- unsigned end, pos, j;
|
|
|
+ pgoff_t index, cur_index, last_index;
|
|
|
+ unsigned pos, j, lblock;
|
|
|
+ sector_t end, i;
|
|
|
struct page *page;
|
|
|
struct buffer_head *head, *bh;
|
|
|
|
|
|
- UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
|
|
|
- inode->i_ino, count, oldb, newb);
|
|
|
+ UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n",
|
|
|
+ inode->i_ino, count,
|
|
|
+ (unsigned long long)oldb, (unsigned long long)newb);
|
|
|
|
|
|
BUG_ON(!locked_page);
|
|
|
BUG_ON(!PageLocked(locked_page));
|
|
|
|
|
|
cur_index = locked_page->index;
|
|
|
-
|
|
|
- for (end = count + beg; beg < end; beg = (beg | mask) + 1) {
|
|
|
- index = beg >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
|
|
+ end = count + beg;
|
|
|
+ last_index = end >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
|
|
+ for (i = beg; i < end; i = (i | mask) + 1) {
|
|
|
+ index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
|
|
|
|
|
if (likely(cur_index != index)) {
|
|
|
page = ufs_get_locked_page(mapping, index);
|
|
|
- if (!page || IS_ERR(page)) /* it was truncated or EIO */
|
|
|
+ if (!page)/* it was truncated */
|
|
|
+ continue;
|
|
|
+ if (IS_ERR(page)) {/* or EIO */
|
|
|
+ ufs_error(inode->i_sb, __FUNCTION__,
|
|
|
+ "read of page %llu failed\n",
|
|
|
+ (unsigned long long)index);
|
|
|
continue;
|
|
|
+ }
|
|
|
} else
|
|
|
page = locked_page;
|
|
|
|
|
|
head = page_buffers(page);
|
|
|
bh = head;
|
|
|
- pos = beg & mask;
|
|
|
+ pos = i & mask;
|
|
|
for (j = 0; j < pos; ++j)
|
|
|
bh = bh->b_this_page;
|
|
|
- j = 0;
|
|
|
+
|
|
|
+
|
|
|
+ if (unlikely(index == last_index))
|
|
|
+ lblock = end & mask;
|
|
|
+ else
|
|
|
+ lblock = blks_per_page;
|
|
|
+
|
|
|
do {
|
|
|
- if (buffer_mapped(bh)) {
|
|
|
- pos = bh->b_blocknr - oldb;
|
|
|
- if (pos < count) {
|
|
|
- UFSD(" change from %llu to %llu\n",
|
|
|
- (unsigned long long)pos + oldb,
|
|
|
- (unsigned long long)pos + newb);
|
|
|
- bh->b_blocknr = newb + pos;
|
|
|
- unmap_underlying_metadata(bh->b_bdev,
|
|
|
- bh->b_blocknr);
|
|
|
- mark_buffer_dirty(bh);
|
|
|
- ++j;
|
|
|
+ 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, __FUNCTION__,
|
|
|
+ "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);
|
|
|
|
|
|
- if (j)
|
|
|
- set_page_dirty(page);
|
|
|
-
|
|
|
if (likely(cur_index != index))
|
|
|
ufs_put_locked_page(page);
|
|
|
}
|