Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 874d0d26 authored by Chris Mason's avatar Chris Mason
Browse files

Merge branch 'for-chris' of...

Merge branch 'for-chris' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-work into for-linus
parents 507903b8 13c5a93e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2576,6 +2576,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
			      struct inode *inode, u64 start, u64 end);
int btrfs_release_file(struct inode *inode, struct file *file);
void btrfs_drop_pages(struct page **pages, size_t num_pages);
int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
		      struct page **pages, size_t num_pages,
		      loff_t pos, size_t write_bytes,
		      struct extent_state **cached);

/* tree-defrag.c */
int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
+1 −1
Original line number Diff line number Diff line
@@ -3136,7 +3136,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
		btrfs_destroy_pinned_extent(root,
					    root->fs_info->pinned_extents);

		t->use_count = 0;
		atomic_set(&t->use_count, 0);
		list_del_init(&t->list);
		memset(t, 0, sizeof(*t));
		kmem_cache_free(btrfs_transaction_cachep, t);
+9 −12
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
/*
 * unlocks pages after btrfs_file_write is done with them
 */
static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
void btrfs_drop_pages(struct page **pages, size_t num_pages)
{
	size_t i;
	for (i = 0; i < num_pages; i++) {
@@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
 * this also makes the decision about creating an inline extent vs
 * doing real data extents, marking pages dirty and delalloc as required.
 */
static noinline int dirty_and_release_pages(struct btrfs_root *root,
					    struct file *file,
					    struct page **pages,
					    size_t num_pages,
					    loff_t pos,
					    size_t write_bytes)
int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
		      struct page **pages, size_t num_pages,
		      loff_t pos, size_t write_bytes,
		      struct extent_state **cached)
{
	int err = 0;
	int i;
	struct inode *inode = fdentry(file)->d_inode;
	u64 num_bytes;
	u64 start_pos;
	u64 end_of_last_block;
@@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct btrfs_root *root,

	end_of_last_block = start_pos + num_bytes - 1;
	err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
					NULL);
					cached);
	if (err)
		return err;

@@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
		}

		if (copied > 0) {
			ret = dirty_and_release_pages(root, file, pages,
						      dirty_pages, pos,
						      copied);
			ret = btrfs_dirty_pages(root, inode, pages,
						dirty_pages, pos, copied,
						NULL);
			if (ret) {
				btrfs_delalloc_release_space(inode,
					dirty_pages << PAGE_CACHE_SHIFT);
+55 −62
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
	struct inode *inode;
	struct rb_node *node;
	struct list_head *pos, *n;
	struct page **pages;
	struct page *page;
	struct extent_state *cached_state = NULL;
	struct btrfs_free_cluster *cluster = NULL;
@@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root,
	u64 start, end, len;
	u64 bytes = 0;
	u32 *crc, *checksums;
	pgoff_t index = 0, last_index = 0;
	unsigned long first_page_offset;
	int num_checksums;
	int index = 0, num_pages = 0;
	int entries = 0;
	int bitmaps = 0;
	int ret = 0;
	bool next_page = false;
	bool out_of_space = false;

	root = root->fs_info->tree_root;

@@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root,
		return 0;
	}

	last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
		PAGE_CACHE_SHIFT;
	filemap_write_and_wait(inode->i_mapping);
	btrfs_wait_ordered_range(inode, inode->i_size &
				 ~(root->sectorsize - 1), (u64)-1);

	/* We need a checksum per page. */
	num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE;
	crc = checksums  = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS);
	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
	if (!crc) {
		iput(inode);
		return 0;
	}

	pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
	if (!pages) {
		kfree(crc);
		iput(inode);
		return 0;
	}

	/* Since the first page has all of our checksums and our generation we
	 * need to calculate the offset into the page that we can start writing
	 * our entries.
	 */
	first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);

	/* Get the cluster for this block_group if it exists */
	if (!list_empty(&block_group->cluster_list))
@@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root,
	 * after find_get_page at this point.  Just putting this here so people
	 * know and don't freak out.
	 */
	while (index <= last_index) {
	while (index < num_pages) {
		page = grab_cache_page(inode->i_mapping, index);
		if (!page) {
			pgoff_t i = 0;
			int i;

			while (i < index) {
				page = find_get_page(inode->i_mapping, i);
				unlock_page(page);
				page_cache_release(page);
				page_cache_release(page);
				i++;
			for (i = 0; i < num_pages; i++) {
				unlock_page(pages[i]);
				page_cache_release(pages[i]);
			}
			goto out_free;
		}
		pages[index] = page;
		index++;
	}

@@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
			offset = start_offset;
		}

		page = find_get_page(inode->i_mapping, index);
		if (index >= num_pages) {
			out_of_space = true;
			break;
		}

		page = pages[index];

		addr = kmap(page);
		entry = addr + start_offset;
@@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,

		bytes += PAGE_CACHE_SIZE;

		ClearPageChecked(page);
		set_page_extent_mapped(page);
		SetPageUptodate(page);
		set_page_dirty(page);

		/*
		 * We need to release our reference we got for grab_cache_page,
		 * except for the first page which will hold our checksums, we
		 * do that below.
		 */
		if (index != 0) {
			unlock_page(page);
			page_cache_release(page);
		}

		page_cache_release(page);

		index++;
	} while (node || next_page);

