mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (25 commits) btrfs: fix uninitialized variable warning btrfs: add helper for fs_info->closing Btrfs: add mount -o inode_cache btrfs: scrub: add explicit plugging btrfs: use btrfs_ino to access inode number Btrfs: don't save the inode cache if we are deleting this root btrfs: false BUG_ON when degraded Btrfs: don't save the inode cache in non-FS roots Btrfs: make sure we don't overflow the free space cache crc page Btrfs: fix uninit variable in the delayed inode code btrfs: scrub: don't reuse bios and pages Btrfs: leave spinning on lookup and map the leaf Btrfs: check for duplicate entries in the free space cache Btrfs: don't try to allocate from a block group that doesn't have enough space Btrfs: don't always do readahead Btrfs: try not to sleep as much when doing slow caching Btrfs: kill BTRFS_I(inode)->block_group Btrfs: don't look at the extent buffer level 3 times in a row Btrfs: map the node block when looking for readahead targets Btrfs: set range_start to the right start in count_range_bits ...
This commit is contained in:
		
						commit
						e6ece70732
					
				
					 19 changed files with 635 additions and 468 deletions
				
			
		|  | @ -121,9 +121,6 @@ struct btrfs_inode { | |||
| 	 */ | ||||
| 	u64 index_cnt; | ||||
| 
 | ||||
| 	/* the start of block group preferred for allocations. */ | ||||
| 	u64 block_group; | ||||
| 
 | ||||
| 	/* the fsync log has some corner cases that mean we have to check
 | ||||
| 	 * directories to see if any unlinks have been done before | ||||
| 	 * the directory was logged.  See tree-log.c for all the | ||||
|  |  | |||
|  | @ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void) | |||
| { | ||||
| 	struct btrfs_path *path; | ||||
| 	path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); | ||||
| 	if (path) | ||||
| 		path->reada = 1; | ||||
| 	return path; | ||||
| } | ||||
| 
 | ||||
|  | @ -1224,6 +1222,7 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 	u64 search; | ||||
| 	u64 target; | ||||
| 	u64 nread = 0; | ||||
| 	u64 gen; | ||||
| 	int direction = path->reada; | ||||
| 	struct extent_buffer *eb; | ||||
| 	u32 nr; | ||||
|  | @ -1251,6 +1250,15 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 	nritems = btrfs_header_nritems(node); | ||||
| 	nr = slot; | ||||
| 	while (1) { | ||||
| 		if (!node->map_token) { | ||||
| 			unsigned long offset = btrfs_node_key_ptr_offset(nr); | ||||
| 			map_private_extent_buffer(node, offset, | ||||
| 						  sizeof(struct btrfs_key_ptr), | ||||
| 						  &node->map_token, | ||||
| 						  &node->kaddr, | ||||
| 						  &node->map_start, | ||||
| 						  &node->map_len, KM_USER1); | ||||
| 		} | ||||
| 		if (direction < 0) { | ||||
| 			if (nr == 0) | ||||
| 				break; | ||||
|  | @ -1268,14 +1276,23 @@ static void reada_for_search(struct btrfs_root *root, | |||
| 		search = btrfs_node_blockptr(node, nr); | ||||
| 		if ((search <= target && target - search <= 65536) || | ||||
| 		    (search > target && search - target <= 65536)) { | ||||
| 			readahead_tree_block(root, search, blocksize, | ||||
| 				     btrfs_node_ptr_generation(node, nr)); | ||||
| 			gen = btrfs_node_ptr_generation(node, nr); | ||||
| 			if (node->map_token) { | ||||
| 				unmap_extent_buffer(node, node->map_token, | ||||
| 						    KM_USER1); | ||||
| 				node->map_token = NULL; | ||||
| 			} | ||||
| 			readahead_tree_block(root, search, blocksize, gen); | ||||
| 			nread += blocksize; | ||||
| 		} | ||||
| 		nscan++; | ||||
| 		if ((nread > 65536 || nscan > 32)) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (node->map_token) { | ||||
| 		unmap_extent_buffer(node, node->map_token, KM_USER1); | ||||
| 		node->map_token = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -1648,9 +1665,6 @@ again: | |||
| 		} | ||||
| cow_done: | ||||
| 		BUG_ON(!cow && ins_len); | ||||
| 		if (level != btrfs_header_level(b)) | ||||
| 			WARN_ON(1); | ||||
| 		level = btrfs_header_level(b); | ||||
| 
 | ||||
| 		p->nodes[level] = b; | ||||
| 		if (!p->skip_locking) | ||||
|  |  | |||
|  | @ -930,7 +930,6 @@ struct btrfs_fs_info { | |||
| 	 * is required instead of the faster short fsync log commits | ||||
| 	 */ | ||||
| 	u64 last_trans_log_full_commit; | ||||
| 	u64 open_ioctl_trans; | ||||
| 	unsigned long mount_opt:20; | ||||
| 	unsigned long compress_type:4; | ||||
| 	u64 max_inline; | ||||
|  | @ -947,7 +946,6 @@ struct btrfs_fs_info { | |||
| 	struct super_block *sb; | ||||
| 	struct inode *btree_inode; | ||||
| 	struct backing_dev_info bdi; | ||||
| 	struct mutex trans_mutex; | ||||
| 	struct mutex tree_log_mutex; | ||||
| 	struct mutex transaction_kthread_mutex; | ||||
| 	struct mutex cleaner_mutex; | ||||
|  | @ -968,6 +966,7 @@ struct btrfs_fs_info { | |||
| 	struct rw_semaphore subvol_sem; | ||||
| 	struct srcu_struct subvol_srcu; | ||||
| 
 | ||||
| 	spinlock_t trans_lock; | ||||
| 	struct list_head trans_list; | ||||
| 	struct list_head hashers; | ||||
| 	struct list_head dead_roots; | ||||
|  | @ -980,6 +979,7 @@ struct btrfs_fs_info { | |||
| 	atomic_t async_submit_draining; | ||||
| 	atomic_t nr_async_bios; | ||||
| 	atomic_t async_delalloc_pages; | ||||
| 	atomic_t open_ioctl_trans; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * this is used by the balancing code to wait for all the pending | ||||
|  | @ -1044,6 +1044,7 @@ struct btrfs_fs_info { | |||
| 	int closing; | ||||
| 	int log_root_recovering; | ||||
| 	int enospc_unlink; | ||||
| 	int trans_no_join; | ||||
| 
 | ||||
| 	u64 total_pinned; | ||||
| 
 | ||||
|  | @ -1065,7 +1066,6 @@ struct btrfs_fs_info { | |||
| 	struct reloc_control *reloc_ctl; | ||||
| 
 | ||||
| 	spinlock_t delalloc_lock; | ||||
| 	spinlock_t new_trans_lock; | ||||
| 	u64 delalloc_bytes; | ||||
| 
 | ||||
| 	/* data_alloc_cluster is only used in ssd mode */ | ||||
|  | @ -1340,6 +1340,7 @@ struct btrfs_ioctl_defrag_range_args { | |||
| #define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14) | ||||
| #define BTRFS_MOUNT_ENOSPC_DEBUG	 (1 << 15) | ||||
| #define BTRFS_MOUNT_AUTO_DEFRAG		(1 << 16) | ||||
| #define BTRFS_MOUNT_INODE_MAP_CACHE	(1 << 17) | ||||
| 
 | ||||
| #define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt) | ||||
| #define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt) | ||||
|  | @ -2238,6 +2239,9 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, | |||
| void btrfs_block_rsv_release(struct btrfs_root *root, | ||||
| 			     struct btrfs_block_rsv *block_rsv, | ||||
| 			     u64 num_bytes); | ||||
| int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans, | ||||
| 				    struct btrfs_root *root, | ||||
| 				    struct btrfs_block_rsv *rsv); | ||||
| int btrfs_set_block_group_ro(struct btrfs_root *root, | ||||
| 			     struct btrfs_block_group_cache *cache); | ||||
| int btrfs_set_block_group_rw(struct btrfs_root *root, | ||||
|  | @ -2350,6 +2354,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | |||
| 			struct btrfs_root *root, | ||||
| 			struct extent_buffer *node, | ||||
| 			struct extent_buffer *parent); | ||||
| static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Get synced with close_ctree() | ||||
| 	 */ | ||||
| 	smp_mb(); | ||||
| 	return fs_info->closing; | ||||
| } | ||||
| 
 | ||||
| /* root-item.c */ | ||||
| int btrfs_find_root_ref(struct btrfs_root *tree_root, | ||||
| 			struct btrfs_path *path, | ||||
|  | @ -2512,8 +2525,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, | |||
| int btrfs_writepages(struct address_space *mapping, | ||||
| 		     struct writeback_control *wbc); | ||||
| int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | ||||
| 			     struct btrfs_root *new_root, | ||||
| 			     u64 new_dirid, u64 alloc_hint); | ||||
| 			     struct btrfs_root *new_root, u64 new_dirid); | ||||
| int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | ||||
| 			 size_t size, struct bio *bio, unsigned long bio_flags); | ||||
| 
 | ||||
|  |  | |||
|  | @ -678,6 +678,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans, | |||
| 	INIT_LIST_HEAD(&head); | ||||
| 
 | ||||
| 	next = item; | ||||
| 	nitems = 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * count the number of the continuous items that we can insert in batch | ||||
|  | @ -1129,7 +1130,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 	delayed_node = async_node->delayed_node; | ||||
| 	root = delayed_node->root; | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 0); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		goto free_path; | ||||
| 
 | ||||
|  | @ -1572,8 +1573,7 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, | |||
| 	btrfs_set_stack_inode_transid(inode_item, trans->transid); | ||||
| 	btrfs_set_stack_inode_rdev(inode_item, inode->i_rdev); | ||||
| 	btrfs_set_stack_inode_flags(inode_item, BTRFS_I(inode)->flags); | ||||
| 	btrfs_set_stack_inode_block_group(inode_item, | ||||
| 					  BTRFS_I(inode)->block_group); | ||||
| 	btrfs_set_stack_inode_block_group(inode_item, 0); | ||||
| 
 | ||||
| 	btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item), | ||||
| 				     inode->i_atime.tv_sec); | ||||
|  | @ -1595,7 +1595,7 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | |||
| 			       struct btrfs_root *root, struct inode *inode) | ||||
| { | ||||
| 	struct btrfs_delayed_node *delayed_node; | ||||
| 	int ret; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	delayed_node = btrfs_get_or_create_delayed_node(inode); | ||||
| 	if (IS_ERR(delayed_node)) | ||||
|  |  | |||
|  | @ -1505,24 +1505,24 @@ static int transaction_kthread(void *arg) | |||
| 		vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); | ||||
| 		mutex_lock(&root->fs_info->transaction_kthread_mutex); | ||||
| 
 | ||||
| 		spin_lock(&root->fs_info->new_trans_lock); | ||||
| 		spin_lock(&root->fs_info->trans_lock); | ||||
| 		cur = root->fs_info->running_transaction; | ||||
| 		if (!cur) { | ||||
| 			spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 			spin_unlock(&root->fs_info->trans_lock); | ||||
| 			goto sleep; | ||||
| 		} | ||||
| 
 | ||||
