diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 11:59:37 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 14:20:42 +0200 | 
| commit | dbb6be6d5e974c42bbecd183effaa0df69e1dd8b (patch) | |
| tree | 5735cb47e70853d057a9881dd0ce44b83e88fa63 /fs/btrfs/extent-tree.c | |
| parent | 6a867a395558a7f882d041783e4cdea6744ca2bf (diff) | |
| parent | b57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff) | |
| download | olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.tar.xz olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.zip  | |
Merge branch 'linus' into timers/core
Reason: Further posix_cpu_timer patches depend on mainline changes
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 55 | 
1 files changed, 37 insertions, 18 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 559f72489b3..b34d32fdaae 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -22,6 +22,7 @@  #include <linux/sort.h>  #include <linux/rcupdate.h>  #include <linux/kthread.h> +#include <linux/slab.h>  #include "compat.h"  #include "hash.h"  #include "ctree.h" @@ -2676,6 +2677,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,  	INIT_LIST_HEAD(&found->block_groups);  	init_rwsem(&found->groups_sem); +	init_waitqueue_head(&found->flush_wait); +	init_waitqueue_head(&found->allocate_wait);  	spin_lock_init(&found->lock);  	found->flags = flags;  	found->total_bytes = total_bytes; @@ -2846,7 +2849,7 @@ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,  	}  	spin_unlock(&BTRFS_I(inode)->accounting_lock); -	BTRFS_I(inode)->reserved_extents--; +	BTRFS_I(inode)->reserved_extents -= num_items;  	BUG_ON(BTRFS_I(inode)->reserved_extents < 0);  	if (meta_sinfo->bytes_delalloc < num_bytes) { @@ -2944,12 +2947,10 @@ static void flush_delalloc(struct btrfs_root *root,  	spin_lock(&info->lock); -	if (!info->flushing) { +	if (!info->flushing)  		info->flushing = 1; -		init_waitqueue_head(&info->flush_wait); -	} else { +	else  		wait = true; -	}  	spin_unlock(&info->lock); @@ -3011,7 +3012,6 @@ static int maybe_allocate_chunk(struct btrfs_root *root,  	if (!info->allocating_chunk) {  		info->force_alloc = 1;  		info->allocating_chunk = 1; -		init_waitqueue_head(&info->allocate_wait);  	} else {  		wait = true;  	} @@ -3111,7 +3111,7 @@ again:  		return -ENOSPC;  	} -	BTRFS_I(inode)->reserved_extents++; +	BTRFS_I(inode)->reserved_extents += num_items;  	check_force_delalloc(meta_sinfo);  	spin_unlock(&meta_sinfo->lock); @@ -3235,7 +3235,8 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,  				u64 bytes)  {  	struct btrfs_space_info *data_sinfo; -	int ret = 0, committed = 0; +	u64 used; +	int ret = 0, committed = 0, flushed = 0;  	/* make sure bytes are sectorsize aligned */  	bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); @@ -3247,12 +3248,21 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,  again:  	/* make sure we have enough space to handle the data first */  	spin_lock(&data_sinfo->lock); -	if (data_sinfo->total_bytes - data_sinfo->bytes_used - -	    data_sinfo->bytes_delalloc - data_sinfo->bytes_reserved - -	    data_sinfo->bytes_pinned - data_sinfo->bytes_readonly - -	    data_sinfo->bytes_may_use - data_sinfo->bytes_super < bytes) { +	used = data_sinfo->bytes_used + data_sinfo->bytes_delalloc + +		data_sinfo->bytes_reserved + data_sinfo->bytes_pinned + +		data_sinfo->bytes_readonly + data_sinfo->bytes_may_use + +		data_sinfo->bytes_super; + +	if (used + bytes > data_sinfo->total_bytes) {  		struct btrfs_trans_handle *trans; +		if (!flushed) { +			spin_unlock(&data_sinfo->lock); +			flush_delalloc(root, data_sinfo); +			flushed = 1; +			goto again; +		} +  		/*  		 * if we don't have enough free bytes in this space then we need  		 * to alloc a new chunk. @@ -4170,6 +4180,10 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,  	ins->offset = 0;  	space_info = __find_space_info(root->fs_info, data); +	if (!space_info) { +		printk(KERN_ERR "No space info for %d\n", data); +		return -ENOSPC; +	}  	if (orig_root->ref_cows || empty_size)  		allowed_chunk_alloc = 1; @@ -5205,6 +5219,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,  	next = btrfs_find_tree_block(root, bytenr, blocksize);  	if (!next) {  		next = btrfs_find_create_tree_block(root, bytenr, blocksize); +		if (!next) +			return -ENOMEM;  		reada = 1;  	}  	btrfs_tree_lock(next); @@ -5417,7 +5433,8 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,  		if (ret > 0) {  			path->slots[level]++;  			continue; -		} +		} else if (ret < 0) +			return ret;  		level = wc->level;  	}  	return 0; @@ -6561,6 +6578,7 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root,  	struct btrfs_key key;  	struct inode *inode = NULL;  	struct btrfs_file_extent_item *fi; +	struct extent_state *cached_state = NULL;  	u64 num_bytes;  	u64 skip_objectid = 0;  	u32 nritems; @@ -6589,12 +6607,14 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root,  		}  		num_bytes = btrfs_file_extent_num_bytes(leaf, fi); -		lock_extent(&BTRFS_I(inode)->io_tree, key.offset, -			    key.offset + num_bytes - 1, GFP_NOFS); +		lock_extent_bits(&BTRFS_I(inode)->io_tree, key.offset, +				 key.offset + num_bytes - 1, 0, &cached_state, +				 GFP_NOFS);  		btrfs_drop_extent_cache(inode, key.offset,  					key.offset + num_bytes - 1, 1); -		unlock_extent(&BTRFS_I(inode)->io_tree, key.offset, -			      key.offset + num_bytes - 1, GFP_NOFS); +		unlock_extent_cached(&BTRFS_I(inode)->io_tree, key.offset, +				     key.offset + num_bytes - 1, &cached_state, +				     GFP_NOFS);  		cond_resched();  	}  	iput(inode); @@ -7366,7 +7386,6 @@ static int find_first_block_group(struct btrfs_root *root,  		}  		path->slots[0]++;  	} -	ret = -ENOENT;  out:  	return ret;  }  |