@@ -734,6 +728,10 @@ int btrfs_write_out_cache(struct btrfs_root *root,
		struct btrfs_free_space *entry =
			list_entry(pos, struct btrfs_free_space, list);

		if (index >= num_pages) {
			out_of_space = true;
			break;
		}
		page = find_get_page(inode->i_mapping, index);

		addr = kmap(page);
@@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root,
		crc++;
		bytes += PAGE_CACHE_SIZE;

		ClearPageChecked(page);
		set_page_extent_mapped(page);
		SetPageUptodate(page);
		set_page_dirty(page);
		unlock_page(page);
		page_cache_release(page);
		page_cache_release(page);
		list_del_init(&entry->list);
		index++;
	}

	if (out_of_space) {
		btrfs_drop_pages(pages, num_pages);
		unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
				     i_size_read(inode) - 1, &cached_state,
				     GFP_NOFS);
		ret = 0;
		goto out_free;
	}

	/* Zero out the rest of the pages just to make sure */
	while (index <= last_index) {
	while (index < num_pages) {
		void *addr;

		page = find_get_page(inode->i_mapping, index);

		page = pages[index];
		addr = kmap(page);
		memset(addr, 0, PAGE_CACHE_SIZE);
		kunmap(page);
		ClearPageChecked(page);
		set_page_extent_mapped(page);
		SetPageUptodate(page);
		set_page_dirty(page);
		unlock_page(page);
		page_cache_release(page);
		page_cache_release(page);
		bytes += PAGE_CACHE_SIZE;
		index++;
	}

	btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state);

	/* Write the checksums and trans id to the first page */
	{
		void *addr;
		u64 *gen;

		page = find_get_page(inode->i_mapping, 0);
		page = pages[0];

		addr = kmap(page);
		memcpy(addr, checksums, sizeof(u32) * num_checksums);
		gen = addr + (sizeof(u32) * num_checksums);
		memcpy(addr, checksums, sizeof(u32) * num_pages);
		gen = addr + (sizeof(u32) * num_pages);
		*gen = trans->transid;
		kunmap(page);
		ClearPageChecked(page);
		set_page_extent_mapped(page);
		SetPageUptodate(page);
		set_page_dirty(page);
		unlock_page(page);
		page_cache_release(page);
		page_cache_release(page);
	}
	BTRFS_I(inode)->generation = trans->transid;

	ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0,
					    bytes, &cached_state);
	btrfs_drop_pages(pages, num_pages);
	unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
			     i_size_read(inode) - 1, &cached_state, GFP_NOFS);

	if (ret) {
		ret = 0;
		goto out_free;
	}

	BTRFS_I(inode)->generation = trans->transid;

	filemap_write_and_wait(inode->i_mapping);

	key.objectid = BTRFS_FREE_SPACE_OBJECTID;
@@ -853,6 +845,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
		BTRFS_I(inode)->generation = 0;
	}
	kfree(checksums);
	kfree(pages);
	btrfs_update_inode(trans, root, inode);
	iput(inode);
	return ret;
+82 −25
Original line number Diff line number Diff line
@@ -1769,9 +1769,12 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
	add_pending_csums(trans, inode, ordered_extent->file_offset,
			  &ordered_extent->list);

	btrfs_ordered_update_i_size(inode, 0, ordered_extent);
	ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
	if (!ret) {
		ret = btrfs_update_inode(trans, root, inode);
		BUG_ON(ret);
	}
	ret = 0;
out:
	if (nolock) {
		if (trans)
@@ -2589,6 +2592,13 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
			    struct btrfs_inode_item *item,
			    struct inode *inode)
{
	if (!leaf->map_token)
		map_private_extent_buffer(leaf, (unsigned long)item,
					  sizeof(struct btrfs_inode_item),
					  &leaf->map_token, &leaf->kaddr,
					  &leaf->map_start, &leaf->map_len,
					  KM_USER1);

	btrfs_set_inode_uid(leaf, item, inode->i_uid);
	btrfs_set_inode_gid(leaf, item, inode->i_gid);
	btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size);
@@ -2617,6 +2627,11 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
	btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
	btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
	btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group);

	if (leaf->map_token) {
		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
		leaf->map_token = NULL;
	}
}

