Beispiel #1
0
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;
                }
            }

            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);
    }
    UFSD("EXIT\n");
}
Beispiel #2
0
static int ufs_alloc_lastblock(struct inode *inode)
{
	int err = 0;
	struct super_block *sb = inode->i_sb;
	struct address_space *mapping = inode->i_mapping;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	unsigned i, end;
	sector_t lastfrag;
	struct page *lastpage;
	struct buffer_head *bh;
	u64 phys64;

	lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;

	if (!lastfrag)
		goto out;

	lastfrag--;

	lastpage = ufs_get_locked_page(mapping, lastfrag >>
				       (PAGE_CACHE_SHIFT - inode->i_blkbits));
       if (IS_ERR(lastpage)) {
               err = -EIO;
               goto out;
       }

       end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1);
       bh = page_buffers(lastpage);
       for (i = 0; i < end; ++i)
               bh = bh->b_this_page;


       err = ufs_getfrag_block(inode, lastfrag, bh, 1);

       if (unlikely(err))
	       goto out_unlock;

       if (buffer_new(bh)) {
	       clear_buffer_new(bh);
	       unmap_underlying_metadata(bh->b_bdev,
					 bh->b_blocknr);
	       /*
		* we do not zeroize fragment, because of
		* if it maped to hole, it already contains zeroes
		*/
	       set_buffer_uptodate(bh);
	       mark_buffer_dirty(bh);
	       set_page_dirty(lastpage);
       }

       if (lastfrag >= UFS_IND_FRAGMENT) {
	       end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
	       phys64 = bh->b_blocknr + 1;
	       for (i = 0; i < end; ++i) {
		       bh = sb_getblk(sb, i + phys64);
		       lock_buffer(bh);
		       memset(bh->b_data, 0, sb->s_blocksize);
		       set_buffer_uptodate(bh);
		       mark_buffer_dirty(bh);
		       unlock_buffer(bh);
		       sync_dirty_buffer(bh);
		       brelse(bh);
	       }
       }
out_unlock:
       ufs_put_locked_page(lastpage);
out:
       return err;
}
Beispiel #3
0
/*
 * 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, unsigned int beg,
			       unsigned int count, unsigned int oldb,
			       unsigned int newb, struct page *locked_page)
{
	const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1;
	struct address_space * const mapping = inode->i_mapping;
	pgoff_t index, cur_index;
	unsigned end, pos, j;
	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);

	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);

		if (likely(cur_index != index)) {
			page = ufs_get_locked_page(mapping, index);
			if (!page || IS_ERR(page)) /* it was truncated or EIO */
				continue;
		} else
			page = locked_page;

		head = page_buffers(page);
		bh = head;
		pos = beg & mask;
		for (j = 0; j < pos; ++j)
			bh = bh->b_this_page;
		j = 0;
		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;
				}
			}

			bh = bh->b_this_page;
		} while (bh != head);

		if (j)
			set_page_dirty(page);

		if (likely(cur_index != index))
			ufs_put_locked_page(page);
 	}
	UFSD("EXIT\n");
}