| 		now = get_seconds(); | ||||
| 		if (!cur->blocked && | ||||
| 		    (now < cur->start_time || now - cur->start_time < 30)) { | ||||
| 			spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 			spin_unlock(&root->fs_info->trans_lock); | ||||
| 			delay = HZ * 5; | ||||
| 			goto sleep; | ||||
| 		} | ||||
| 		transid = cur->transid; | ||||
| 		spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		BUG_ON(IS_ERR(trans)); | ||||
| 		if (transid == trans->transid) { | ||||
| 			ret = btrfs_commit_transaction(trans, root); | ||||
|  | @ -1613,7 +1613,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 	INIT_LIST_HEAD(&fs_info->ordered_operations); | ||||
| 	INIT_LIST_HEAD(&fs_info->caching_block_groups); | ||||
| 	spin_lock_init(&fs_info->delalloc_lock); | ||||
| 	spin_lock_init(&fs_info->new_trans_lock); | ||||
| 	spin_lock_init(&fs_info->trans_lock); | ||||
| 	spin_lock_init(&fs_info->ref_cache_lock); | ||||
| 	spin_lock_init(&fs_info->fs_roots_radix_lock); | ||||
| 	spin_lock_init(&fs_info->delayed_iput_lock); | ||||
|  | @ -1645,6 +1645,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 	fs_info->max_inline = 8192 * 1024; | ||||
| 	fs_info->metadata_ratio = 0; | ||||
| 	fs_info->defrag_inodes = RB_ROOT; | ||||
| 	fs_info->trans_no_join = 0; | ||||
| 
 | ||||
| 	fs_info->thread_pool_size = min_t(unsigned long, | ||||
| 					  num_online_cpus() + 2, 8); | ||||
|  | @ -1709,7 +1710,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 	fs_info->do_barriers = 1; | ||||
| 
 | ||||
| 
 | ||||
| 	mutex_init(&fs_info->trans_mutex); | ||||
| 	mutex_init(&fs_info->ordered_operations_mutex); | ||||
| 	mutex_init(&fs_info->tree_log_mutex); | ||||
| 	mutex_init(&fs_info->chunk_mutex); | ||||
|  | @ -2479,13 +2479,13 @@ int btrfs_commit_super(struct btrfs_root *root) | |||
| 	down_write(&root->fs_info->cleanup_work_sem); | ||||
| 	up_write(&root->fs_info->cleanup_work_sem); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 	ret = btrfs_commit_transaction(trans, root); | ||||
| 	BUG_ON(ret); | ||||
| 	/* run commit again to drop the original snapshot */ | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 	btrfs_commit_transaction(trans, root); | ||||
|  | @ -3024,10 +3024,13 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
| 
 | ||||
| 	WARN_ON(1); | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	mutex_lock(&root->fs_info->transaction_kthread_mutex); | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	list_splice_init(&root->fs_info->trans_list, &list); | ||||
| 	root->fs_info->trans_no_join = 1; | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	while (!list_empty(&list)) { | ||||
| 		t = list_entry(list.next, struct btrfs_transaction, list); | ||||
| 		if (!t) | ||||
|  | @ -3052,23 +3055,18 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
| 		t->blocked = 0; | ||||
| 		if (waitqueue_active(&root->fs_info->transaction_wait)) | ||||
| 			wake_up(&root->fs_info->transaction_wait); | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		t->commit_done = 1; | ||||
| 		if (waitqueue_active(&t->commit_wait)) | ||||
| 			wake_up(&t->commit_wait); | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 		btrfs_destroy_pending_snapshots(t); | ||||
| 
 | ||||
| 		btrfs_destroy_delalloc_inodes(root); | ||||
| 
 | ||||
| 		spin_lock(&root->fs_info->new_trans_lock); | ||||
| 		spin_lock(&root->fs_info->trans_lock); | ||||
| 		root->fs_info->running_transaction = NULL; | ||||
| 		spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 		btrfs_destroy_marked_extents(root, &t->dirty_pages, | ||||
| 					     EXTENT_DIRTY); | ||||
|  | @ -3082,8 +3080,10 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
| 		kmem_cache_free(btrfs_transaction_cachep, t); | ||||
| 	} | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	root->fs_info->trans_no_join = 0; | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 	mutex_unlock(&root->fs_info->transaction_kthread_mutex); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -348,7 +348,7 @@ static int caching_kthread(void *data) | |||
| 	 */ | ||||
| 	path->skip_locking = 1; | ||||
| 	path->search_commit_root = 1; | ||||
| 	path->reada = 2; | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	key.objectid = last; | ||||
| 	key.offset = 0; | ||||
|  | @ -366,8 +366,7 @@ again: | |||
| 	nritems = btrfs_header_nritems(leaf); | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		smp_mb(); | ||||
| 		if (fs_info->closing > 1) { | ||||
| 		if (btrfs_fs_closing(fs_info) > 1) { | ||||
| 			last = (u64)-1; | ||||
| 			break; | ||||
| 		} | ||||
|  | @ -379,15 +378,18 @@ again: | |||
| 			if (ret) | ||||
| 				break; | ||||
| 
 | ||||
| 			caching_ctl->progress = last; | ||||
| 			btrfs_release_path(path); | ||||
| 			up_read(&fs_info->extent_commit_sem); | ||||
| 			mutex_unlock(&caching_ctl->mutex); | ||||
| 			if (btrfs_transaction_in_commit(fs_info)) | ||||
| 				schedule_timeout(1); | ||||
| 			else | ||||
| 			if (need_resched() || | ||||
| 			    btrfs_next_leaf(extent_root, path)) { | ||||
| 				caching_ctl->progress = last; | ||||
| 				btrfs_release_path(path); | ||||
| 				up_read(&fs_info->extent_commit_sem); | ||||
| 				mutex_unlock(&caching_ctl->mutex); | ||||
| 				cond_resched(); | ||||
| 			goto again; | ||||
| 				goto again; | ||||
| 			} | ||||
| 			leaf = path->nodes[0]; | ||||
| 			nritems = btrfs_header_nritems(leaf); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		if (key.objectid < block_group->key.objectid) { | ||||
|  | @ -3065,7 +3067,7 @@ again: | |||
| 			spin_unlock(&data_sinfo->lock); | ||||
| alloc: | ||||
| 			alloc_target = btrfs_get_alloc_profile(root, 1); | ||||
| 			trans = btrfs_join_transaction(root, 1); | ||||
| 			trans = btrfs_join_transaction(root); | ||||
| 			if (IS_ERR(trans)) | ||||
| 				return PTR_ERR(trans); | ||||
| 
 | ||||
|  | @ -3091,9 +3093,10 @@ alloc: | |||
| 
 | ||||
| 		/* commit the current transaction and try again */ | ||||
| commit_trans: | ||||
| 		if (!committed && !root->fs_info->open_ioctl_trans) { | ||||
| 		if (!committed && | ||||
| 		    !atomic_read(&root->fs_info->open_ioctl_trans)) { | ||||
| 			committed = 1; | ||||
| 			trans = btrfs_join_transaction(root, 1); | ||||
| 			trans = btrfs_join_transaction(root); | ||||
| 			if (IS_ERR(trans)) | ||||
| 				return PTR_ERR(trans); | ||||
| 			ret = btrfs_commit_transaction(trans, root); | ||||
|  | @ -3472,7 +3475,7 @@ again: | |||
| 		goto out; | ||||
| 
 | ||||
| 	ret = -ENOSPC; | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		goto out; | ||||
| 	ret = btrfs_commit_transaction(trans, root); | ||||
|  | @ -3699,7 +3702,7 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans, | |||
| 		if (trans) | ||||
| 			return -EAGAIN; | ||||
| 
 | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		BUG_ON(IS_ERR(trans)); | ||||
| 		ret = btrfs_commit_transaction(trans, root); | ||||
| 		return 0; | ||||
|  | @ -3837,6 +3840,37 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info) | |||
| 	WARN_ON(fs_info->chunk_block_rsv.reserved > 0); | ||||
| } | ||||
| 
 | ||||
| int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans, | ||||
| 				    struct btrfs_root *root, | ||||
| 				    struct btrfs_block_rsv *rsv) | ||||
| { | ||||
| 	struct btrfs_block_rsv *trans_rsv = &root->fs_info->trans_block_rsv; | ||||
| 	u64 num_bytes; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Truncate should be freeing data, but give us 2 items just in case it | ||||
| 	 * needs to use some space.  We may want to be smarter about this in the | ||||
| 	 * future. | ||||
| 	 */ | ||||
| 	num_bytes = btrfs_calc_trans_metadata_size(root, 2); | ||||
| 
 | ||||
| 	/* We already have enough bytes, just return */ | ||||
| 	if (rsv->reserved >= num_bytes) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	num_bytes -= rsv->reserved; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * You should have reserved enough space before hand to do this, so this | ||||
| 	 * should not fail. | ||||
| 	 */ | ||||
| 	ret = block_rsv_migrate_bytes(trans_rsv, rsv, num_bytes); | ||||
| 	BUG_ON(ret); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans, | ||||
| 				 struct btrfs_root *root, | ||||
| 				 int num_items) | ||||
|  | @ -3877,23 +3911,18 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, | |||
| 	struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * one for deleting orphan item, one for updating inode and | ||||
| 	 * two for calling btrfs_truncate_inode_items. | ||||
| 	 * | ||||
| 	 * btrfs_truncate_inode_items is a delete operation, it frees | ||||
| 	 * more space than it uses in most cases. So two units of | ||||
| 	 * metadata space should be enough for calling it many times. | ||||
| 	 * If all of the metadata space is used, we can commit | ||||
| 	 * transaction and use space it freed. | ||||
| 	 * We need to hold space in order to delete our orphan item once we've | ||||
| 	 * added it, so this takes the reservation so we can release it later | ||||
| 	 * when we are truly done with the orphan item. | ||||
| 	 */ | ||||
| 	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); | ||||
| 	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); | ||||
| 	return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); | ||||
| } | ||||
| 
 | ||||
| void btrfs_orphan_release_metadata(struct inode *inode) | ||||
| { | ||||
| 	struct btrfs_root *root = BTRFS_I(inode)->root; | ||||
| 	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); | ||||
| 	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); | ||||
| 	btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); | ||||
| } | ||||
| 
 | ||||
|  | @ -4987,6 +5016,15 @@ have_block_group: | |||
| 		if (unlikely(block_group->ro)) | ||||
| 			goto loop; | ||||
| 
 | ||||
| 		spin_lock(&block_group->free_space_ctl->tree_lock); | ||||
| 		if (cached && | ||||
| 		    block_group->free_space_ctl->free_space < | ||||
| 		    num_bytes + empty_size) { | ||||
| 			spin_unlock(&block_group->free_space_ctl->tree_lock); | ||||
| 			goto loop; | ||||
| 		} | ||||
| 		spin_unlock(&block_group->free_space_ctl->tree_lock); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Ok we want to try and use the cluster allocator, so lets look | ||||
| 		 * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will | ||||
|  | @ -5150,6 +5188,7 @@ checks: | |||
| 			btrfs_add_free_space(block_group, offset, | ||||
| 					     search_start - offset); | ||||
| 		BUG_ON(offset > search_start); | ||||
| 		btrfs_put_block_group(block_group); | ||||
| 		break; | ||||
| loop: | ||||
| 		failed_cluster_refill = false; | ||||
|  | @ -5242,14 +5281,7 @@ loop: | |||
| 		ret = -ENOSPC; | ||||
| 	} else if (!ins->objectid) { | ||||
| 		ret = -ENOSPC; | ||||
| 	} | ||||
| 
 | ||||