/*
@@ -5433,17 +5448,30 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
}

static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
						  struct extent_map *em,
						  u64 start, u64 len)
{
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_trans_handle *trans;
	struct extent_map *em;
	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
	struct btrfs_key ins;
	u64 alloc_hint;
	int ret;
	bool insert = false;

	/*
	 * Ok if the extent map we looked up is a hole and is for the exact
	 * range we want, there is no reason to allocate a new one, however if
	 * it is not right then we need to free this one and drop the cache for
	 * our range.
	 */
	if (em->block_start != EXTENT_MAP_HOLE || em->start != start ||
	    em->len != len) {
		free_extent_map(em);
		em = NULL;
		insert = true;
		btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
	}

	trans = btrfs_join_transaction(root, 0);
	if (IS_ERR(trans))
@@ -5459,11 +5487,13 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
		goto out;
	}

	if (!em) {
		em = alloc_extent_map(GFP_NOFS);
		if (!em) {
			em = ERR_PTR(-ENOMEM);
			goto out;
		}
	}

	em->start = start;
	em->orig_start = em->start;
@@ -5472,9 +5502,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
	em->block_start = ins.objectid;
	em->block_len = ins.offset;
	em->bdev = root->fs_info->fs_devices->latest_bdev;

	/*
	 * We need to do this because if we're using the original em we searched
	 * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that.
	 */
	em->flags = 0;
	set_bit(EXTENT_FLAG_PINNED, &em->flags);

	while (1) {
	while (insert) {
		write_lock(&em_tree->lock);
		ret = add_extent_mapping(em_tree, em);
		write_unlock(&em_tree->lock);
@@ -5692,8 +5728,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
	 * it above
	 */
	len = bh_result->b_size;
	free_extent_map(em);
	em = btrfs_new_extent_direct(inode, start, len);
	em = btrfs_new_extent_direct(inode, em, start, len);
	if (IS_ERR(em))
		return PTR_ERR(em);
	len = min(len, em->len - (start - em->start));
@@ -5856,8 +5891,10 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
	}

	add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
	btrfs_ordered_update_i_size(inode, 0, ordered);
	ret = btrfs_ordered_update_i_size(inode, 0, ordered);
	if (!ret)
		btrfs_update_inode(trans, root, inode);
	ret = 0;
out_unlock:
	unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset,
			     ordered->file_offset + ordered->len - 1,
@@ -5943,7 +5980,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,

static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
					 int rw, u64 file_offset, int skip_sum,
					 u32 *csums)
					 u32 *csums, int async_submit)
{
	int write = rw & REQ_WRITE;
	struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -5954,13 +5991,24 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
	if (ret)
		goto err;

	if (write && !skip_sum) {
	if (skip_sum)
		goto map;

	if (write && async_submit) {
		ret = btrfs_wq_submit_bio(root->fs_info,
				   inode, rw, bio, 0, 0,
				   file_offset,
				   __btrfs_submit_bio_start_direct_io,
				   __btrfs_submit_bio_done);
		goto err;
	} else if (write) {
		/*
		 * If we aren't doing async submit, calculate the csum of the
		 * bio now.
		 */
		ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1);
		if (ret)
			goto err;
	} else if (!skip_sum) {
		ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
					  file_offset, csums);
@@ -5968,7 +6016,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
			goto err;
	}

	ret = btrfs_map_bio(root, rw, bio, 0, 1);
map:
	ret = btrfs_map_bio(root, rw, bio, 0, async_submit);
err:
	bio_put(bio);
	return ret;
@@ -5990,15 +6039,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
	int nr_pages = 0;
	u32 *csums = dip->csums;
	int ret = 0;
	int async_submit = 0;
	int write = rw & REQ_WRITE;

	bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
	if (!bio)
		return -ENOMEM;
	bio->bi_private = dip;
	bio->bi_end_io = btrfs_end_dio_bio;
	atomic_inc(&dip->pending_bios);

	map_length = orig_bio->bi_size;
	ret = btrfs_map_block(map_tree, READ, start_sector << 9,
			      &map_length, NULL, 0);
@@ -6007,6 +6050,19 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
		return -EIO;
	}

	if (map_length >= orig_bio->bi_size) {
		bio = orig_bio;
		goto submit;
	}

	async_submit = 1;
	bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
	if (!bio)
		return -ENOMEM;
	bio->bi_private = dip;
	bio->bi_end_io = btrfs_end_dio_bio;
	atomic_inc(&dip->pending_bios);

	while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
		if (unlikely(map_length < submit_len + bvec->bv_len ||
		    bio_add_page(bio, bvec->bv_page, bvec->bv_len,
@@ -6020,7 +6076,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
			atomic_inc(&dip->pending_bios);
			ret = __btrfs_submit_dio_bio(bio, inode, rw,
						     file_offset, skip_sum,
						     csums);
						     csums, async_submit);
			if (ret) {
				bio_put(bio);
				atomic_dec(&dip->pending_bios);
@@ -6057,8 +6113,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
		}
	}

submit:
	ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
				     csums);
				     csums, async_submit);
	if (!ret)
		return 0;

Loading