+/*
+ * Modify inode page cache in such way:
+ * have - blocks with b_blocknr equal to oldb...oldb+count-1
+ * get - blocks with b_blocknr equal to newb...newb+count-1
+ * also we suppose that oldb...oldb+count-1 blocks
+ * situated at the end of file.
+ *
+ * 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, sector_t beg,
+ unsigned int count, sector_t oldb,
+ sector_t newb, struct page *locked_page)
+{
+ 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, 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 %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;
+ 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)/* it was truncated */
+ continue;
+ if (IS_ERR(page)) {/* or EIO */
+ ufs_error(inode->i_sb, __func__,
+ "read of page %llu failed\n",
+ (unsigned long long)index);
+ continue;
+ }
+ } 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 (!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;
+ }
+ }