| 	/* we found what we needed */ | ||||
| 	if (ins->objectid) { | ||||
| 		if (!(data & BTRFS_BLOCK_GROUP_DATA)) | ||||
| 			trans->block_group = block_group->key.objectid; | ||||
| 
 | ||||
| 		btrfs_put_block_group(block_group); | ||||
| 	} else if (ins->objectid) { | ||||
| 		ret = 0; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -6526,7 +6558,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, | |||
| 
 | ||||
| 	BUG_ON(cache->ro); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 
 | ||||
| 	alloc_flags = update_block_group_flags(root, cache->flags); | ||||
|  | @ -6882,6 +6914,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy); | ||||
| 	if (cache_gen != 0 && | ||||
|  |  | |||
|  | @ -1476,7 +1476,7 @@ u64 count_range_bits(struct extent_io_tree *tree, | |||
| 			if (total_bytes >= max_bytes) | ||||
| 				break; | ||||
| 			if (!found) { | ||||
| 				*start = state->start; | ||||
| 				*start = max(cur_start, state->start); | ||||
| 				found = 1; | ||||
| 			} | ||||
| 			last = state->end; | ||||
|  |  | |||
|  | @ -129,7 +129,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | |||
| 	if (!btrfs_test_opt(root, AUTO_DEFRAG)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (root->fs_info->closing) | ||||
| 	if (btrfs_fs_closing(root->fs_info)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (BTRFS_I(inode)->in_defrag) | ||||
|  | @ -144,7 +144,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | |||
| 	if (!defrag) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	defrag->ino = inode->i_ino; | ||||
| 	defrag->ino = btrfs_ino(inode); | ||||
| 	defrag->transid = transid; | ||||
| 	defrag->root = root->root_key.objectid; | ||||
| 
 | ||||
|  | @ -229,7 +229,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
| 		first_ino = defrag->ino + 1; | ||||
| 		rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); | ||||
| 
 | ||||
| 		if (fs_info->closing) | ||||
| 		if (btrfs_fs_closing(fs_info)) | ||||
| 			goto next_free; | ||||
| 
 | ||||
| 		spin_unlock(&fs_info->defrag_inodes_lock); | ||||
|  | @ -1480,14 +1480,12 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
| 	 * the current transaction, we can bail out now without any | ||||
| 	 * syncing | ||||
| 	 */ | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	smp_mb(); | ||||
| 	if (BTRFS_I(inode)->last_trans <= | ||||
| 	    root->fs_info->last_trans_committed) { | ||||
| 		BTRFS_I(inode)->last_trans = 0; | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * ok we haven't committed the transaction yet, lets do a commit | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root, | |||
| 		return inode; | ||||
| 
 | ||||
| 	spin_lock(&block_group->lock); | ||||
| 	if (!root->fs_info->closing) { | ||||
| 	if (!btrfs_fs_closing(root->fs_info)) { | ||||
| 		block_group->inode = igrab(inode); | ||||
| 		block_group->iref = 1; | ||||
| 	} | ||||
|  | @ -402,7 +402,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, | |||
| 				spin_lock(&ctl->tree_lock); | ||||
| 				ret = link_free_space(ctl, e); | ||||
| 				spin_unlock(&ctl->tree_lock); | ||||
| 				BUG_ON(ret); | ||||
| 				if (ret) { | ||||
| 					printk(KERN_ERR "Duplicate entries in " | ||||
| 					       "free space cache, dumping\n"); | ||||
| 					kunmap(page); | ||||
| 					unlock_page(page); | ||||
| 					page_cache_release(page); | ||||
| 					goto free_cache; | ||||
| 				} | ||||
| 			} else { | ||||
| 				e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS); | ||||
| 				if (!e->bitmap) { | ||||
|  | @ -419,6 +426,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, | |||
| 				ctl->op->recalc_thresholds(ctl); | ||||
| 				spin_unlock(&ctl->tree_lock); | ||||
| 				list_add_tail(&e->list, &bitmaps); | ||||
| 				if (ret) { | ||||
| 					printk(KERN_ERR "Duplicate entries in " | ||||
| 					       "free space cache, dumping\n"); | ||||
| 					kunmap(page); | ||||
| 					unlock_page(page); | ||||
| 					page_cache_release(page); | ||||
| 					goto free_cache; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			num_entries--; | ||||
|  | @ -478,8 +493,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, | |||
| 	 * If we're unmounting then just return, since this does a search on the | ||||
| 	 * normal root and not the commit root and we could deadlock. | ||||
| 	 */ | ||||
| 	smp_mb(); | ||||
| 	if (fs_info->closing) | ||||
| 	if (btrfs_fs_closing(fs_info)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -575,10 +589,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
| 
 | ||||
| 	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> | ||||
| 		PAGE_CACHE_SHIFT; | ||||
| 
 | ||||
| 	/* 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_pages) + sizeof(u64); | ||||
| 
 | ||||
| 	filemap_write_and_wait(inode->i_mapping); | ||||
| 	btrfs_wait_ordered_range(inode, inode->i_size & | ||||
| 				 ~(root->sectorsize - 1), (u64)-1); | ||||
| 
 | ||||
| 	/* make sure we don't overflow that first page */ | ||||
| 	if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) { | ||||
| 		/* this is really the same as running out of space, where we also return 0 */ | ||||
| 		printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n"); | ||||
| 		ret = 0; | ||||
| 		goto out_update; | ||||
| 	} | ||||
| 
 | ||||
| 	/* We need a checksum per page. */ | ||||
| 	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); | ||||
| 	if (!crc) | ||||
|  | @ -590,12 +619,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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_pages) + sizeof(u64); | ||||
| 
 | ||||
| 	/* Get the cluster for this block_group if it exists */ | ||||
| 	if (block_group && !list_empty(&block_group->cluster_list)) | ||||
| 		cluster = list_entry(block_group->cluster_list.next, | ||||
|  | @ -857,12 +880,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
| 	ret = 1; | ||||
| 
 | ||||
| out_free: | ||||
| 	kfree(checksums); | ||||
| 	kfree(pages); | ||||
| 
 | ||||
| out_update: | ||||
| 	if (ret != 1) { | ||||
| 		invalidate_inode_pages2_range(inode->i_mapping, 0, index); | ||||
| 		BTRFS_I(inode)->generation = 0; | ||||
| 	} | ||||
| 	kfree(checksums); | ||||
| 	kfree(pages); | ||||
| 	btrfs_update_inode(trans, root, inode); | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -963,10 +988,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset, | |||
| 			 * logically. | ||||
| 			 */ | ||||
| 			if (bitmap) { | ||||
| 				WARN_ON(info->bitmap); | ||||
| 				if (info->bitmap) { | ||||
| 					WARN_ON_ONCE(1); | ||||
| 					return -EEXIST; | ||||
| 				} | ||||
| 				p = &(*p)->rb_right; | ||||
| 			} else { | ||||
| 				WARN_ON(!info->bitmap); | ||||
| 				if (!info->bitmap) { | ||||
| 					WARN_ON_ONCE(1); | ||||
| 					return -EEXIST; | ||||
| 				} | ||||
| 				p = &(*p)->rb_left; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -2481,7 +2512,7 @@ struct inode *lookup_free_ino_inode(struct btrfs_root *root, | |||
| 		return inode; | ||||
| 
 | ||||
| 	spin_lock(&root->cache_lock); | ||||
| 	if (!root->fs_info->closing) | ||||
| 	if (!btrfs_fs_closing(root->fs_info)) | ||||
| 		root->cache_inode = igrab(inode); | ||||
| 	spin_unlock(&root->cache_lock); | ||||
| 
 | ||||
|  | @ -2504,12 +2535,14 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |||
| 	int ret = 0; | ||||
| 	u64 root_gen = btrfs_root_generation(&root->root_item); | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If we're unmounting then just return, since this does a search on the | ||||
| 	 * normal root and not the commit root and we could deadlock. | ||||
| 	 */ | ||||
| 	smp_mb(); | ||||
| 	if (fs_info->closing) | ||||
| 	if (btrfs_fs_closing(fs_info)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	path = btrfs_alloc_path(); | ||||
|  | @ -2543,6 +2576,9 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root, | |||
| 	struct inode *inode; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	inode = lookup_free_ino_inode(root, path); | ||||
| 	if (IS_ERR(inode)) | ||||
| 		return 0; | ||||
|  |  | |||
|  | @ -38,6 +38,9 @@ static int caching_kthread(void *data) | |||
| 	int slot; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
|  | @ -59,8 +62,7 @@ again: | |||
| 		goto out; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		smp_mb(); | ||||
| 		if (fs_info->closing) | ||||
| 		if (btrfs_fs_closing(fs_info)) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		leaf = path->nodes[0]; | ||||
|  | @ -141,6 +143,9 @@ static void start_caching(struct btrfs_root *root) | |||
| 	int ret; | ||||
| 	u64 objectid; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return; | ||||
| 
 | ||||
| 	spin_lock(&root->cache_lock); | ||||
| 	if (root->cached != BTRFS_CACHE_NO) { | ||||
| 		spin_unlock(&root->cache_lock); | ||||
|  | @ -178,6 +183,9 @@ static void start_caching(struct btrfs_root *root) | |||
| 
 | ||||
| int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) | ||||
| { | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return btrfs_find_free_objectid(root, objectid); | ||||
| 
 | ||||
| again: | ||||
| 	*objectid = btrfs_find_ino_for_alloc(root); | ||||
| 
 | ||||
|  | @ -201,6 +209,10 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid) | |||
| { | ||||
| 	struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | ||||
| 	struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return; | ||||
| 
 | ||||
| again: | ||||
| 	if (root->cached == BTRFS_CACHE_FINISHED) { | ||||
| 		__btrfs_add_free_space(ctl, objectid, 1); | ||||
|  | @ -250,6 +262,9 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) | |||
| 	struct rb_node *n; | ||||
| 	u64 count; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		n = rb_first(rbroot); | ||||
| 		if (!n) | ||||
|  | @ -388,9 +403,24 @@ int btrfs_save_ino_cache(struct btrfs_root *root, | |||
| 	int prealloc; | ||||
| 	bool retry = false; | ||||
| 
 | ||||
| 	/* only fs tree and subvol/snap needs ino cache */ | ||||
| 	if (root->root_key.objectid != BTRFS_FS_TREE_OBJECTID && | ||||
| 	    (root->root_key.objectid < BTRFS_FIRST_FREE_OBJECTID || | ||||
| 	     root->root_key.objectid > BTRFS_LAST_FREE_OBJECTID)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Don't save inode cache if we are deleting this root */ | ||||
| 	if (btrfs_root_refs(&root->root_item) == 0 && | ||||
| 	    root != root->fs_info->tree_root) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| again: | ||||
| 	inode = lookup_free_ino_inode(root, path); | ||||
| 	if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { | ||||
|  |  | |||
							
								
								
									
										261
									
								
								fs/btrfs/inode.c
									
										
									
									
									
								
							
							
						
						
									
										261
									
								
								fs/btrfs/inode.c
									
										
									
									
									
								
							|  | @ -138,7 +138,6 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	path->leave_spinning = 1; | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 	key.objectid = btrfs_ino(inode); | ||||
| 	key.offset = start; | ||||
|  | @ -426,9 +425,8 @@ again: | |||
| 		} | ||||
| 	} | ||||
| 	if (start == 0) { | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		BUG_ON(IS_ERR(trans)); | ||||
| 		btrfs_set_trans_block_group(trans, inode); | ||||
| 		trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 
 | ||||
| 		/* lets try to make an inline extent */ | ||||
|  | @ -623,8 +621,9 @@ retry: | |||
| 			    async_extent->start + async_extent->ram_size - 1, | ||||
| 			    GFP_NOFS); | ||||
| 
 | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		BUG_ON(IS_ERR(trans)); | ||||
| 		trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 		ret = btrfs_reserve_extent(trans, root, | ||||
| 					   async_extent->compressed_size, | ||||
| 					   async_extent->compressed_size, | ||||
|  | @ -793,9 +792,8 @@ static noinline int cow_file_range(struct inode *inode, | |||
| 	int ret = 0; | ||||
| 
 | ||||
| 	BUG_ON(is_free_space_inode(root, inode)); | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 
 | ||||
| 	num_bytes = (end - start + blocksize) & ~(blocksize - 1); | ||||
|  | @ -1077,10 +1075,12 @@ static noinline int run_delalloc_nocow(struct inode *inode, | |||
| 	nolock = is_free_space_inode(root, inode); | ||||
| 
 | ||||
| 	if (nolock) | ||||
| 		trans = btrfs_join_transaction_nolock(root, 1); | ||||
| 		trans = btrfs_join_transaction_nolock(root); | ||||
| 	else | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 
 | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 	trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 
 | ||||
| 	cow_start = (u64)-1; | ||||
| 	cur_offset = start; | ||||
|  | @ -1519,8 +1519,6 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, | |||
| { | ||||
| 	struct btrfs_ordered_sum *sum; | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 	list_for_each_entry(sum, list, list) { | ||||
| 		btrfs_csum_file_blocks(trans, | ||||
| 		       BTRFS_I(inode)->root->fs_info->csum_root, sum); | ||||
|  | @ -1735,11 +1733,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 		ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | ||||
| 		if (!ret) { | ||||
| 			if (nolock) | ||||
| 				trans = btrfs_join_transaction_nolock(root, 1); | ||||
| 				trans = btrfs_join_transaction_nolock(root); | ||||
| 			else | ||||
| 				trans = btrfs_join_transaction(root, 1); | ||||
| 				trans = btrfs_join_transaction(root); | ||||
| 			BUG_ON(IS_ERR(trans)); | ||||
| 			btrfs_set_trans_block_group(trans, inode); | ||||
| 			trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 			ret = btrfs_update_inode(trans, root, inode); | ||||
| 			BUG_ON(ret); | ||||
|  | @ -1752,11 +1749,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 			 0, &cached_state, GFP_NOFS); | ||||
| 
 | ||||
| 	if (nolock) | ||||
| 		trans = btrfs_join_transaction_nolock(root, 1); | ||||
| 		trans = btrfs_join_transaction_nolock(root); | ||||
| 	else | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||||
| 
 | ||||
| 	if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) | ||||
|  | @ -2431,7 +2427,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
| 					(u64)-1); | ||||
| 
 | ||||
| 	if (root->orphan_block_rsv || root->orphan_item_inserted) { | ||||
| 		trans = btrfs_join_transaction(root, 1); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		if (!IS_ERR(trans)) | ||||
| 			btrfs_end_transaction(trans, root); | ||||
| 	} | ||||
|  | @ -2511,12 +2507,12 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 	struct btrfs_root *root = BTRFS_I(inode)->root; | ||||
| 	struct btrfs_key location; | ||||
| 	int maybe_acls; | ||||
| 	u64 alloc_group_block; | ||||
| 	u32 rdev; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	path = btrfs_alloc_path(); | ||||
| 	BUG_ON(!path); | ||||
| 	path->leave_spinning = 1; | ||||
| 	memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); | ||||
| 
 | ||||
| 	ret = btrfs_lookup_inode(NULL, root, path, &location, 0); | ||||
|  | @ -2526,6 +2522,12 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 	leaf = path->nodes[0]; | ||||
| 	inode_item = btrfs_item_ptr(leaf, path->slots[0], | ||||
| 				    struct btrfs_inode_item); | ||||
| 	if (!leaf->map_token) | ||||
| 		map_private_extent_buffer(leaf, (unsigned long)inode_item, | ||||
| 					  sizeof(struct btrfs_inode_item), | ||||
| 					  &leaf->map_token, &leaf->kaddr, | ||||
| 					  &leaf->map_start, &leaf->map_len, | ||||
| 					  KM_USER1); | ||||
| 
 | ||||
| 	inode->i_mode = btrfs_inode_mode(leaf, inode_item); | ||||
| 	inode->i_nlink = btrfs_inode_nlink(leaf, inode_item); | ||||
|  | @ -2555,8 +2557,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 	BTRFS_I(inode)->index_cnt = (u64)-1; | ||||
| 	BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | ||||
| 
 | ||||
| 	alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * try to precache a NULL acl entry for files that don't have | ||||
| 	 * any xattrs or acls | ||||
|  | @ -2566,8 +2566,11 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 	if (!maybe_acls) | ||||
| 		cache_no_acl(inode); | ||||
| 
 | ||||
| 	BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, | ||||
| 						alloc_group_block, 0); | ||||
| 	if (leaf->map_token) { | ||||
| 		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); | ||||
| 		leaf->map_token = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	btrfs_free_path(path); | ||||
| 	inode_item = NULL; | ||||
| 
 | ||||
|  | @ -2647,7 +2650,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
| 	btrfs_set_inode_transid(leaf, item, trans->transid); | ||||
| 	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); | ||||
| 	btrfs_set_inode_block_group(leaf, item, 0); | ||||
| 
 | ||||
| 	if (leaf->map_token) { | ||||
| 		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); | ||||
|  | @ -3004,8 +3007,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0); | ||||
| 
 | ||||
| 	ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, | ||||
|  | @ -3094,8 +3095,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	if (unlikely(btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { | ||||
| 		err = btrfs_unlink_subvol(trans, root, dir, | ||||
| 					  BTRFS_I(inode)->location.objectid, | ||||
|  | @ -3514,7 +3513,6 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) | |||
| 				err = PTR_ERR(trans); | ||||
| 				break; | ||||
| 			} | ||||
| 			btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 			err = btrfs_drop_extents(trans, inode, cur_offset, | ||||
| 						 cur_offset + hole_size, | ||||
|  | @ -3650,7 +3648,6 @@ void btrfs_evict_inode(struct inode *inode) | |||
| 	while (1) { | ||||
| 		trans = btrfs_start_transaction(root, 0); | ||||
| 		BUG_ON(IS_ERR(trans)); | ||||
| 		btrfs_set_trans_block_group(trans, inode); | ||||
| 		trans->block_rsv = root->orphan_block_rsv; | ||||
| 
 | ||||
| 		ret = btrfs_block_rsv_check(trans, root, | ||||
|  | @ -4133,7 +4130,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = 2; | ||||
| 
 | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	if (key_type == BTRFS_DIR_INDEX_KEY) { | ||||
| 		INIT_LIST_HEAD(&ins_list); | ||||
|  | @ -4268,18 +4266,16 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 	if (BTRFS_I(inode)->dummy_inode) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	smp_mb(); | ||||
| 	if (root->fs_info->closing && is_free_space_inode(root, inode)) | ||||
| 	if (btrfs_fs_closing(root->fs_info) && is_free_space_inode(root, inode)) | ||||
| 		nolock = true; | ||||
| 
 | ||||
| 	if (wbc->sync_mode == WB_SYNC_ALL) { | ||||
| 		if (nolock) | ||||
| 			trans = btrfs_join_transaction_nolock(root, 1); | ||||
| 			trans = btrfs_join_transaction_nolock(root); | ||||
| 		else | ||||
| 			trans = btrfs_join_transaction(root, 1); | ||||
| 			trans = btrfs_join_transaction(root); | ||||
| 		if (IS_ERR(trans)) | ||||
| 			return PTR_ERR(trans); | ||||
| 		btrfs_set_trans_block_group(trans, inode); | ||||
| 		if (nolock) | ||||
| 			ret = btrfs_end_transaction_nolock(trans, root); | ||||
| 		else | ||||
|  | @ -4303,9 +4299,8 @@ void btrfs_dirty_inode(struct inode *inode, int flags) | |||
| 	if (BTRFS_I(inode)->dummy_inode) | ||||
| 		return; | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 	ret = btrfs_update_inode(trans, root, inode); | ||||
| 	if (ret && ret == -ENOSPC) { | ||||
|  | @ -4319,7 +4314,6 @@ void btrfs_dirty_inode(struct inode *inode, int flags) | |||
| 				       PTR_ERR(trans)); | ||||
| 			return; | ||||
| 		} | ||||
| 		btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 		ret = btrfs_update_inode(trans, root, inode); | ||||
| 		if (ret) { | ||||
|  | @ -4418,8 +4412,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 				     struct btrfs_root *root, | ||||
| 				     struct inode *dir, | ||||
| 				     const char *name, int name_len, | ||||
| 				     u64 ref_objectid, u64 objectid, | ||||
| 				     u64 alloc_hint, int mode, u64 *index) | ||||
| 				     u64 ref_objectid, u64 objectid, int mode, | ||||
| 				     u64 *index) | ||||
| { | ||||
| 	struct inode *inode; | ||||
| 	struct btrfs_inode_item *inode_item; | ||||
|  | @ -4472,8 +4466,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 		owner = 0; | ||||
| 	else | ||||
| 		owner = 1; | ||||
| 	BTRFS_I(inode)->block_group = | ||||
| 			btrfs_find_block_group(root, 0, alloc_hint, owner); | ||||
| 
 | ||||
| 	key[0].objectid = objectid; | ||||
| 	btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); | ||||
|  | @ -4629,15 +4621,13 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	err = btrfs_find_free_ino(root, &objectid); | ||||
| 	if (err) | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
| 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | ||||
| 				dentry->d_name.len, btrfs_ino(dir), objectid, | ||||
| 				BTRFS_I(dir)->block_group, mode, &index); | ||||
| 				mode, &index); | ||||
| 	if (IS_ERR(inode)) { | ||||
| 		err = PTR_ERR(inode); | ||||
| 		goto out_unlock; | ||||
|  | @ -4649,7 +4639,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 		goto out_unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); | ||||
| 	if (err) | ||||
| 		drop_inode = 1; | ||||
|  | @ -4658,8 +4647,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 		init_special_inode(inode, inode->i_mode, rdev); | ||||
| 		btrfs_update_inode(trans, root, inode); | ||||
| 	} | ||||
| 	btrfs_update_inode_block_group(trans, inode); | ||||
| 	btrfs_update_inode_block_group(trans, dir); | ||||
| out_unlock: | ||||
| 	nr = trans->blocks_used; | ||||
| 	btrfs_end_transaction_throttle(trans, root); | ||||
|  | @ -4692,15 +4679,13 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	err = btrfs_find_free_ino(root, &objectid); | ||||
| 	if (err) | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
| 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | ||||
| 				dentry->d_name.len, btrfs_ino(dir), objectid, | ||||
| 				BTRFS_I(dir)->block_group, mode, &index); | ||||
| 				mode, &index); | ||||
| 	if (IS_ERR(inode)) { | ||||
| 		err = PTR_ERR(inode); | ||||
| 		goto out_unlock; | ||||
|  | @ -4712,7 +4697,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
| 		goto out_unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); | ||||
| 	if (err) | ||||
| 		drop_inode = 1; | ||||
|  | @ -4723,8 +4707,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
| 		inode->i_op = &btrfs_file_inode_operations; | ||||
| 		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; | ||||
| 	} | ||||
| 	btrfs_update_inode_block_group(trans, inode); | ||||
| 	btrfs_update_inode_block_group(trans, dir); | ||||
| out_unlock: | ||||
| 	nr = trans->blocks_used; | ||||
| 	btrfs_end_transaction_throttle(trans, root); | ||||
|  | @ -4771,8 +4753,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 
 | ||||
| 	btrfs_inc_nlink(inode); | ||||
| 	inode->i_ctime = CURRENT_TIME; | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 	ihold(inode); | ||||
| 
 | ||||
| 	err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index); | ||||
|  | @ -4781,7 +4761,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 		drop_inode = 1; | ||||
| 	} else { | ||||
| 		struct dentry *parent = dget_parent(dentry); | ||||
| 		btrfs_update_inode_block_group(trans, dir); | ||||
| 		err = btrfs_update_inode(trans, root, inode); | ||||
| 		BUG_ON(err); | ||||
| 		btrfs_log_new_name(trans, inode, NULL, parent); | ||||
|  | @ -4818,7 +4797,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 	trans = btrfs_start_transaction(root, 5); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	err = btrfs_find_free_ino(root, &objectid); | ||||
| 	if (err) | ||||
|  | @ -4826,8 +4804,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 
 | ||||
| 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | ||||
| 				dentry->d_name.len, btrfs_ino(dir), objectid, | ||||
| 				BTRFS_I(dir)->block_group, S_IFDIR | mode, | ||||
| 				&index); | ||||
| 				S_IFDIR | mode, &index); | ||||
| 	if (IS_ERR(inode)) { | ||||
| 		err = PTR_ERR(inode); | ||||
| 		goto out_fail; | ||||
|  | @ -4841,7 +4818,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 
 | ||||
| 	inode->i_op = &btrfs_dir_inode_operations; | ||||
| 	inode->i_fop = &btrfs_dir_file_operations; | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 	btrfs_i_size_write(inode, 0); | ||||
| 	err = btrfs_update_inode(trans, root, inode); | ||||
|  | @ -4855,8 +4831,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 
 | ||||
| 	d_instantiate(dentry, inode); | ||||
| 	drop_on_err = 0; | ||||
| 	btrfs_update_inode_block_group(trans, inode); | ||||
| 	btrfs_update_inode_block_group(trans, dir); | ||||
| 
 | ||||
| out_fail: | ||||
| 	nr = trans->blocks_used; | ||||
|  | @ -4989,7 +4963,15 @@ again: | |||
| 
 | ||||
| 	if (!path) { | ||||
| 		path = btrfs_alloc_path(); | ||||
| 		BUG_ON(!path); | ||||
| 		if (!path) { | ||||
| 			err = -ENOMEM; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		/*
 | ||||
| 		 * Chances are we'll be called again, so go ahead and do | ||||
| 		 * readahead | ||||
| 		 */ | ||||
| 		path->reada = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = btrfs_lookup_file_extent(trans, root, path, | ||||
|  | @ -5130,8 +5112,10 @@ again: | |||
| 				kunmap(page); | ||||
| 				free_extent_map(em); | ||||
| 				em = NULL; | ||||
| 
 | ||||
| 				btrfs_release_path(path); | ||||
| 				trans = btrfs_join_transaction(root, 1); | ||||
| 				trans = btrfs_join_transaction(root); | ||||
| 
 | ||||
| 				if (IS_ERR(trans)) | ||||
| 					return ERR_CAST(trans); | ||||
| 				goto again; | ||||
|  | @ -5375,7 +5359,7 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
| 		btrfs_drop_extent_cache(inode, start, start + len - 1, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 0); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return ERR_CAST(trans); | ||||
| 
 | ||||
|  | @ -5611,7 +5595,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
| 		 * to make sure the current transaction stays open | ||||
| 		 * while we look for nocow cross refs | ||||
| 		 */ | ||||
| 		trans = btrfs_join_transaction(root, 0); | ||||
| 		trans = btrfs_join_transaction(root); | ||||
| 		if (IS_ERR(trans)) | ||||
| 			goto must_cow; | ||||
| 
 | ||||
|  | @ -5750,7 +5734,7 @@ again: | |||
| 
 | ||||
| 	BUG_ON(!ordered); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		err = -ENOMEM; | ||||
| 		goto out; | ||||
|  | @ -6500,6 +6484,7 @@ out: | |||
| static int btrfs_truncate(struct inode *inode) | ||||
| { | ||||
| 	struct btrfs_root *root = BTRFS_I(inode)->root; | ||||
| 	struct btrfs_block_rsv *rsv; | ||||
| 	int ret; | ||||
| 	int err = 0; | ||||
| 	struct btrfs_trans_handle *trans; | ||||
|  | @ -6513,28 +6498,80 @@ static int btrfs_truncate(struct inode *inode) | |||
| 	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); | ||||
| 	btrfs_ordered_update_i_size(inode, inode->i_size, NULL); | ||||
| 
 | ||||
| 	trans = btrfs_start_transaction(root, 5); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 	/*
 | ||||
| 	 * Yes ladies and gentelment, this is indeed ugly.  The fact is we have | ||||
| 	 * 3 things going on here | ||||
| 	 * | ||||
| 	 * 1) We need to reserve space for our orphan item and the space to | ||||
| 	 * delete our orphan item.  Lord knows we don't want to have a dangling | ||||
| 	 * orphan item because we didn't reserve space to remove it. | ||||
| 	 * | ||||
| 	 * 2) We need to reserve space to update our inode. | ||||
| 	 * | ||||
| 	 * 3) We need to have something to cache all the space that is going to | ||||
| 	 * be free'd up by the truncate operation, but also have some slack | ||||
| 	 * space reserved in case it uses space during the truncate (thank you | ||||
| 	 * very much snapshotting). | ||||
| 	 * | ||||
| 	 * And we need these to all be seperate.  The fact is we can use alot of | ||||
| 	 * space doing the truncate, and we have no earthly idea how much space | ||||
| 	 * we will use, so we need the truncate reservation to be seperate so it | ||||
| 	 * doesn't end up using space reserved for updating the inode or | ||||
| 	 * removing the orphan item.  We also need to be able to stop the | ||||
| 	 * transaction and start a new one, which means we need to be able to | ||||
| 	 * update the inode several times, and we have no idea of knowing how | ||||
| 	 * many times that will be, so we can't just reserve 1 item for the | ||||
| 	 * entirety of the opration, so that has to be done seperately as well. | ||||
| 	 * Then there is the orphan item, which does indeed need to be held on | ||||
| 	 * to for the whole operation, and we need nobody to touch this reserved | ||||
| 	 * space except the orphan code. | ||||
| 	 * | ||||
| 	 * So that leaves us with | ||||
| 	 * | ||||
| 	 * 1) root->orphan_block_rsv - for the orphan deletion. | ||||
| 	 * 2) rsv - for the truncate reservation, which we will steal from the | ||||
| 	 * transaction reservation. | ||||
| 	 * 3) fs_info->trans_block_rsv - this will have 1 items worth left for | ||||
| 	 * updating the inode. | ||||
| 	 */ | ||||
| 	rsv = btrfs_alloc_block_rsv(root); | ||||
| 	if (!rsv) | ||||
| 		return -ENOMEM; | ||||
| 	btrfs_add_durable_block_rsv(root->fs_info, rsv); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	trans = btrfs_start_transaction(root, 4); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		err = PTR_ERR(trans); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Reserve space for the truncate process.  Truncate should be adding | ||||
| 	 * space, but if there are snapshots it may end up using space. | ||||
| 	 */ | ||||
| 	ret = btrfs_truncate_reserve_metadata(trans, root, rsv); | ||||
| 	BUG_ON(ret); | ||||
| 
 | ||||
| 	ret = btrfs_orphan_add(trans, inode); | ||||
| 	if (ret) { | ||||
| 		btrfs_end_transaction(trans, root); | ||||
| 		return ret; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	nr = trans->blocks_used; | ||||
| 	btrfs_end_transaction(trans, root); | ||||
| 	btrfs_btree_balance_dirty(root, nr); | ||||
| 
 | ||||
| 	/* Now start a transaction for the truncate */ | ||||
| 	trans = btrfs_start_transaction(root, 0); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	trans->block_rsv = root->orphan_block_rsv; | ||||
| 	/*
 | ||||
| 	 * Ok so we've already migrated our bytes over for the truncate, so here | ||||
| 	 * just reserve the one slot we need for updating the inode. | ||||
| 	 */ | ||||
| 	trans = btrfs_start_transaction(root, 1); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		err = PTR_ERR(trans); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	trans->block_rsv = rsv; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * setattr is responsible for setting the ordered_data_close flag, | ||||
|  | @ -6558,24 +6595,17 @@ static int btrfs_truncate(struct inode *inode) | |||
| 
 | ||||
| 	while (1) { | ||||
| 		if (!trans) { | ||||
| 			trans = btrfs_start_transaction(root, 0); | ||||
| 			if (IS_ERR(trans)) | ||||
| 				return PTR_ERR(trans); | ||||
| 			btrfs_set_trans_block_group(trans, inode); | ||||
| 			trans->block_rsv = root->orphan_block_rsv; | ||||
| 		} | ||||
| 			trans = btrfs_start_transaction(root, 3); | ||||
| 			if (IS_ERR(trans)) { | ||||
| 				err = PTR_ERR(trans); | ||||
| 				goto out; | ||||
| 			} | ||||
| 
 | ||||
| 		ret = btrfs_block_rsv_check(trans, root, | ||||
| 					    root->orphan_block_rsv, 0, 5); | ||||
| 		if (ret == -EAGAIN) { | ||||
| 			ret = btrfs_commit_transaction(trans, root); | ||||
| 			if (ret) | ||||
| 				return ret; | ||||
| 			trans = NULL; | ||||
| 			continue; | ||||
| 		} else if (ret) { | ||||
| 			err = ret; | ||||
| 			break; | ||||
| 			ret = btrfs_truncate_reserve_metadata(trans, root, | ||||
| 							      rsv); | ||||
| 			BUG_ON(ret); | ||||
| 
 | ||||
| 			trans->block_rsv = rsv; | ||||
| 		} | ||||
| 
 | ||||
| 		ret = btrfs_truncate_inode_items(trans, root, inode, | ||||
|  | @ -6586,6 +6616,7 @@ static int btrfs_truncate(struct inode *inode) | |||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		trans->block_rsv = &root->fs_info->trans_block_rsv; | ||||
| 		ret = btrfs_update_inode(trans, root, inode); | ||||
| 		if (ret) { | ||||
| 			err = ret; | ||||
|  | @ -6599,6 +6630,7 @@ static int btrfs_truncate(struct inode *inode) | |||
| 	} | ||||
| 
 | ||||
| 	if (ret == 0 && inode->i_nlink > 0) { | ||||
| 		trans->block_rsv = root->orphan_block_rsv; | ||||
| 		ret = btrfs_orphan_del(trans, inode); | ||||
| 		if (ret) | ||||
| 			err = ret; | ||||
|  | @ -6610,15 +6642,20 @@ static int btrfs_truncate(struct inode *inode) | |||
| 		ret = btrfs_orphan_del(NULL, inode); | ||||
| 	} | ||||
| 
 | ||||
| 	trans->block_rsv = &root->fs_info->trans_block_rsv; | ||||
| 	ret = btrfs_update_inode(trans, root, inode); | ||||
| 	if (ret && !err) | ||||
| 		err = ret; | ||||
| 
 | ||||
| 	nr = trans->blocks_used; | ||||
| 	ret = btrfs_end_transaction_throttle(trans, root); | ||||
| 	btrfs_btree_balance_dirty(root, nr); | ||||
| 
 | ||||
| out: | ||||
| 	btrfs_free_block_rsv(root, rsv); | ||||
| 
 | ||||
| 	if (ret && !err) | ||||
| 		err = ret; | ||||
| 	btrfs_btree_balance_dirty(root, nr); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
|  | @ -6627,15 +6664,14 @@ static int btrfs_truncate(struct inode *inode) | |||
|  * create a new subvolume directory/inode (helper for the ioctl). | ||||
|  */ | ||||
| int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | ||||
| 			     struct btrfs_root *new_root, | ||||
| 			     u64 new_dirid, u64 alloc_hint) | ||||
| 			     struct btrfs_root *new_root, u64 new_dirid) | ||||
| { | ||||
| 	struct inode *inode; | ||||
| 	int err; | ||||
| 	u64 index = 0; | ||||
| 
 | ||||
| 	inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, | ||||
| 				new_dirid, alloc_hint, S_IFDIR | 0700, &index); | ||||
| 				new_dirid, S_IFDIR | 0700, &index); | ||||
| 	if (IS_ERR(inode)) | ||||
| 		return PTR_ERR(inode); | ||||
| 	inode->i_op = &btrfs_dir_inode_operations; | ||||
|  | @ -6748,21 +6784,6 @@ void btrfs_destroy_inode(struct inode *inode) | |||
| 		spin_unlock(&root->fs_info->ordered_extent_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (root == root->fs_info->tree_root) { | ||||
| 		struct btrfs_block_group_cache *block_group; | ||||
| 
 | ||||
| 		block_group = btrfs_lookup_block_group(root->fs_info, | ||||
| 						BTRFS_I(inode)->block_group); | ||||
| 		if (block_group && block_group->inode == inode) { | ||||
| 			spin_lock(&block_group->lock); | ||||
| 			block_group->inode = NULL; | ||||
| 			spin_unlock(&block_group->lock); | ||||
| 			btrfs_put_block_group(block_group); | ||||
| 		} else if (block_group) { | ||||
| 			btrfs_put_block_group(block_group); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	spin_lock(&root->orphan_lock); | ||||
| 	if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | ||||
| 		printk(KERN_INFO "BTRFS: inode %llu still on the orphan list\n", | ||||
|  | @ -6948,8 +6969,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
|                 goto out_notrans; | ||||
|         } | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, new_dir); | ||||
| 
 | ||||
| 	if (dest != root) | ||||
| 		btrfs_record_root_in_trans(trans, dest); | ||||
| 
 | ||||
|  | @ -7131,16 +7150,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, dir); | ||||
| 
 | ||||
| 	err = btrfs_find_free_ino(root, &objectid); | ||||
| 	if (err) | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
| 	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | ||||
| 				dentry->d_name.len, btrfs_ino(dir), objectid, | ||||
| 				BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, | ||||
| 				&index); | ||||
| 				S_IFLNK|S_IRWXUGO, &index); | ||||
| 	if (IS_ERR(inode)) { | ||||
| 		err = PTR_ERR(inode); | ||||
| 		goto out_unlock; | ||||
|  | @ -7152,7 +7168,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 		goto out_unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); | ||||
| 	if (err) | ||||
| 		drop_inode = 1; | ||||
|  | @ -7163,8 +7178,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 		inode->i_op = &btrfs_file_inode_operations; | ||||
| 		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; | ||||
| 	} | ||||
| 	btrfs_update_inode_block_group(trans, inode); | ||||
| 	btrfs_update_inode_block_group(trans, dir); | ||||
| 	if (drop_inode) | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
|  |  | |||
|  | @ -243,7 +243,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); | ||||
| 	} | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 1); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 
 | ||||
| 	ret = btrfs_update_inode(trans, root, inode); | ||||
|  | @ -414,8 +414,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 
 | ||||
| 	btrfs_record_root_in_trans(trans, new_root); | ||||
| 
 | ||||
| 	ret = btrfs_create_subvol_root(trans, new_root, new_dirid, | ||||
| 				       BTRFS_I(dir)->block_group); | ||||
| 	ret = btrfs_create_subvol_root(trans, new_root, new_dirid); | ||||
| 	/*
 | ||||
| 	 * insert the directory item | ||||
| 	 */ | ||||
|  | @ -707,16 +706,17 @@ static int find_new_extents(struct btrfs_root *root, | |||
| 	struct btrfs_file_extent_item *extent; | ||||
| 	int type; | ||||
| 	int ret; | ||||
| 	u64 ino = btrfs_ino(inode); | ||||
| 
 | ||||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	min_key.objectid = inode->i_ino; | ||||
| 	min_key.objectid = ino; | ||||
| 	min_key.type = BTRFS_EXTENT_DATA_KEY; | ||||
| 	min_key.offset = *off; | ||||
| 
 | ||||
| 	max_key.objectid = inode->i_ino; | ||||
| 	max_key.objectid = ino; | ||||
| 	max_key.type = (u8)-1; | ||||
| 	max_key.offset = (u64)-1; | ||||
| 
 | ||||
|  | @ -727,7 +727,7 @@ static int find_new_extents(struct btrfs_root *root, | |||
| 					   path, 0, newer_than); | ||||
| 		if (ret != 0) | ||||
| 			goto none; | ||||
| 		if (min_key.objectid != inode->i_ino) | ||||
| 		if (min_key.objectid != ino) | ||||
| 			goto none; | ||||
| 		if (min_key.type != BTRFS_EXTENT_DATA_KEY) | ||||
| 			goto none; | ||||
|  | @ -2489,12 +2489,10 @@ static long btrfs_ioctl_trans_start(struct file *file) | |||
| 	if (ret) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	root->fs_info->open_ioctl_trans++; | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	atomic_inc(&root->fs_info->open_ioctl_trans); | ||||
| 
 | ||||
| 	ret = -ENOMEM; | ||||
| 	trans = btrfs_start_ioctl_transaction(root, 0); | ||||
| 	trans = btrfs_start_ioctl_transaction(root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		goto out_drop; | ||||
| 
 | ||||
|  | @ -2502,9 +2500,7 @@ static long btrfs_ioctl_trans_start(struct file *file) | |||
| 	return 0; | ||||
| 
 | ||||
| out_drop: | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	root->fs_info->open_ioctl_trans--; | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	atomic_dec(&root->fs_info->open_ioctl_trans); | ||||
| 	mnt_drop_write(file->f_path.mnt); | ||||
| out: | ||||
| 	return ret; | ||||
|  | @ -2738,9 +2734,7 @@ long btrfs_ioctl_trans_end(struct file *file) | |||
| 
 | ||||
| 	btrfs_end_transaction(trans, root); | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	root->fs_info->open_ioctl_trans--; | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	atomic_dec(&root->fs_info->open_ioctl_trans); | ||||
| 
 | ||||
| 	mnt_drop_write(file->f_path.mnt); | ||||
| 	return 0; | ||||
|  |  | |||
|  | @ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, | |||
| 		err = -ENOMEM; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	path1->reada = 1; | ||||
| 	path2->reada = 2; | ||||
| 
 | ||||
| 	node = alloc_backref_node(cache); | ||||
| 	if (!node) { | ||||
|  | @ -1999,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	reloc_root = root->reloc_root; | ||||
| 	root_item = &reloc_root->root_item; | ||||
|  | @ -2139,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err) | |||
| 	u64 num_bytes = 0; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; | ||||
| 	rc->merging_rsv_size += rc->nodes_relocated * 2; | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| again: | ||||
| 	if (!err) { | ||||
| 		num_bytes = rc->merging_rsv_size; | ||||
|  | @ -2152,7 +2155,7 @@ again: | |||
| 			err = ret; | ||||
| 	} | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(rc->extent_root, 1); | ||||
| 	trans = btrfs_join_transaction(rc->extent_root); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		if (!err) | ||||
| 			btrfs_block_rsv_release(rc->extent_root, | ||||
|  | @ -2211,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc) | |||
| 	int ret; | ||||
| again: | ||||
| 	root = rc->extent_root; | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	list_splice_init(&rc->reloc_roots, &reloc_roots); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	while (!list_empty(&reloc_roots)) { | ||||
| 		found = 1; | ||||
|  | @ -3236,7 +3239,7 @@ truncate: | |||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(root, 0); | ||||
| 	trans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		btrfs_free_path(path); | ||||
| 		ret = PTR_ERR(trans); | ||||
|  | @ -3300,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc, | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	root = read_fs_root(rc->extent_root->fs_info, ref_root); | ||||
| 	if (IS_ERR(root)) { | ||||
|  | @ -3586,17 +3590,17 @@ next: | |||
| static void set_reloc_control(struct reloc_control *rc) | ||||
| { | ||||
| 	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | ||||
| 	mutex_lock(&fs_info->trans_mutex); | ||||
| 	spin_lock(&fs_info->trans_lock); | ||||
| 	fs_info->reloc_ctl = rc; | ||||
| 	mutex_unlock(&fs_info->trans_mutex); | ||||
| 	spin_unlock(&fs_info->trans_lock); | ||||
| } | ||||
| 
 | ||||
| static void unset_reloc_control(struct reloc_control *rc) | ||||
| { | ||||
| 	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | ||||
| 	mutex_lock(&fs_info->trans_mutex); | ||||
| 	spin_lock(&fs_info->trans_lock); | ||||
| 	fs_info->reloc_ctl = NULL; | ||||
| 	mutex_unlock(&fs_info->trans_mutex); | ||||
| 	spin_unlock(&fs_info->trans_lock); | ||||
| } | ||||
| 
 | ||||
| static int check_extent_flags(u64 flags) | ||||
|  | @ -3645,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
| 	rc->create_reloc_tree = 1; | ||||
| 	set_reloc_control(rc); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(rc->extent_root, 1); | ||||
| 	trans = btrfs_join_transaction(rc->extent_root); | ||||
| 	BUG_ON(IS_ERR(trans)); | ||||
| 	btrfs_commit_transaction(trans, rc->extent_root); | ||||
| 	return 0; | ||||
|  | @ -3668,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = 1; | ||||
| 
 | ||||
| 	ret = prepare_to_relocate(rc); | ||||
| 	if (ret) { | ||||
|  | @ -3834,7 +3839,7 @@ restart: | |||
| 	btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1); | ||||
| 
 | ||||
| 	/* get rid of pinned extents */ | ||||
| 	trans = btrfs_join_transaction(rc->extent_root, 1); | ||||
| 	trans = btrfs_join_transaction(rc->extent_root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		err = PTR_ERR(trans); | ||||
| 	else | ||||
|  | @ -4093,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
| 	path = btrfs_alloc_path(); | ||||
| 	if (!path) | ||||
| 		return -ENOMEM; | ||||
| 	path->reada = -1; | ||||
| 
 | ||||
| 	key.objectid = BTRFS_TREE_RELOC_OBJECTID; | ||||
| 	key.type = BTRFS_ROOT_ITEM_KEY; | ||||
|  | @ -4159,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
| 
 | ||||
| 	set_reloc_control(rc); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(rc->extent_root, 1); | ||||
| 	trans = btrfs_join_transaction(rc->extent_root); | ||||
| 	if (IS_ERR(trans)) { | ||||
| 		unset_reloc_control(rc); | ||||
| 		err = PTR_ERR(trans); | ||||
|  | @ -4193,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
| 
 | ||||
| 	unset_reloc_control(rc); | ||||
| 
 | ||||
| 	trans = btrfs_join_transaction(rc->extent_root, 1); | ||||
| 	trans = btrfs_join_transaction(rc->extent_root); | ||||
| 	if (IS_ERR(trans)) | ||||
| 		err = PTR_ERR(trans); | ||||
| 	else | ||||
|  |  | |||
							
								
								
									
										123
									
								
								fs/btrfs/scrub.c
									
										
									
									
									
								
							
							
						
						
									
										123
									
								
								fs/btrfs/scrub.c
									
										
									
									
									
								
							|  | @ -117,33 +117,37 @@ static void scrub_free_csums(struct scrub_dev *sdev) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void scrub_free_bio(struct bio *bio) | ||||
| { | ||||
| 	int i; | ||||
| 	struct page *last_page = NULL; | ||||
| 
 | ||||
| 	if (!bio) | ||||
| 		return; | ||||
| 
 | ||||
| 	for (i = 0; i < bio->bi_vcnt; ++i) { | ||||
| 		if (bio->bi_io_vec[i].bv_page == last_page) | ||||
| 			continue; | ||||
| 		last_page = bio->bi_io_vec[i].bv_page; | ||||
| 		__free_page(last_page); | ||||
| 	} | ||||
| 	bio_put(bio); | ||||
| } | ||||
| 
 | ||||
| static noinline_for_stack void scrub_free_dev(struct scrub_dev *sdev) | ||||
| { | ||||
| 	int i; | ||||
| 	int j; | ||||
| 	struct page *last_page; | ||||
| 
 | ||||
| 	if (!sdev) | ||||
| 		return; | ||||
| 
 | ||||
| 	for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) { | ||||
| 		struct scrub_bio *sbio = sdev->bios[i]; | ||||
| 		struct bio *bio; | ||||
| 
 | ||||
| 		if (!sbio) | ||||
| 			break; | ||||
| 
 | ||||
| 		bio = sbio->bio; | ||||
| 		if (bio) { | ||||
| 			last_page = NULL; | ||||
| 			for (j = 0; j < bio->bi_vcnt; ++j) { | ||||
| 				if (bio->bi_io_vec[j].bv_page == last_page) | ||||
| 					continue; | ||||
| 				last_page = bio->bi_io_vec[j].bv_page; | ||||
| 				__free_page(last_page); | ||||
| 			} | ||||
| 			bio_put(bio); | ||||
| 		} | ||||
| 		scrub_free_bio(sbio->bio); | ||||
| 		kfree(sbio); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -156,8 +160,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) | |||
| { | ||||
| 	struct scrub_dev *sdev; | ||||
| 	int		i; | ||||
| 	int		j; | ||||
| 	int		ret; | ||||
| 	struct btrfs_fs_info *fs_info = dev->dev_root->fs_info; | ||||
| 
 | ||||
| 	sdev = kzalloc(sizeof(*sdev), GFP_NOFS); | ||||
|  | @ -165,7 +167,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) | |||
| 		goto nomem; | ||||
| 	sdev->dev = dev; | ||||
| 	for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) { | ||||
| 		struct bio *bio; | ||||
| 		struct scrub_bio *sbio; | ||||
| 
 | ||||
| 		sbio = kzalloc(sizeof(*sbio), GFP_NOFS); | ||||
|  | @ -173,32 +174,10 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev) | |||
| 			goto nomem; | ||||
| 		sdev->bios[i] = sbio; | ||||
| 
 | ||||
| 		bio = bio_kmalloc(GFP_NOFS, SCRUB_PAGES_PER_BIO); | ||||
| 		if (!bio) | ||||
| 			goto nomem; | ||||
| 
 | ||||
| 		sbio->index = i; | ||||
| 		sbio->sdev = sdev; | ||||
| 		sbio->bio = bio; | ||||
| 		sbio->count = 0; | ||||
| 		sbio->work.func = scrub_checksum; | ||||
| 		bio->bi_private = sdev->bios[i]; | ||||
| 		bio->bi_end_io = scrub_bio_end_io; | ||||
| 		bio->bi_sector = 0; | ||||
| 		bio->bi_bdev = dev->bdev; | ||||
| 		bio->bi_size = 0; | ||||
| 
 | ||||
| 		for (j = 0; j < SCRUB_PAGES_PER_BIO; ++j) { | ||||
| 			struct page *page; | ||||
| 			page = alloc_page(GFP_NOFS); | ||||
| 			if (!page) | ||||
| 				goto nomem; | ||||
| 
 | ||||
| 			ret = bio_add_page(bio, page, PAGE_SIZE, 0); | ||||
| 			if (!ret) | ||||
| 				goto nomem; | ||||
| 		} | ||||
| 		WARN_ON(bio->bi_vcnt != SCRUB_PAGES_PER_BIO); | ||||
| 
 | ||||
| 		if (i != SCRUB_BIOS_PER_DEV-1) | ||||
| 			sdev->bios[i]->next_free = i + 1; | ||||
|  | @ -369,9 +348,6 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector, | |||
| 	int ret; | ||||
| 	DECLARE_COMPLETION_ONSTACK(complete); | ||||
| 
 | ||||
| 	/* we are going to wait on this IO */ | ||||
| 	rw |= REQ_SYNC; | ||||
| 
 | ||||
| 	bio = bio_alloc(GFP_NOFS, 1); | ||||
| 	bio->bi_bdev = bdev; | ||||
| 	bio->bi_sector = sector; | ||||
|  | @ -380,6 +356,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector, | |||
| 	bio->bi_private = &complete; | ||||
| 	submit_bio(rw, bio); | ||||
| 
 | ||||
| 	/* this will also unplug the queue */ | ||||
| 	wait_for_completion(&complete); | ||||
| 
 | ||||
| 	ret = !test_bit(BIO_UPTODATE, &bio->bi_flags); | ||||
|  | @ -394,6 +371,7 @@ static void scrub_bio_end_io(struct bio *bio, int err) | |||
| 	struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info; | ||||
| 
 | ||||
| 	sbio->err = err; | ||||
| 	sbio->bio = bio; | ||||
| 
 | ||||
| 	btrfs_queue_worker(&fs_info->scrub_workers, &sbio->work); | ||||
| } | ||||
|  | @ -453,6 +431,8 @@ static void scrub_checksum(struct btrfs_work *work) | |||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	scrub_free_bio(sbio->bio); | ||||
| 	sbio->bio = NULL; | ||||
| 	spin_lock(&sdev->list_lock); | ||||
| 	sbio->next_free = sdev->first_free; | ||||
| 	sdev->first_free = sbio->index; | ||||
|  | @ -583,25 +563,50 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer) | |||
| static int scrub_submit(struct scrub_dev *sdev) | ||||
| { | ||||
| 	struct scrub_bio *sbio; | ||||
| 	struct bio *bio; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (sdev->curr == -1) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	sbio = sdev->bios[sdev->curr]; | ||||
| 
 | ||||
| 	sbio->bio->bi_sector = sbio->physical >> 9; | ||||
| 	sbio->bio->bi_size = sbio->count * PAGE_SIZE; | ||||
| 	sbio->bio->bi_next = NULL; | ||||
| 	sbio->bio->bi_flags |= 1 << BIO_UPTODATE; | ||||
| 	sbio->bio->bi_comp_cpu = -1; | ||||
| 	sbio->bio->bi_bdev = sdev->dev->bdev; | ||||
| 	bio = bio_alloc(GFP_NOFS, sbio->count); | ||||
| 	if (!bio) | ||||
| 		goto nomem; | ||||
| 
 | ||||
| 	bio->bi_private = sbio; | ||||
| 	bio->bi_end_io = scrub_bio_end_io; | ||||
| 	bio->bi_bdev = sdev->dev->bdev; | ||||
| 	bio->bi_sector = sbio->physical >> 9; | ||||
| 
 | ||||
| 	for (i = 0; i < sbio->count; ++i) { | ||||
| 		struct page *page; | ||||
| 		int ret; | ||||
| 
 | ||||
| 		page = alloc_page(GFP_NOFS); | ||||
| 		if (!page) | ||||
| 			goto nomem; | ||||
| 
 | ||||
| 		ret = bio_add_page(bio, page, PAGE_SIZE, 0); | ||||
| 		if (!ret) { | ||||
| 			__free_page(page); | ||||
| 			goto nomem; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	sbio->err = 0; | ||||
| 	sdev->curr = -1; | ||||
| 	atomic_inc(&sdev->in_flight); | ||||
| 
 | ||||
| 	submit_bio(0, sbio->bio); | ||||
| 	submit_bio(READ, bio); | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| nomem: | ||||
| 	scrub_free_bio(bio); | ||||
| 
 | ||||
| 	return -ENOMEM; | ||||
| } | ||||
| 
 | ||||
| static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, | ||||
|  | @ -633,7 +638,11 @@ again: | |||
| 		sbio->logical = logical; | ||||
| 	} else if (sbio->physical + sbio->count * PAGE_SIZE != physical || | ||||
| 		   sbio->logical + sbio->count * PAGE_SIZE != logical) { | ||||
| 		scrub_submit(sdev); | ||||
| 		int ret; | ||||
| 
 | ||||
| 		ret = scrub_submit(sdev); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		goto again; | ||||
| 	} | ||||
| 	sbio->spag[sbio->count].flags = flags; | ||||
|  | @ -645,8 +654,13 @@ again: | |||
| 		memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); | ||||
| 	} | ||||
| 	++sbio->count; | ||||
| 	if (sbio->count == SCRUB_PAGES_PER_BIO || force) | ||||
| 		scrub_submit(sdev); | ||||
| 	if (sbio->count == SCRUB_PAGES_PER_BIO || force) { | ||||
| 		int ret; | ||||
| 
 | ||||
| 		ret = scrub_submit(sdev); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -727,6 +741,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, | |||
| 	struct btrfs_root *root = fs_info->extent_root; | ||||
| 	struct btrfs_root *csum_root = fs_info->csum_root; | ||||
| 	struct btrfs_extent_item *extent; | ||||
| 	struct blk_plug plug; | ||||
| 	u64 flags; | ||||
| 	int ret; | ||||
| 	int slot; | ||||
|  | @ -831,6 +846,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, | |||
| 	 * the scrub. This might currently (crc32) end up to be about 1MB | ||||
| 	 */ | ||||
| 	start_stripe = 0; | ||||
| 	blk_start_plug(&plug); | ||||
| again: | ||||
| 	logical = base + offset + start_stripe * increment; | ||||
| 	for (i = start_stripe; i < nstripes; ++i) { | ||||
|  | @ -972,6 +988,7 @@ next: | |||
| 	scrub_submit(sdev); | ||||
| 
 | ||||
| out: | ||||
| 	blk_finish_plug(&plug); | ||||
| 	btrfs_free_path(path); | ||||
| 	return ret < 0 ? ret : 0; | ||||
| } | ||||
|  | @ -1166,7 +1183,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, | |||
| 	int ret; | ||||
| 	struct btrfs_device *dev; | ||||
| 
 | ||||
| 	if (root->fs_info->closing) | ||||
| 	if (btrfs_fs_closing(root->fs_info)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/*
 | ||||
|  |  | |||
|  | @ -161,7 +161,8 @@ enum { | |||
| 	Opt_compress_type, Opt_compress_force, Opt_compress_force_type, | ||||
| 	Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, | ||||
| 	Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, | ||||
| 	Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_err, | ||||
| 	Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, | ||||
| 	Opt_inode_cache, Opt_err, | ||||
| }; | ||||
| 
 | ||||
| static match_table_t tokens = { | ||||
|  | @ -193,6 +194,7 @@ static match_table_t tokens = { | |||
| 	{Opt_enospc_debug, "enospc_debug"}, | ||||
| 	{Opt_subvolrootid, "subvolrootid=%d"}, | ||||
| 	{Opt_defrag, "autodefrag"}, | ||||
| 	{Opt_inode_cache, "inode_cache"}, | ||||
| 	{Opt_err, NULL}, | ||||
| }; | ||||
| 
 | ||||
|  | @ -361,6 +363,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 			printk(KERN_INFO "btrfs: enabling disk space caching\n"); | ||||
| 			btrfs_set_opt(info->mount_opt, SPACE_CACHE); | ||||
| 			break; | ||||
| 		case Opt_inode_cache: | ||||
| 			printk(KERN_INFO "btrfs: enabling inode map caching\n"); | ||||
| 			btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE); | ||||
| 			break; | ||||
| 		case Opt_clear_cache: | ||||
| 			printk(KERN_INFO "btrfs: force clearing of disk cache\n"); | ||||
| 			btrfs_set_opt(info->mount_opt, CLEAR_CACHE); | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ static noinline void put_transaction(struct btrfs_transaction *transaction) | |||
| { | ||||
| 	WARN_ON(atomic_read(&transaction->use_count) == 0); | ||||
| 	if (atomic_dec_and_test(&transaction->use_count)) { | ||||
| 		BUG_ON(!list_empty(&transaction->list)); | ||||
| 		memset(transaction, 0, sizeof(*transaction)); | ||||
| 		kmem_cache_free(btrfs_transaction_cachep, transaction); | ||||
| 	} | ||||
|  | @ -49,46 +50,72 @@ static noinline void switch_commit_root(struct btrfs_root *root) | |||
| /*
 | ||||
|  * either allocate a new transaction or hop into the existing one | ||||
|  */ | ||||
| static noinline int join_transaction(struct btrfs_root *root) | ||||
| static noinline int join_transaction(struct btrfs_root *root, int nofail) | ||||
| { | ||||
| 	struct btrfs_transaction *cur_trans; | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	if (root->fs_info->trans_no_join) { | ||||
| 		if (!nofail) { | ||||
| 			spin_unlock(&root->fs_info->trans_lock); | ||||
| 			return -EBUSY; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	cur_trans = root->fs_info->running_transaction; | ||||
| 	if (!cur_trans) { | ||||
| 		cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, | ||||
| 					     GFP_NOFS); | ||||
| 		if (!cur_trans) | ||||
| 			return -ENOMEM; | ||||
| 		root->fs_info->generation++; | ||||
| 		atomic_set(&cur_trans->num_writers, 1); | ||||
| 		cur_trans->num_joined = 0; | ||||
| 		cur_trans->transid = root->fs_info->generation; | ||||
| 		init_waitqueue_head(&cur_trans->writer_wait); | ||||
| 		init_waitqueue_head(&cur_trans->commit_wait); | ||||
| 		cur_trans->in_commit = 0; | ||||
| 		cur_trans->blocked = 0; | ||||
| 		atomic_set(&cur_trans->use_count, 1); | ||||
| 		cur_trans->commit_done = 0; | ||||
| 		cur_trans->start_time = get_seconds(); | ||||
| 
 | ||||
| 		cur_trans->delayed_refs.root = RB_ROOT; | ||||
| 		cur_trans->delayed_refs.num_entries = 0; | ||||
| 		cur_trans->delayed_refs.num_heads_ready = 0; | ||||
| 		cur_trans->delayed_refs.num_heads = 0; | ||||
| 		cur_trans->delayed_refs.flushing = 0; | ||||
| 		cur_trans->delayed_refs.run_delayed_start = 0; | ||||
| 		spin_lock_init(&cur_trans->delayed_refs.lock); | ||||
| 
 | ||||
| 		INIT_LIST_HEAD(&cur_trans->pending_snapshots); | ||||
| 		list_add_tail(&cur_trans->list, &root->fs_info->trans_list); | ||||
| 		extent_io_tree_init(&cur_trans->dirty_pages, | ||||
| 				     root->fs_info->btree_inode->i_mapping); | ||||
| 		spin_lock(&root->fs_info->new_trans_lock); | ||||
| 		root->fs_info->running_transaction = cur_trans; | ||||
| 		spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 	} else { | ||||
| 	if (cur_trans) { | ||||
| 		atomic_inc(&cur_trans->use_count); | ||||
| 		atomic_inc(&cur_trans->num_writers); | ||||
| 		cur_trans->num_joined++; | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); | ||||
| 	if (!cur_trans) | ||||
| 		return -ENOMEM; | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	if (root->fs_info->running_transaction) { | ||||
| 		kmem_cache_free(btrfs_transaction_cachep, cur_trans); | ||||
| 		cur_trans = root->fs_info->running_transaction; | ||||
| 		atomic_inc(&cur_trans->use_count); | ||||
| 		atomic_inc(&cur_trans->num_writers); | ||||
| 		cur_trans->num_joined++; | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	atomic_set(&cur_trans->num_writers, 1); | ||||
| 	cur_trans->num_joined = 0; | ||||
| 	init_waitqueue_head(&cur_trans->writer_wait); | ||||
| 	init_waitqueue_head(&cur_trans->commit_wait); | ||||
| 	cur_trans->in_commit = 0; | ||||
| 	cur_trans->blocked = 0; | ||||
| 	/*
 | ||||
| 	 * One for this trans handle, one so it will live on until we | ||||
| 	 * commit the transaction. | ||||
| 	 */ | ||||
| 	atomic_set(&cur_trans->use_count, 2); | ||||
| 	cur_trans->commit_done = 0; | ||||
| 	cur_trans->start_time = get_seconds(); | ||||
| 
 | ||||
| 	cur_trans->delayed_refs.root = RB_ROOT; | ||||
| 	cur_trans->delayed_refs.num_entries = 0; | ||||
| 	cur_trans->delayed_refs.num_heads_ready = 0; | ||||
| 	cur_trans->delayed_refs.num_heads = 0; | ||||
| 	cur_trans->delayed_refs.flushing = 0; | ||||
| 	cur_trans->delayed_refs.run_delayed_start = 0; | ||||
| 	spin_lock_init(&cur_trans->commit_lock); | ||||
| 	spin_lock_init(&cur_trans->delayed_refs.lock); | ||||
| 
 | ||||
| 	INIT_LIST_HEAD(&cur_trans->pending_snapshots); | ||||
| 	list_add_tail(&cur_trans->list, &root->fs_info->trans_list); | ||||
| 	extent_io_tree_init(&cur_trans->dirty_pages, | ||||
| 			     root->fs_info->btree_inode->i_mapping); | ||||
| 	root->fs_info->generation++; | ||||
| 	cur_trans->transid = root->fs_info->generation; | ||||
| 	root->fs_info->running_transaction = cur_trans; | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -99,39 +126,28 @@ static noinline int join_transaction(struct btrfs_root *root) | |||
|  * to make sure the old root from before we joined the transaction is deleted | ||||
|  * when the transaction commits | ||||
|  */ | ||||
| static noinline int record_root_in_trans(struct btrfs_trans_handle *trans, | ||||
| 					 struct btrfs_root *root) | ||||
| int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | ||||
| 			       struct btrfs_root *root) | ||||
| { | ||||
| 	if (root->ref_cows && root->last_trans < trans->transid) { | ||||
| 		WARN_ON(root == root->fs_info->extent_root); | ||||
| 		WARN_ON(root->commit_root != root->node); | ||||
| 
 | ||||
| 		spin_lock(&root->fs_info->fs_roots_radix_lock); | ||||
| 		if (root->last_trans == trans->transid) { | ||||
| 			spin_unlock(&root->fs_info->fs_roots_radix_lock); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		root->last_trans = trans->transid; | ||||
| 		radix_tree_tag_set(&root->fs_info->fs_roots_radix, | ||||
| 			   (unsigned long)root->root_key.objectid, | ||||
| 			   BTRFS_ROOT_TRANS_TAG); | ||||
| 		root->last_trans = trans->transid; | ||||
| 		spin_unlock(&root->fs_info->fs_roots_radix_lock); | ||||
| 		btrfs_init_reloc_root(trans, root); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | ||||
| 			       struct btrfs_root *root) | ||||
| { | ||||
| 	if (!root->ref_cows) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	if (root->last_trans == trans->transid) { | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	record_root_in_trans(trans, root); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* wait for commit against the current transaction to become unblocked
 | ||||
|  * when this is done, it is safe to start a new transaction, but the current | ||||
|  * transaction might not be fully on disk. | ||||
|  | @ -140,21 +156,23 @@ static void wait_current_trans(struct btrfs_root *root) | |||
| { | ||||
| 	struct btrfs_transaction *cur_trans; | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	cur_trans = root->fs_info->running_transaction; | ||||
| 	if (cur_trans && cur_trans->blocked) { | ||||
| 		DEFINE_WAIT(wait); | ||||
| 		atomic_inc(&cur_trans->use_count); | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 		while (1) { | ||||
| 			prepare_to_wait(&root->fs_info->transaction_wait, &wait, | ||||
| 					TASK_UNINTERRUPTIBLE); | ||||
| 			if (!cur_trans->blocked) | ||||
| 				break; | ||||
| 			mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 			schedule(); | ||||
| 			mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		} | ||||
| 		finish_wait(&root->fs_info->transaction_wait, &wait); | ||||
| 		put_transaction(cur_trans); | ||||
| 	} else { | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -167,10 +185,16 @@ enum btrfs_trans_type { | |||
| 
 | ||||
| static int may_wait_transaction(struct btrfs_root *root, int type) | ||||
| { | ||||
| 	if (!root->fs_info->log_root_recovering && | ||||
| 	    ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || | ||||
| 	     type == TRANS_USERSPACE)) | ||||
| 	if (root->fs_info->log_root_recovering) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (type == TRANS_USERSPACE) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if (type == TRANS_START && | ||||
| 	    !atomic_read(&root->fs_info->open_ioctl_trans)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -184,36 +208,44 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
| 
 | ||||
| 	if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | ||||
| 		return ERR_PTR(-EROFS); | ||||
| 
 | ||||
| 	if (current->journal_info) { | ||||
| 		WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK); | ||||
| 		h = current->journal_info; | ||||
| 		h->use_count++; | ||||
| 		h->orig_rsv = h->block_rsv; | ||||
| 		h->block_rsv = NULL; | ||||
| 		goto got_it; | ||||
| 	} | ||||
| again: | ||||
| 	h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | ||||
| 	if (!h) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	if (type != TRANS_JOIN_NOLOCK) | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	if (may_wait_transaction(root, type)) | ||||
| 		wait_current_trans(root); | ||||
| 
 | ||||
| 	ret = join_transaction(root); | ||||
| 	do { | ||||
| 		ret = join_transaction(root, type == TRANS_JOIN_NOLOCK); | ||||
| 		if (ret == -EBUSY) | ||||
| 			wait_current_trans(root); | ||||
| 	} while (ret == -EBUSY); | ||||
| 
 | ||||
| 	if (ret < 0) { | ||||
| 		kmem_cache_free(btrfs_trans_handle_cachep, h); | ||||
| 		if (type != TRANS_JOIN_NOLOCK) | ||||
| 			mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		return ERR_PTR(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	cur_trans = root->fs_info->running_transaction; | ||||
| 	atomic_inc(&cur_trans->use_count); | ||||
| 	if (type != TRANS_JOIN_NOLOCK) | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	h->transid = cur_trans->transid; | ||||
| 	h->transaction = cur_trans; | ||||
| 	h->blocks_used = 0; | ||||
| 	h->block_group = 0; | ||||
| 	h->bytes_reserved = 0; | ||||
| 	h->delayed_ref_updates = 0; | ||||
| 	h->use_count = 1; | ||||
| 	h->block_rsv = NULL; | ||||
| 	h->orig_rsv = NULL; | ||||
| 
 | ||||
| 	smp_mb(); | ||||
| 	if (cur_trans->blocked && may_wait_transaction(root, type)) { | ||||
|  | @ -241,11 +273,8 @@ again: | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (type != TRANS_JOIN_NOLOCK) | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	record_root_in_trans(h, root); | ||||
| 	if (type != TRANS_JOIN_NOLOCK) | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| got_it: | ||||
| 	btrfs_record_root_in_trans(h, root); | ||||
| 
 | ||||
| 	if (!current->journal_info && type != TRANS_USERSPACE) | ||||
| 		current->journal_info = h; | ||||
|  | @ -257,22 +286,19 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | |||
| { | ||||
| 	return start_transaction(root, num_items, TRANS_START); | ||||
| } | ||||
| struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | ||||
| 						   int num_blocks) | ||||
| struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root) | ||||
| { | ||||
| 	return start_transaction(root, 0, TRANS_JOIN); | ||||
| } | ||||
| 
 | ||||
| struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, | ||||
| 							  int num_blocks) | ||||
| struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root) | ||||
| { | ||||
| 	return start_transaction(root, 0, TRANS_JOIN_NOLOCK); | ||||
| } | ||||
| 
 | ||||
| struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | ||||
| 							 int num_blocks) | ||||
| struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root) | ||||
| { | ||||
| 	return start_transaction(r, 0, TRANS_USERSPACE); | ||||
| 	return start_transaction(root, 0, TRANS_USERSPACE); | ||||
| } | ||||
| 
 | ||||
| /* wait for a transaction commit to be fully complete */ | ||||
|  | @ -280,17 +306,13 @@ static noinline int wait_for_commit(struct btrfs_root *root, | |||
| 				    struct btrfs_transaction *commit) | ||||
| { | ||||
| 	DEFINE_WAIT(wait); | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	while (!commit->commit_done) { | ||||
| 		prepare_to_wait(&commit->commit_wait, &wait, | ||||
| 				TASK_UNINTERRUPTIBLE); | ||||
| 		if (commit->commit_done) | ||||
| 			break; | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		schedule(); | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	} | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	finish_wait(&commit->commit_wait, &wait); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -300,59 +322,56 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) | |||
| 	struct btrfs_transaction *cur_trans = NULL, *t; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	ret = 0; | ||||
| 	if (transid) { | ||||
| 		if (transid <= root->fs_info->last_trans_committed) | ||||
| 			goto out_unlock; | ||||
| 			goto out; | ||||
| 
 | ||||
| 		/* find specified transaction */ | ||||
| 		spin_lock(&root->fs_info->trans_lock); | ||||
| 		list_for_each_entry(t, &root->fs_info->trans_list, list) { | ||||
| 			if (t->transid == transid) { | ||||
| 				cur_trans = t; | ||||
| 				atomic_inc(&cur_trans->use_count); | ||||
| 				break; | ||||
| 			} | ||||
| 			if (t->transid > transid) | ||||
| 				break; | ||||
| 		} | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 		ret = -EINVAL; | ||||
| 		if (!cur_trans) | ||||
| 			goto out_unlock;  /* bad transid */ | ||||
| 			goto out;  /* bad transid */ | ||||
| 	} else { | ||||
| 		/* find newest transaction that is committing | committed */ | ||||
| 		spin_lock(&root->fs_info->trans_lock); | ||||
| 		list_for_each_entry_reverse(t, &root->fs_info->trans_list, | ||||
| 					    list) { | ||||
| 			if (t->in_commit) { | ||||
| 				if (t->commit_done) | ||||
| 					goto out_unlock; | ||||
| 					goto out; | ||||
| 				cur_trans = t; | ||||
| 				atomic_inc(&cur_trans->use_count); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 		if (!cur_trans) | ||||
| 			goto out_unlock;  /* nothing committing|committed */ | ||||
| 			goto out;  /* nothing committing|committed */ | ||||
| 	} | ||||
| 
 | ||||
| 	atomic_inc(&cur_trans->use_count); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	wait_for_commit(root, cur_trans); | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	put_transaction(cur_trans); | ||||
| 	ret = 0; | ||||
| out_unlock: | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void btrfs_throttle(struct btrfs_root *root) | ||||
| { | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	if (!root->fs_info->open_ioctl_trans) | ||||
| 	if (!atomic_read(&root->fs_info->open_ioctl_trans)) | ||||
| 		wait_current_trans(root); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| } | ||||
| 
 | ||||
| static int should_end_transaction(struct btrfs_trans_handle *trans, | ||||
|  | @ -370,6 +389,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | |||
| 	struct btrfs_transaction *cur_trans = trans->transaction; | ||||
| 	int updates; | ||||
| 
 | ||||
| 	smp_mb(); | ||||
| 	if (cur_trans->blocked || cur_trans->delayed_refs.flushing) | ||||
| 		return 1; | ||||
| 
 | ||||
|  | @ -388,6 +408,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
| 	struct btrfs_fs_info *info = root->fs_info; | ||||
| 	int count = 0; | ||||
| 
 | ||||
| 	if (--trans->use_count) { | ||||
| 		trans->block_rsv = trans->orig_rsv; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	while (count < 4) { | ||||
| 		unsigned long cur = trans->delayed_ref_updates; | ||||
| 		trans->delayed_ref_updates = 0; | ||||
|  | @ -410,9 +435,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 	btrfs_trans_release_metadata(trans, root); | ||||
| 
 | ||||
| 	if (lock && !root->fs_info->open_ioctl_trans && | ||||
| 	    should_end_transaction(trans, root)) | ||||
| 	if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && | ||||
| 	    should_end_transaction(trans, root)) { | ||||
| 		trans->transaction->blocked = 1; | ||||
| 		smp_wmb(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (lock && cur_trans->blocked && !cur_trans->in_commit) { | ||||
| 		if (throttle) | ||||
|  | @ -703,9 +730,9 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
|  */ | ||||
| int btrfs_add_dead_root(struct btrfs_root *root) | ||||
| { | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	list_add(&root->root_list, &root->fs_info->dead_roots); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -721,6 +748,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 	int ret; | ||||
| 	int err = 0; | ||||
| 
 | ||||
| 	spin_lock(&fs_info->fs_roots_radix_lock); | ||||
| 	while (1) { | ||||
| 		ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix, | ||||
| 						 (void **)gang, 0, | ||||
|  | @ -733,6 +761,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 			radix_tree_tag_clear(&fs_info->fs_roots_radix, | ||||
| 					(unsigned long)root->root_key.objectid, | ||||
| 					BTRFS_ROOT_TRANS_TAG); | ||||
| 			spin_unlock(&fs_info->fs_roots_radix_lock); | ||||
| 
 | ||||
| 			btrfs_free_log(trans, root); | ||||
| 			btrfs_update_reloc_root(trans, root); | ||||
|  | @ -753,10 +782,12 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 			err = btrfs_update_root(trans, fs_info->tree_root, | ||||
| 						&root->root_key, | ||||
| 						&root->root_item); | ||||
| 			spin_lock(&fs_info->fs_roots_radix_lock); | ||||
| 			if (err) | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| 	spin_unlock(&fs_info->fs_roots_radix_lock); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
|  | @ -786,7 +817,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | |||
| 		btrfs_btree_balance_dirty(info->tree_root, nr); | ||||
| 		cond_resched(); | ||||
| 
 | ||||
| 		if (root->fs_info->closing || ret != -EAGAIN) | ||||
| 		if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN) | ||||
| 			break; | ||||
| 	} | ||||
| 	root->defrag_running = 0; | ||||
|  | @ -851,7 +882,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 	parent = dget_parent(dentry); | ||||
| 	parent_inode = parent->d_inode; | ||||
| 	parent_root = BTRFS_I(parent_inode)->root; | ||||
| 	record_root_in_trans(trans, parent_root); | ||||
| 	btrfs_record_root_in_trans(trans, parent_root); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * insert the directory item | ||||
|  | @ -869,7 +900,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 	ret = btrfs_update_inode(trans, parent_root, parent_inode); | ||||
| 	BUG_ON(ret); | ||||
| 
 | ||||
| 	record_root_in_trans(trans, root); | ||||
| 	btrfs_record_root_in_trans(trans, root); | ||||
| 	btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | ||||
| 	memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | ||||
| 	btrfs_check_and_init_root_item(new_root_item); | ||||
|  | @ -967,20 +998,20 @@ static void update_super_roots(struct btrfs_root *root) | |||
| int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	spin_lock(&info->new_trans_lock); | ||||
| 	spin_lock(&info->trans_lock); | ||||
| 	if (info->running_transaction) | ||||
| 		ret = info->running_transaction->in_commit; | ||||
| 	spin_unlock(&info->new_trans_lock); | ||||
| 	spin_unlock(&info->trans_lock); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int btrfs_transaction_blocked(struct btrfs_fs_info *info) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	spin_lock(&info->new_trans_lock); | ||||
| 	spin_lock(&info->trans_lock); | ||||
| 	if (info->running_transaction) | ||||
| 		ret = info->running_transaction->blocked; | ||||
| 	spin_unlock(&info->new_trans_lock); | ||||
| 	spin_unlock(&info->trans_lock); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -1004,9 +1035,7 @@ static void wait_current_trans_commit_start(struct btrfs_root *root, | |||
| 				    &wait); | ||||
| 			break; | ||||
| 		} | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		schedule(); | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		finish_wait(&root->fs_info->transaction_blocked_wait, &wait); | ||||
| 	} | ||||
| } | ||||
|  | @ -1032,9 +1061,7 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root, | |||
| 				    &wait); | ||||
| 			break; | ||||
| 		} | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		schedule(); | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		finish_wait(&root->fs_info->transaction_wait, | ||||
| 			    &wait); | ||||
| 	} | ||||
|  | @ -1072,7 +1099,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 	INIT_DELAYED_WORK(&ac->work, do_async_commit); | ||||
| 	ac->root = root; | ||||
| 	ac->newtrans = btrfs_join_transaction(root, 0); | ||||
| 	ac->newtrans = btrfs_join_transaction(root); | ||||
| 	if (IS_ERR(ac->newtrans)) { | ||||
| 		int err = PTR_ERR(ac->newtrans); | ||||
| 		kfree(ac); | ||||
|  | @ -1080,22 +1107,18 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, | |||
| 	} | ||||
| 
 | ||||
| 	/* take transaction reference */ | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	cur_trans = trans->transaction; | ||||
| 	atomic_inc(&cur_trans->use_count); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	btrfs_end_transaction(trans, root); | ||||
| 	schedule_delayed_work(&ac->work, 0); | ||||
| 
 | ||||
| 	/* wait for transaction to start and unblock */ | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	if (wait_for_unblock) | ||||
| 		wait_current_trans_commit_start_and_unblock(root, cur_trans); | ||||
| 	else | ||||
| 		wait_current_trans_commit_start(root, cur_trans); | ||||
| 	put_transaction(cur_trans); | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -1139,38 +1162,41 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 	ret = btrfs_run_delayed_refs(trans, root, 0); | ||||
| 	BUG_ON(ret); | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 	spin_lock(&cur_trans->commit_lock); | ||||
| 	if (cur_trans->in_commit) { | ||||
| 		spin_unlock(&cur_trans->commit_lock); | ||||
| 		atomic_inc(&cur_trans->use_count); | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 		btrfs_end_transaction(trans, root); | ||||
| 
 | ||||
| 		ret = wait_for_commit(root, cur_trans); | ||||
| 		BUG_ON(ret); | ||||
| 
 | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		put_transaction(cur_trans); | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	trans->transaction->in_commit = 1; | ||||
| 	trans->transaction->blocked = 1; | ||||
| 	spin_unlock(&cur_trans->commit_lock); | ||||
| 	wake_up(&root->fs_info->transaction_blocked_wait); | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	if (cur_trans->list.prev != &root->fs_info->trans_list) { | ||||
| 		prev_trans = list_entry(cur_trans->list.prev, | ||||
| 					struct btrfs_transaction, list); | ||||
| 		if (!prev_trans->commit_done) { | ||||
| 			atomic_inc(&prev_trans->use_count); | ||||
| 			mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 			spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 			wait_for_commit(root, prev_trans); | ||||
| 
 | ||||
| 			mutex_lock(&root->fs_info->trans_mutex); | ||||
| 			put_transaction(prev_trans); | ||||
| 		} else { | ||||
| 			spin_unlock(&root->fs_info->trans_lock); | ||||
| 		} | ||||
| 	} else { | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (now < cur_trans->start_time || now - cur_trans->start_time < 1) | ||||
|  | @ -1178,12 +1204,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 	do { | ||||
| 		int snap_pending = 0; | ||||
| 
 | ||||
| 		joined = cur_trans->num_joined; | ||||
| 		if (!list_empty(&trans->transaction->pending_snapshots)) | ||||
| 			snap_pending = 1; | ||||
| 
 | ||||
| 		WARN_ON(cur_trans != trans->transaction); | ||||
| 		mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 		if (flush_on_commit || snap_pending) { | ||||
| 			btrfs_start_delalloc_inodes(root, 1); | ||||
|  | @ -1206,14 +1232,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 		prepare_to_wait(&cur_trans->writer_wait, &wait, | ||||
| 				TASK_UNINTERRUPTIBLE); | ||||
| 
 | ||||
| 		smp_mb(); | ||||
| 		if (atomic_read(&cur_trans->num_writers) > 1) | ||||
| 			schedule_timeout(MAX_SCHEDULE_TIMEOUT); | ||||
| 		else if (should_grow) | ||||
| 			schedule_timeout(1); | ||||
| 
 | ||||
| 		mutex_lock(&root->fs_info->trans_mutex); | ||||
| 		finish_wait(&cur_trans->writer_wait, &wait); | ||||
| 		spin_lock(&root->fs_info->trans_lock); | ||||
| 		root->fs_info->trans_no_join = 1; | ||||
| 		spin_unlock(&root->fs_info->trans_lock); | ||||
| 	} while (atomic_read(&cur_trans->num_writers) > 1 || | ||||
| 		 (should_grow && cur_trans->num_joined != joined)); | ||||
| 
 | ||||
|  | @ -1258,9 +1285,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 	btrfs_prepare_extent_commit(trans, root); | ||||
| 
 | ||||
| 	cur_trans = root->fs_info->running_transaction; | ||||
| 	spin_lock(&root->fs_info->new_trans_lock); | ||||
| 	root->fs_info->running_transaction = NULL; | ||||
| 	spin_unlock(&root->fs_info->new_trans_lock); | ||||
| 
 | ||||
| 	btrfs_set_root_node(&root->fs_info->tree_root->root_item, | ||||
| 			    root->fs_info->tree_root->node); | ||||
|  | @ -1281,10 +1305,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 	       sizeof(root->fs_info->super_copy)); | ||||
| 
 | ||||
| 	trans->transaction->blocked = 0; | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	root->fs_info->running_transaction = NULL; | ||||
| 	root->fs_info->trans_no_join = 0; | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	wake_up(&root->fs_info->transaction_wait); | ||||
| 
 | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 	ret = btrfs_write_and_wait_transaction(trans, root); | ||||
| 	BUG_ON(ret); | ||||
| 	write_ctree_super(trans, root, 0); | ||||
|  | @ -1297,22 +1324,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 	btrfs_finish_extent_commit(trans, root); | ||||
| 
 | ||||
| 	mutex_lock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	cur_trans->commit_done = 1; | ||||
| 
 | ||||
| 	root->fs_info->last_trans_committed = cur_trans->transid; | ||||
| 
 | ||||
| 	wake_up(&cur_trans->commit_wait); | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->trans_lock); | ||||
| 	list_del_init(&cur_trans->list); | ||||
| 	spin_unlock(&root->fs_info->trans_lock); | ||||
| 
 | ||||
| 	put_transaction(cur_trans); | ||||
| 	put_transaction(cur_trans); | ||||
| 
 | ||||
| 	trace_btrfs_transaction_commit(root); | ||||
| 
 | ||||
| 	mutex_unlock(&root->fs_info->trans_mutex); | ||||
| 
 | ||||
| 	btrfs_scrub_continue(root); | ||||
| 
 | ||||
| 	if (current->journal_info == trans) | ||||
|  | @ -1334,9 +1360,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) | |||
| 	LIST_HEAD(list); | ||||
| 	struct btrfs_fs_info *fs_info = root->fs_info; | ||||
| 
 | ||||
| 	mutex_lock(&fs_info->trans_mutex); | ||||
| 	spin_lock(&fs_info->trans_lock); | ||||
| 	list_splice_init(&fs_info->dead_roots, &list); | ||||
| 	mutex_unlock(&fs_info->trans_mutex); | ||||
| 	spin_unlock(&fs_info->trans_lock); | ||||
| 
 | ||||
| 	while (!list_empty(&list)) { | ||||
| 		root = list_entry(list.next, struct btrfs_root, root_list); | ||||
|  |  | |||
|  | @ -28,10 +28,12 @@ struct btrfs_transaction { | |||
| 	 * transaction can end | ||||
| 	 */ | ||||
| 	atomic_t num_writers; | ||||
| 	atomic_t use_count; | ||||
| 
 | ||||
| 	unsigned long num_joined; | ||||
| 
 | ||||
| 	spinlock_t commit_lock; | ||||
| 	int in_commit; | ||||
| 	atomic_t use_count; | ||||
| 	int commit_done; | ||||
| 	int blocked; | ||||
| 	struct list_head list; | ||||
|  | @ -45,13 +47,14 @@ struct btrfs_transaction { | |||
| 
 | ||||
| struct btrfs_trans_handle { | ||||
| 	u64 transid; | ||||
| 	u64 block_group; | ||||
| 	u64 bytes_reserved; | ||||
| 	unsigned long use_count; | ||||
| 	unsigned long blocks_reserved; | ||||
| 	unsigned long blocks_used; | ||||
| 	unsigned long delayed_ref_updates; | ||||
| 	struct btrfs_transaction *transaction; | ||||
| 	struct btrfs_block_rsv *block_rsv; | ||||
| 	struct btrfs_block_rsv *orig_rsv; | ||||
| }; | ||||
| 
 | ||||
| struct btrfs_pending_snapshot { | ||||
|  | @ -66,19 +69,6 @@ struct btrfs_pending_snapshot { | |||
| 	struct list_head list; | ||||
| }; | ||||
| 
 | ||||
| static inline void btrfs_set_trans_block_group(struct btrfs_trans_handle *trans, | ||||
| 					       struct inode *inode) | ||||
| { | ||||
| 	trans->block_group = BTRFS_I(inode)->block_group; | ||||
| } | ||||
| 
 | ||||
| static inline void btrfs_update_inode_block_group( | ||||
| 					  struct btrfs_trans_handle *trans, | ||||
| 					  struct inode *inode) | ||||
| { | ||||
| 	BTRFS_I(inode)->block_group = trans->block_group; | ||||
| } | ||||
| 
 | ||||
| static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans, | ||||
| 					      struct inode *inode) | ||||
| { | ||||
|  | @ -92,12 +82,9 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans, | |||
| 				 struct btrfs_root *root); | ||||
| struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | ||||
| 						   int num_items); | ||||
| struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | ||||
| 						  int num_blocks); | ||||
| struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, | ||||
| 							  int num_blocks); | ||||
| struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | ||||
| 							 int num_blocks); | ||||
| struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root); | ||||
| struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root); | ||||
| struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root); | ||||
| int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid); | ||||
| int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | ||||
| 				     struct btrfs_root *root); | ||||
|  |  | |||
|  | @ -504,7 +504,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) | |||
| 		BUG_ON(!new_device); | ||||
| 		memcpy(new_device, device, sizeof(*new_device)); | ||||
| 		new_device->name = kstrdup(device->name, GFP_NOFS); | ||||
| 		BUG_ON(!new_device->name); | ||||
| 		BUG_ON(device->name && !new_device->name); | ||||
| 		new_device->bdev = NULL; | ||||
| 		new_device->writeable = 0; | ||||
| 		new_device->in_fs_metadata = 0; | ||||
|  |  | |||
|  | @ -158,8 +158,6 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, | |||
| 	if (IS_ERR(trans)) | ||||
| 		return PTR_ERR(trans); | ||||
| 
 | ||||
| 	btrfs_set_trans_block_group(trans, inode); | ||||
| 
 | ||||
| 	ret = do_setxattr(trans, inode, name, value, size, flags); | ||||
| 	if (ret) | ||||
| 		goto out; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds