mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Btrfs: Add a write ahead tree log to optimize synchronous operations
File syncs and directory syncs are optimized by copying their items into a special (copy-on-write) log tree. There is one log tree per subvolume and the btrfs super block points to a tree of log tree roots. After a crash, items are copied out of the log tree and back into the subvolume. See tree-log.c for all the details. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
		
							parent
							
								
									a1b32a5932
								
							
						
					
					
						commit
						e02119d5a7
					
				
					 17 changed files with 3408 additions and 205 deletions
				
			
		| 
						 | 
					@ -7,8 +7,7 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
 | 
				
			||||||
	   transaction.o bit-radix.o inode.o file.o tree-defrag.o \
 | 
						   transaction.o bit-radix.o inode.o file.o tree-defrag.o \
 | 
				
			||||||
	   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
 | 
						   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
 | 
				
			||||||
	   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
 | 
						   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
 | 
				
			||||||
	   ref-cache.o acl.o export.o
 | 
						   ref-cache.o export.o tree-log.o acl.o
 | 
				
			||||||
 | 
					 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Normal Makefile
 | 
					# Normal Makefile
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ struct btrfs_inode {
 | 
				
			||||||
	struct extent_io_tree io_failure_tree;
 | 
						struct extent_io_tree io_failure_tree;
 | 
				
			||||||
	struct mutex csum_mutex;
 | 
						struct mutex csum_mutex;
 | 
				
			||||||
	struct mutex extent_mutex;
 | 
						struct mutex extent_mutex;
 | 
				
			||||||
 | 
						struct mutex log_mutex;
 | 
				
			||||||
	struct inode vfs_inode;
 | 
						struct inode vfs_inode;
 | 
				
			||||||
	struct btrfs_ordered_inode_tree ordered_tree;
 | 
						struct btrfs_ordered_inode_tree ordered_tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,10 +45,17 @@ struct btrfs_inode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct list_head delalloc_inodes;
 | 
						struct list_head delalloc_inodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* full 64 bit generation number */
 | 
				
			||||||
 | 
						u64 generation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * transid of the trans_handle that last modified this inode
 | 
						 * transid of the trans_handle that last modified this inode
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	u64 last_trans;
 | 
						u64 last_trans;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * transid that last logged this inode
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						u64 logged_trans;
 | 
				
			||||||
	u64 delalloc_bytes;
 | 
						u64 delalloc_bytes;
 | 
				
			||||||
	u64 disk_i_size;
 | 
						u64 disk_i_size;
 | 
				
			||||||
	u32 flags;
 | 
						u32 flags;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,21 @@ static inline struct dentry *d_obtain_alias(struct inode *inode)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
 | 
				
			||||||
 | 
					static inline void btrfs_drop_nlink(struct inode *inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						inode->i_nlink--;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void btrfs_inc_nlink(struct inode *inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						inode->i_nlink++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define btrfs_drop_nlink(inode) drop_nlink(inode)
 | 
				
			||||||
 | 
					# define btrfs_inc_nlink(inode)	inc_nlink(inode)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Even if AppArmor isn't enabled, it still has different prototypes.
 | 
					 * Even if AppArmor isn't enabled, it still has different prototypes.
 | 
				
			||||||
 * Add more distro/version pairs here to declare which has AppArmor applied.
 | 
					 * Add more distro/version pairs here to declare which has AppArmor applied.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ void btrfs_free_path(struct btrfs_path *p)
 | 
				
			||||||
	kmem_cache_free(btrfs_path_cachep, p);
 | 
						kmem_cache_free(btrfs_path_cachep, p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
 | 
					void noinline btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
					int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			     struct btrfs_root *root,
 | 
								     struct btrfs_root *root,
 | 
				
			||||||
			     struct extent_buffer *buf,
 | 
								     struct extent_buffer *buf,
 | 
				
			||||||
			     struct extent_buffer *parent, int parent_slot,
 | 
								     struct extent_buffer *parent, int parent_slot,
 | 
				
			||||||
| 
						 | 
					@ -294,7 +294,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
					int noinline btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		    struct btrfs_root *root, struct extent_buffer *buf,
 | 
							    struct btrfs_root *root, struct extent_buffer *buf,
 | 
				
			||||||
		    struct extent_buffer *parent, int parent_slot,
 | 
							    struct extent_buffer *parent, int parent_slot,
 | 
				
			||||||
		    struct extent_buffer **cow_ret, u64 prealloc_dest)
 | 
							    struct extent_buffer **cow_ret, u64 prealloc_dest)
 | 
				
			||||||
| 
						 | 
					@ -677,7 +677,8 @@ static int noinline check_block(struct btrfs_root *root,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * slot may point to max if the key is bigger than all of the keys
 | 
					 * slot may point to max if the key is bigger than all of the keys
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
 | 
					static noinline int generic_bin_search(struct extent_buffer *eb,
 | 
				
			||||||
 | 
									       unsigned long p,
 | 
				
			||||||
				       int item_size, struct btrfs_key *key,
 | 
									       int item_size, struct btrfs_key *key,
 | 
				
			||||||
				       int max, int *slot)
 | 
									       int max, int *slot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -765,7 +766,7 @@ static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct extent_buffer *read_node_slot(struct btrfs_root *root,
 | 
					static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
 | 
				
			||||||
				   struct extent_buffer *parent, int slot)
 | 
									   struct extent_buffer *parent, int slot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int level = btrfs_header_level(parent);
 | 
						int level = btrfs_header_level(parent);
 | 
				
			||||||
| 
						 | 
					@ -781,7 +782,7 @@ static struct extent_buffer *read_node_slot(struct btrfs_root *root,
 | 
				
			||||||
		       btrfs_node_ptr_generation(parent, slot));
 | 
							       btrfs_node_ptr_generation(parent, slot));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int balance_level(struct btrfs_trans_handle *trans,
 | 
					static noinline int balance_level(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			 struct btrfs_root *root,
 | 
								 struct btrfs_root *root,
 | 
				
			||||||
			 struct btrfs_path *path, int level)
 | 
								 struct btrfs_path *path, int level)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1128,7 +1129,8 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans,
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * readahead one full node of leaves
 | 
					 * readahead one full node of leaves
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
 | 
					static noinline void reada_for_search(struct btrfs_root *root,
 | 
				
			||||||
 | 
									      struct btrfs_path *path,
 | 
				
			||||||
				      int level, int slot, u64 objectid)
 | 
									      int level, int slot, u64 objectid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct extent_buffer *node;
 | 
						struct extent_buffer *node;
 | 
				
			||||||
| 
						 | 
					@ -1201,7 +1203,8 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock)
 | 
					static noinline void unlock_up(struct btrfs_path *path, int level,
 | 
				
			||||||
 | 
								       int lowest_unlock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	int skip_level = level;
 | 
						int skip_level = level;
 | 
				
			||||||
| 
						 | 
					@ -1759,8 +1762,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * returns 0 on success and < 0 on failure
 | 
					 * returns 0 on success and < 0 on failure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
					static noinline int split_node(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		      *root, struct btrfs_path *path, int level)
 | 
								       struct btrfs_root *root,
 | 
				
			||||||
 | 
								       struct btrfs_path *path, int level)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 root_gen;
 | 
						u64 root_gen;
 | 
				
			||||||
	struct extent_buffer *c;
 | 
						struct extent_buffer *c;
 | 
				
			||||||
| 
						 | 
					@ -1874,7 +1878,8 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr)
 | 
				
			||||||
 * the start of the leaf data.  IOW, how much room
 | 
					 * the start of the leaf data.  IOW, how much room
 | 
				
			||||||
 * the leaf has left for both items and data
 | 
					 * the leaf has left for both items and data
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf)
 | 
					int noinline btrfs_leaf_free_space(struct btrfs_root *root,
 | 
				
			||||||
 | 
									   struct extent_buffer *leaf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int nritems = btrfs_header_nritems(leaf);
 | 
						int nritems = btrfs_header_nritems(leaf);
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -2283,9 +2288,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * returns 0 if all went well and < 0 on failure.
 | 
					 * returns 0 if all went well and < 0 on failure.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
					static noinline int split_leaf(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		      *root, struct btrfs_key *ins_key,
 | 
								       struct btrfs_root *root,
 | 
				
			||||||
		      struct btrfs_path *path, int data_size, int extend)
 | 
								       struct btrfs_key *ins_key,
 | 
				
			||||||
 | 
								       struct btrfs_path *path, int data_size,
 | 
				
			||||||
 | 
								       int extend)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 root_gen;
 | 
						u64 root_gen;
 | 
				
			||||||
	struct extent_buffer *l;
 | 
						struct extent_buffer *l;
 | 
				
			||||||
| 
						 | 
					@ -3079,6 +3086,7 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
 | 
				
			||||||
 * was nothing in the tree that matched the search criteria.
 | 
					 * was nothing in the tree that matched the search criteria.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
					int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
 | 
								 struct btrfs_key *max_key,
 | 
				
			||||||
			 struct btrfs_path *path, int cache_only,
 | 
								 struct btrfs_path *path, int cache_only,
 | 
				
			||||||
			 u64 min_trans)
 | 
								 u64 min_trans)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -3093,6 +3101,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
again:
 | 
					again:
 | 
				
			||||||
	cur = btrfs_lock_root_node(root);
 | 
						cur = btrfs_lock_root_node(root);
 | 
				
			||||||
	level = btrfs_header_level(cur);
 | 
						level = btrfs_header_level(cur);
 | 
				
			||||||
 | 
						WARN_ON(path->nodes[level]);
 | 
				
			||||||
	path->nodes[level] = cur;
 | 
						path->nodes[level] = cur;
 | 
				
			||||||
	path->locks[level] = 1;
 | 
						path->locks[level] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3107,6 +3116,8 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* at level = 0, we're done, setup the path and exit */
 | 
							/* at level = 0, we're done, setup the path and exit */
 | 
				
			||||||
		if (level == 0) {
 | 
							if (level == 0) {
 | 
				
			||||||
 | 
								if (slot >= nritems)
 | 
				
			||||||
 | 
									goto find_next_key;
 | 
				
			||||||
			ret = 0;
 | 
								ret = 0;
 | 
				
			||||||
			path->slots[level] = slot;
 | 
								path->slots[level] = slot;
 | 
				
			||||||
			btrfs_item_key_to_cpu(cur, &found_key, slot);
 | 
								btrfs_item_key_to_cpu(cur, &found_key, slot);
 | 
				
			||||||
| 
						 | 
					@ -3123,6 +3134,8 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
			u64 blockptr;
 | 
								u64 blockptr;
 | 
				
			||||||
			u64 gen;
 | 
								u64 gen;
 | 
				
			||||||
			struct extent_buffer *tmp;
 | 
								struct extent_buffer *tmp;
 | 
				
			||||||
 | 
								struct btrfs_disk_key disk_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			blockptr = btrfs_node_blockptr(cur, slot);
 | 
								blockptr = btrfs_node_blockptr(cur, slot);
 | 
				
			||||||
			gen = btrfs_node_ptr_generation(cur, slot);
 | 
								gen = btrfs_node_ptr_generation(cur, slot);
 | 
				
			||||||
			if (gen < min_trans) {
 | 
								if (gen < min_trans) {
 | 
				
			||||||
| 
						 | 
					@ -3132,6 +3145,14 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
			if (!cache_only)
 | 
								if (!cache_only)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (max_key) {
 | 
				
			||||||
 | 
									btrfs_node_key(cur, &disk_key, slot);
 | 
				
			||||||
 | 
									if (comp_keys(&disk_key, max_key) >= 0) {
 | 
				
			||||||
 | 
										ret = 1;
 | 
				
			||||||
 | 
										goto out;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			tmp = btrfs_find_tree_block(root, blockptr,
 | 
								tmp = btrfs_find_tree_block(root, blockptr,
 | 
				
			||||||
					    btrfs_level_size(root, level - 1));
 | 
										    btrfs_level_size(root, level - 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3143,14 +3164,16 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
				free_extent_buffer(tmp);
 | 
									free_extent_buffer(tmp);
 | 
				
			||||||
			slot++;
 | 
								slot++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					find_next_key:
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * we didn't find a candidate key in this node, walk forward
 | 
							 * we didn't find a candidate key in this node, walk forward
 | 
				
			||||||
		 * and find another one
 | 
							 * and find another one
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (slot >= nritems) {
 | 
							if (slot >= nritems) {
 | 
				
			||||||
			ret = btrfs_find_next_key(root, path, min_key, level,
 | 
								path->slots[level] = slot;
 | 
				
			||||||
 | 
								sret = btrfs_find_next_key(root, path, min_key, level,
 | 
				
			||||||
						  cache_only, min_trans);
 | 
											  cache_only, min_trans);
 | 
				
			||||||
			if (ret == 0) {
 | 
								if (sret == 0) {
 | 
				
			||||||
				btrfs_release_path(root, path);
 | 
									btrfs_release_path(root, path);
 | 
				
			||||||
				goto again;
 | 
									goto again;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
| 
						 | 
					@ -3351,6 +3374,7 @@ int btrfs_previous_item(struct btrfs_root *root,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_key found_key;
 | 
						struct btrfs_key found_key;
 | 
				
			||||||
	struct extent_buffer *leaf;
 | 
						struct extent_buffer *leaf;
 | 
				
			||||||
 | 
						u32 nritems;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while(1) {
 | 
						while(1) {
 | 
				
			||||||
| 
						 | 
					@ -3362,9 +3386,20 @@ int btrfs_previous_item(struct btrfs_root *root,
 | 
				
			||||||
			path->slots[0]--;
 | 
								path->slots[0]--;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		leaf = path->nodes[0];
 | 
							leaf = path->nodes[0];
 | 
				
			||||||
 | 
							nritems = btrfs_header_nritems(leaf);
 | 
				
			||||||
 | 
							if (nritems == 0)
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							if (path->slots[0] == nritems)
 | 
				
			||||||
 | 
								path->slots[0]--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 | 
							btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 | 
				
			||||||
		if (found_key.type == type)
 | 
							if (found_key.type == type)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
							if (found_key.objectid < min_objectid)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							if (found_key.objectid == min_objectid &&
 | 
				
			||||||
 | 
							    found_key.type < type)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,10 @@ struct btrfs_ordered_sum;
 | 
				
			||||||
/* orhpan objectid for tracking unlinked/truncated files */
 | 
					/* orhpan objectid for tracking unlinked/truncated files */
 | 
				
			||||||
#define BTRFS_ORPHAN_OBJECTID -5ULL
 | 
					#define BTRFS_ORPHAN_OBJECTID -5ULL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* does write ahead logging to speed up fsyncs */
 | 
				
			||||||
 | 
					#define BTRFS_TREE_LOG_OBJECTID -6ULL
 | 
				
			||||||
 | 
					#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * All files have objectids higher than this.
 | 
					 * All files have objectids higher than this.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -276,6 +280,7 @@ struct btrfs_super_block {
 | 
				
			||||||
	__le64 generation;
 | 
						__le64 generation;
 | 
				
			||||||
	__le64 root;
 | 
						__le64 root;
 | 
				
			||||||
	__le64 chunk_root;
 | 
						__le64 chunk_root;
 | 
				
			||||||
 | 
						__le64 log_root;
 | 
				
			||||||
	__le64 total_bytes;
 | 
						__le64 total_bytes;
 | 
				
			||||||
	__le64 bytes_used;
 | 
						__le64 bytes_used;
 | 
				
			||||||
	__le64 root_dir_objectid;
 | 
						__le64 root_dir_objectid;
 | 
				
			||||||
| 
						 | 
					@ -287,6 +292,7 @@ struct btrfs_super_block {
 | 
				
			||||||
	__le32 sys_chunk_array_size;
 | 
						__le32 sys_chunk_array_size;
 | 
				
			||||||
	u8 root_level;
 | 
						u8 root_level;
 | 
				
			||||||
	u8 chunk_root_level;
 | 
						u8 chunk_root_level;
 | 
				
			||||||
 | 
						u8 log_root_level;
 | 
				
			||||||
	struct btrfs_dev_item dev_item;
 | 
						struct btrfs_dev_item dev_item;
 | 
				
			||||||
	char label[BTRFS_LABEL_SIZE];
 | 
						char label[BTRFS_LABEL_SIZE];
 | 
				
			||||||
	u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
 | 
						u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -392,7 +398,10 @@ struct btrfs_timespec {
 | 
				
			||||||
 * make a new item type
 | 
					 * make a new item type
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct btrfs_inode_item {
 | 
					struct btrfs_inode_item {
 | 
				
			||||||
 | 
						/* nfs style generation number */
 | 
				
			||||||
	__le64 generation;
 | 
						__le64 generation;
 | 
				
			||||||
 | 
						/* transid that last touched this inode */
 | 
				
			||||||
 | 
						__le64 transid;
 | 
				
			||||||
	__le64 size;
 | 
						__le64 size;
 | 
				
			||||||
	__le64 nblocks;
 | 
						__le64 nblocks;
 | 
				
			||||||
	__le64 block_group;
 | 
						__le64 block_group;
 | 
				
			||||||
| 
						 | 
					@ -409,8 +418,13 @@ struct btrfs_inode_item {
 | 
				
			||||||
	struct btrfs_timespec otime;
 | 
						struct btrfs_timespec otime;
 | 
				
			||||||
} __attribute__ ((__packed__));
 | 
					} __attribute__ ((__packed__));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct btrfs_dir_log_item {
 | 
				
			||||||
 | 
						__le64 end;
 | 
				
			||||||
 | 
					} __attribute__ ((__packed__));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct btrfs_dir_item {
 | 
					struct btrfs_dir_item {
 | 
				
			||||||
	struct btrfs_disk_key location;
 | 
						struct btrfs_disk_key location;
 | 
				
			||||||
 | 
						__le64 transid;
 | 
				
			||||||
	__le16 data_len;
 | 
						__le16 data_len;
 | 
				
			||||||
	__le16 name_len;
 | 
						__le16 name_len;
 | 
				
			||||||
	u8 type;
 | 
						u8 type;
 | 
				
			||||||
| 
						 | 
					@ -505,6 +519,9 @@ struct btrfs_fs_info {
 | 
				
			||||||
	struct btrfs_root *tree_root;
 | 
						struct btrfs_root *tree_root;
 | 
				
			||||||
	struct btrfs_root *chunk_root;
 | 
						struct btrfs_root *chunk_root;
 | 
				
			||||||
	struct btrfs_root *dev_root;
 | 
						struct btrfs_root *dev_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the log root tree is a directory of all the other log roots */
 | 
				
			||||||
 | 
						struct btrfs_root *log_root_tree;
 | 
				
			||||||
	struct radix_tree_root fs_roots_radix;
 | 
						struct radix_tree_root fs_roots_radix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct extent_io_tree free_space_cache;
 | 
						struct extent_io_tree free_space_cache;
 | 
				
			||||||
| 
						 | 
					@ -518,6 +535,7 @@ struct btrfs_fs_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u64 generation;
 | 
						u64 generation;
 | 
				
			||||||
	u64 last_trans_committed;
 | 
						u64 last_trans_committed;
 | 
				
			||||||
 | 
						u64 last_trans_new_blockgroup;
 | 
				
			||||||
	u64 open_ioctl_trans;
 | 
						u64 open_ioctl_trans;
 | 
				
			||||||
	unsigned long mount_opt;
 | 
						unsigned long mount_opt;
 | 
				
			||||||
	u64 max_extent;
 | 
						u64 max_extent;
 | 
				
			||||||
| 
						 | 
					@ -527,6 +545,9 @@ struct btrfs_fs_info {
 | 
				
			||||||
	wait_queue_head_t transaction_throttle;
 | 
						wait_queue_head_t transaction_throttle;
 | 
				
			||||||
	wait_queue_head_t transaction_wait;
 | 
						wait_queue_head_t transaction_wait;
 | 
				
			||||||
	wait_queue_head_t async_submit_wait;
 | 
						wait_queue_head_t async_submit_wait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wait_queue_head_t tree_log_wait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct btrfs_super_block super_copy;
 | 
						struct btrfs_super_block super_copy;
 | 
				
			||||||
	struct btrfs_super_block super_for_commit;
 | 
						struct btrfs_super_block super_for_commit;
 | 
				
			||||||
	struct block_device *__bdev;
 | 
						struct block_device *__bdev;
 | 
				
			||||||
| 
						 | 
					@ -535,6 +556,7 @@ struct btrfs_fs_info {
 | 
				
			||||||
	struct backing_dev_info bdi;
 | 
						struct backing_dev_info bdi;
 | 
				
			||||||
	spinlock_t hash_lock;
 | 
						spinlock_t hash_lock;
 | 
				
			||||||
	struct mutex trans_mutex;
 | 
						struct mutex trans_mutex;
 | 
				
			||||||
 | 
						struct mutex tree_log_mutex;
 | 
				
			||||||
	struct mutex transaction_kthread_mutex;
 | 
						struct mutex transaction_kthread_mutex;
 | 
				
			||||||
	struct mutex cleaner_mutex;
 | 
						struct mutex cleaner_mutex;
 | 
				
			||||||
	struct mutex alloc_mutex;
 | 
						struct mutex alloc_mutex;
 | 
				
			||||||
| 
						 | 
					@ -544,8 +566,13 @@ struct btrfs_fs_info {
 | 
				
			||||||
	struct list_head trans_list;
 | 
						struct list_head trans_list;
 | 
				
			||||||
	struct list_head hashers;
 | 
						struct list_head hashers;
 | 
				
			||||||
	struct list_head dead_roots;
 | 
						struct list_head dead_roots;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atomic_t nr_async_submits;
 | 
						atomic_t nr_async_submits;
 | 
				
			||||||
	atomic_t nr_async_bios;
 | 
						atomic_t nr_async_bios;
 | 
				
			||||||
 | 
						atomic_t tree_log_writers;
 | 
				
			||||||
 | 
						atomic_t tree_log_commit;
 | 
				
			||||||
 | 
						unsigned long tree_log_batch;
 | 
				
			||||||
 | 
						u64 tree_log_transid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * this is used by the balancing code to wait for all the pending
 | 
						 * this is used by the balancing code to wait for all the pending
 | 
				
			||||||
| 
						 | 
					@ -583,6 +610,7 @@ struct btrfs_fs_info {
 | 
				
			||||||
	struct completion kobj_unregister;
 | 
						struct completion kobj_unregister;
 | 
				
			||||||
	int do_barriers;
 | 
						int do_barriers;
 | 
				
			||||||
	int closing;
 | 
						int closing;
 | 
				
			||||||
 | 
						int log_root_recovering;
 | 
				
			||||||
	atomic_t throttles;
 | 
						atomic_t throttles;
 | 
				
			||||||
	atomic_t throttle_gen;
 | 
						atomic_t throttle_gen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -596,6 +624,7 @@ struct btrfs_fs_info {
 | 
				
			||||||
	u64 delalloc_bytes;
 | 
						u64 delalloc_bytes;
 | 
				
			||||||
	u64 last_alloc;
 | 
						u64 last_alloc;
 | 
				
			||||||
	u64 last_data_alloc;
 | 
						u64 last_data_alloc;
 | 
				
			||||||
 | 
						u64 last_log_alloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spinlock_t ref_cache_lock;
 | 
						spinlock_t ref_cache_lock;
 | 
				
			||||||
	u64 total_ref_cache_size;
 | 
						u64 total_ref_cache_size;
 | 
				
			||||||
| 
						 | 
					@ -632,6 +661,7 @@ struct btrfs_root {
 | 
				
			||||||
	struct btrfs_leaf_ref_tree *ref_tree;
 | 
						struct btrfs_leaf_ref_tree *ref_tree;
 | 
				
			||||||
	struct btrfs_leaf_ref_tree ref_tree_struct;
 | 
						struct btrfs_leaf_ref_tree ref_tree_struct;
 | 
				
			||||||
	struct btrfs_dirty_root *dirty_root;
 | 
						struct btrfs_dirty_root *dirty_root;
 | 
				
			||||||
 | 
						struct btrfs_root *log_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct btrfs_root_item root_item;
 | 
						struct btrfs_root_item root_item;
 | 
				
			||||||
	struct btrfs_key root_key;
 | 
						struct btrfs_key root_key;
 | 
				
			||||||
| 
						 | 
					@ -640,6 +670,7 @@ struct btrfs_root {
 | 
				
			||||||
	struct kobject root_kobj;
 | 
						struct kobject root_kobj;
 | 
				
			||||||
	struct completion kobj_unregister;
 | 
						struct completion kobj_unregister;
 | 
				
			||||||
	struct mutex objectid_mutex;
 | 
						struct mutex objectid_mutex;
 | 
				
			||||||
 | 
						struct mutex log_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u64 objectid;
 | 
						u64 objectid;
 | 
				
			||||||
	u64 last_trans;
 | 
						u64 last_trans;
 | 
				
			||||||
| 
						 | 
					@ -692,6 +723,8 @@ struct btrfs_root {
 | 
				
			||||||
 * dir items are the name -> inode pointers in a directory.  There is one
 | 
					 * dir items are the name -> inode pointers in a directory.  There is one
 | 
				
			||||||
 * for every name in a directory.
 | 
					 * for every name in a directory.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#define BTRFS_DIR_LOG_ITEM_KEY  14
 | 
				
			||||||
 | 
					#define BTRFS_DIR_LOG_INDEX_KEY 15
 | 
				
			||||||
#define BTRFS_DIR_ITEM_KEY	16
 | 
					#define BTRFS_DIR_ITEM_KEY	16
 | 
				
			||||||
#define BTRFS_DIR_INDEX_KEY	17
 | 
					#define BTRFS_DIR_INDEX_KEY	17
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -703,7 +736,8 @@ struct btrfs_root {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define BTRFS_CSUM_ITEM_KEY	19
 | 
					#define BTRFS_CSUM_ITEM_KEY	19
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* reserve 20-31 for other file stuff */
 | 
					
 | 
				
			||||||
 | 
					/* reserve 21-31 for other file/dir stuff */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * root items point to tree roots.  There are typically in the root
 | 
					 * root items point to tree roots.  There are typically in the root
 | 
				
			||||||
| 
						 | 
					@ -938,6 +972,7 @@ BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* struct btrfs_inode_item */
 | 
					/* struct btrfs_inode_item */
 | 
				
			||||||
BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
 | 
					BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
 | 
				
			||||||
 | 
					BTRFS_SETGET_FUNCS(inode_transid, struct btrfs_inode_item, transid, 64);
 | 
				
			||||||
BTRFS_SETGET_FUNCS(inode_size, struct btrfs_inode_item, size, 64);
 | 
					BTRFS_SETGET_FUNCS(inode_size, struct btrfs_inode_item, size, 64);
 | 
				
			||||||
BTRFS_SETGET_FUNCS(inode_nblocks, struct btrfs_inode_item, nblocks, 64);
 | 
					BTRFS_SETGET_FUNCS(inode_nblocks, struct btrfs_inode_item, nblocks, 64);
 | 
				
			||||||
BTRFS_SETGET_FUNCS(inode_block_group, struct btrfs_inode_item, block_group, 64);
 | 
					BTRFS_SETGET_FUNCS(inode_block_group, struct btrfs_inode_item, block_group, 64);
 | 
				
			||||||
| 
						 | 
					@ -1126,10 +1161,13 @@ static inline void btrfs_set_item_key(struct extent_buffer *eb,
 | 
				
			||||||
	write_eb_member(eb, item, struct btrfs_item, key, disk_key);
 | 
						write_eb_member(eb, item, struct btrfs_item, key, disk_key);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BTRFS_SETGET_FUNCS(dir_log_end, struct btrfs_dir_log_item, end, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* struct btrfs_dir_item */
 | 
					/* struct btrfs_dir_item */
 | 
				
			||||||
BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
 | 
					BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
 | 
				
			||||||
BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
 | 
					BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
 | 
				
			||||||
BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
 | 
					BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
 | 
				
			||||||
 | 
					BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void btrfs_dir_item_key(struct extent_buffer *eb,
 | 
					static inline void btrfs_dir_item_key(struct extent_buffer *eb,
 | 
				
			||||||
				      struct btrfs_dir_item *item,
 | 
									      struct btrfs_dir_item *item,
 | 
				
			||||||
| 
						 | 
					@ -1301,7 +1339,11 @@ BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
 | 
				
			||||||
BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
 | 
					BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
 | 
				
			||||||
			 chunk_root, 64);
 | 
								 chunk_root, 64);
 | 
				
			||||||
BTRFS_SETGET_STACK_FUNCS(super_chunk_root_level, struct btrfs_super_block,
 | 
					BTRFS_SETGET_STACK_FUNCS(super_chunk_root_level, struct btrfs_super_block,
 | 
				
			||||||
			 chunk_root_level, 64);
 | 
								 chunk_root_level, 8);
 | 
				
			||||||
 | 
					BTRFS_SETGET_STACK_FUNCS(super_log_root, struct btrfs_super_block,
 | 
				
			||||||
 | 
								 log_root, 64);
 | 
				
			||||||
 | 
					BTRFS_SETGET_STACK_FUNCS(super_log_root_level, struct btrfs_super_block,
 | 
				
			||||||
 | 
								 log_root_level, 8);
 | 
				
			||||||
BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
 | 
					BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
 | 
				
			||||||
			 total_bytes, 64);
 | 
								 total_bytes, 64);
 | 
				
			||||||
BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
 | 
					BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
 | 
				
			||||||
| 
						 | 
					@ -1405,6 +1447,12 @@ static inline struct dentry *fdentry(struct file *file) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* extent-tree.c */
 | 
					/* extent-tree.c */
 | 
				
			||||||
 | 
					int btrfs_lookup_extent(struct btrfs_root *root, struct btrfs_path *path,
 | 
				
			||||||
 | 
								u64 start, u64 len);
 | 
				
			||||||
 | 
					int btrfs_update_pinned_extents(struct btrfs_root *root,
 | 
				
			||||||
 | 
									u64 bytenr, u64 num, int pin);
 | 
				
			||||||
 | 
					int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								struct btrfs_root *root, struct extent_buffer *leaf);
 | 
				
			||||||
int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
 | 
					int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			   struct btrfs_root *root,
 | 
								   struct btrfs_root *root,
 | 
				
			||||||
			   struct btrfs_key *key, u64 bytenr);
 | 
								   struct btrfs_key *key, u64 bytenr);
 | 
				
			||||||
| 
						 | 
					@ -1448,6 +1496,11 @@ int btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
				u64 root_objectid, u64 ref_generation,
 | 
									u64 root_objectid, u64 ref_generation,
 | 
				
			||||||
				u64 owner, u64 owner_offset,
 | 
									u64 owner, u64 owner_offset,
 | 
				
			||||||
				struct btrfs_key *ins);
 | 
									struct btrfs_key *ins);
 | 
				
			||||||
 | 
					int btrfs_alloc_logged_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
									struct btrfs_root *root,
 | 
				
			||||||
 | 
									u64 root_objectid, u64 ref_generation,
 | 
				
			||||||
 | 
									u64 owner, u64 owner_offset,
 | 
				
			||||||
 | 
									struct btrfs_key *ins);
 | 
				
			||||||
int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 | 
					int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
				  struct btrfs_root *root,
 | 
									  struct btrfs_root *root,
 | 
				
			||||||
				  u64 num_bytes, u64 min_alloc_size,
 | 
									  u64 num_bytes, u64 min_alloc_size,
 | 
				
			||||||
| 
						 | 
					@ -1488,9 +1541,9 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
 | 
				
			||||||
			struct btrfs_key *key, int lowest_level,
 | 
								struct btrfs_key *key, int lowest_level,
 | 
				
			||||||
			int cache_only, u64 min_trans);
 | 
								int cache_only, u64 min_trans);
 | 
				
			||||||
int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
					int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 | 
				
			||||||
 | 
								 struct btrfs_key *max_key,
 | 
				
			||||||
			 struct btrfs_path *path, int cache_only,
 | 
								 struct btrfs_path *path, int cache_only,
 | 
				
			||||||
			 u64 min_trans);
 | 
								 u64 min_trans);
 | 
				
			||||||
 | 
					 | 
				
			||||||
int btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
					int btrfs_cow_block(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		    struct btrfs_root *root, struct extent_buffer *buf,
 | 
							    struct btrfs_root *root, struct extent_buffer *buf,
 | 
				
			||||||
		    struct extent_buffer *parent, int parent_slot,
 | 
							    struct extent_buffer *parent, int parent_slot,
 | 
				
			||||||
| 
						 | 
					@ -1656,6 +1709,18 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
 | 
				
			||||||
#define PageChecked PageFsMisc
 | 
					#define PageChecked PageFsMisc
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
							       struct btrfs_root *root,
 | 
				
			||||||
 | 
							       struct inode *dir, struct inode *inode,
 | 
				
			||||||
 | 
							       const char *name, int name_len);
 | 
				
			||||||
 | 
					int btrfs_add_link(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
							   struct inode *parent_inode, struct inode *inode,
 | 
				
			||||||
 | 
							   const char *name, int name_len, int add_backref, u64 index);
 | 
				
			||||||
 | 
					int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								       struct btrfs_root *root,
 | 
				
			||||||
 | 
								       struct inode *inode, u64 new_size,
 | 
				
			||||||
 | 
								       u32 min_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int btrfs_start_delalloc_inodes(struct btrfs_root *root);
 | 
					int btrfs_start_delalloc_inodes(struct btrfs_root *root);
 | 
				
			||||||
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
 | 
					int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
 | 
				
			||||||
int btrfs_writepages(struct address_space *mapping,
 | 
					int btrfs_writepages(struct address_space *mapping,
 | 
				
			||||||
| 
						 | 
					@ -1715,6 +1780,7 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 | 
					long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* file.c */
 | 
					/* file.c */
 | 
				
			||||||
 | 
					int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync);
 | 
				
			||||||
int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end);
 | 
					int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end);
 | 
				
			||||||
int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 | 
					int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 | 
				
			||||||
extern struct file_operations btrfs_file_operations;
 | 
					extern struct file_operations btrfs_file_operations;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,6 +96,7 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
 | 
						btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
 | 
				
			||||||
	btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
 | 
						btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
 | 
				
			||||||
	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
						btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
				
			||||||
 | 
						btrfs_set_dir_transid(leaf, dir_item, trans->transid);
 | 
				
			||||||
	btrfs_set_dir_data_len(leaf, dir_item, data_len);
 | 
						btrfs_set_dir_data_len(leaf, dir_item, data_len);
 | 
				
			||||||
	name_ptr = (unsigned long)(dir_item + 1);
 | 
						name_ptr = (unsigned long)(dir_item + 1);
 | 
				
			||||||
	data_ptr = (unsigned long)((char *)name_ptr + name_len);
 | 
						data_ptr = (unsigned long)((char *)name_ptr + name_len);
 | 
				
			||||||
| 
						 | 
					@ -142,6 +143,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
				
			||||||
	btrfs_set_dir_type(leaf, dir_item, type);
 | 
						btrfs_set_dir_type(leaf, dir_item, type);
 | 
				
			||||||
	btrfs_set_dir_data_len(leaf, dir_item, 0);
 | 
						btrfs_set_dir_data_len(leaf, dir_item, 0);
 | 
				
			||||||
	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
						btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
				
			||||||
 | 
						btrfs_set_dir_transid(leaf, dir_item, trans->transid);
 | 
				
			||||||
	name_ptr = (unsigned long)(dir_item + 1);
 | 
						name_ptr = (unsigned long)(dir_item + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write_extent_buffer(leaf, name, name_ptr, name_len);
 | 
						write_extent_buffer(leaf, name, name_ptr, name_len);
 | 
				
			||||||
| 
						 | 
					@ -169,6 +171,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
 | 
				
			||||||
	btrfs_set_dir_type(leaf, dir_item, type);
 | 
						btrfs_set_dir_type(leaf, dir_item, type);
 | 
				
			||||||
	btrfs_set_dir_data_len(leaf, dir_item, 0);
 | 
						btrfs_set_dir_data_len(leaf, dir_item, 0);
 | 
				
			||||||
	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
						btrfs_set_dir_name_len(leaf, dir_item, name_len);
 | 
				
			||||||
 | 
						btrfs_set_dir_transid(leaf, dir_item, trans->transid);
 | 
				
			||||||
	name_ptr = (unsigned long)(dir_item + 1);
 | 
						name_ptr = (unsigned long)(dir_item + 1);
 | 
				
			||||||
	write_extent_buffer(leaf, name, name_ptr, name_len);
 | 
						write_extent_buffer(leaf, name, name_ptr, name_len);
 | 
				
			||||||
	btrfs_mark_buffer_dirty(leaf);
 | 
						btrfs_mark_buffer_dirty(leaf);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@
 | 
				
			||||||
#include "async-thread.h"
 | 
					#include "async-thread.h"
 | 
				
			||||||
#include "locking.h"
 | 
					#include "locking.h"
 | 
				
			||||||
#include "ref-cache.h"
 | 
					#include "ref-cache.h"
 | 
				
			||||||
 | 
					#include "tree-log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
 | 
					static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
 | 
				
			||||||
| 
						 | 
					@ -694,6 +695,18 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_write_tree_block(struct extent_buffer *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return btrfs_fdatawrite_range(buf->first_page->mapping, buf->start,
 | 
				
			||||||
 | 
									      buf->start + buf->len - 1, WB_SYNC_NONE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_wait_tree_block_writeback(struct extent_buffer *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return btrfs_wait_on_page_writeback_range(buf->first_page->mapping,
 | 
				
			||||||
 | 
									  buf->start, buf->start + buf->len -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
 | 
					struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
 | 
				
			||||||
				      u32 blocksize, u64 parent_transid)
 | 
									      u32 blocksize, u64 parent_transid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -732,15 +745,6 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int wait_on_tree_block_writeback(struct btrfs_root *root,
 | 
					 | 
				
			||||||
				 struct extent_buffer *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct inode *btree_inode = root->fs_info->btree_inode;
 | 
					 | 
				
			||||||
	wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->io_tree,
 | 
					 | 
				
			||||||
					buf);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 | 
					static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 | 
				
			||||||
			u32 stripesize, struct btrfs_root *root,
 | 
								u32 stripesize, struct btrfs_root *root,
 | 
				
			||||||
			struct btrfs_fs_info *fs_info,
 | 
								struct btrfs_fs_info *fs_info,
 | 
				
			||||||
| 
						 | 
					@ -771,6 +775,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 | 
				
			||||||
	spin_lock_init(&root->node_lock);
 | 
						spin_lock_init(&root->node_lock);
 | 
				
			||||||
	spin_lock_init(&root->list_lock);
 | 
						spin_lock_init(&root->list_lock);
 | 
				
			||||||
	mutex_init(&root->objectid_mutex);
 | 
						mutex_init(&root->objectid_mutex);
 | 
				
			||||||
 | 
						mutex_init(&root->log_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
 | 
						btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
 | 
				
			||||||
	root->ref_tree = &root->ref_tree_struct;
 | 
						root->ref_tree = &root->ref_tree_struct;
 | 
				
			||||||
| 
						 | 
					@ -809,11 +814,74 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
 | 
					int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					       struct btrfs_key *location)
 | 
								     struct btrfs_fs_info *fs_info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct extent_buffer *eb;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!fs_info->log_root_tree)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eb = fs_info->log_root_tree->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WARN_ON(btrfs_header_level(eb) != 0);
 | 
				
			||||||
 | 
						WARN_ON(btrfs_header_nritems(eb) != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = btrfs_free_extent(trans, fs_info->tree_root,
 | 
				
			||||||
 | 
									eb->start, eb->len,
 | 
				
			||||||
 | 
									BTRFS_TREE_LOG_OBJECTID, 0, 0, 0, 1);
 | 
				
			||||||
 | 
						BUG_ON(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free_extent_buffer(eb);
 | 
				
			||||||
 | 
						kfree(fs_info->log_root_tree);
 | 
				
			||||||
 | 
						fs_info->log_root_tree = NULL;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								     struct btrfs_fs_info *fs_info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_root *root;
 | 
						struct btrfs_root *root;
 | 
				
			||||||
	struct btrfs_root *tree_root = fs_info->tree_root;
 | 
						struct btrfs_root *tree_root = fs_info->tree_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						root = kzalloc(sizeof(*root), GFP_NOFS);
 | 
				
			||||||
 | 
						if (!root)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__setup_root(tree_root->nodesize, tree_root->leafsize,
 | 
				
			||||||
 | 
							     tree_root->sectorsize, tree_root->stripesize,
 | 
				
			||||||
 | 
							     root, fs_info, BTRFS_TREE_LOG_OBJECTID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
 | 
				
			||||||
 | 
						root->root_key.type = BTRFS_ROOT_ITEM_KEY;
 | 
				
			||||||
 | 
						root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
 | 
				
			||||||
 | 
						root->ref_cows = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
 | 
				
			||||||
 | 
										    BTRFS_TREE_LOG_OBJECTID,
 | 
				
			||||||
 | 
										    0, 0, 0, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						btrfs_set_header_nritems(root->node, 0);
 | 
				
			||||||
 | 
						btrfs_set_header_level(root->node, 0);
 | 
				
			||||||
 | 
						btrfs_set_header_bytenr(root->node, root->node->start);
 | 
				
			||||||
 | 
						btrfs_set_header_generation(root->node, trans->transid);
 | 
				
			||||||
 | 
						btrfs_set_header_owner(root->node, BTRFS_TREE_LOG_OBJECTID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						write_extent_buffer(root->node, root->fs_info->fsid,
 | 
				
			||||||
 | 
								    (unsigned long)btrfs_header_fsid(root->node),
 | 
				
			||||||
 | 
								    BTRFS_FSID_SIZE);
 | 
				
			||||||
 | 
						btrfs_mark_buffer_dirty(root->node);
 | 
				
			||||||
 | 
						btrfs_tree_unlock(root->node);
 | 
				
			||||||
 | 
						fs_info->log_root_tree = root;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
 | 
				
			||||||
 | 
										       struct btrfs_key *location)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btrfs_root *root;
 | 
				
			||||||
 | 
						struct btrfs_fs_info *fs_info = tree_root->fs_info;
 | 
				
			||||||
	struct btrfs_path *path;
 | 
						struct btrfs_path *path;
 | 
				
			||||||
	struct extent_buffer *l;
 | 
						struct extent_buffer *l;
 | 
				
			||||||
	u64 highest_inode;
 | 
						u64 highest_inode;
 | 
				
			||||||
| 
						 | 
					@ -863,12 +931,14 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
				     blocksize, 0);
 | 
									     blocksize, 0);
 | 
				
			||||||
	BUG_ON(!root->node);
 | 
						BUG_ON(!root->node);
 | 
				
			||||||
insert:
 | 
					insert:
 | 
				
			||||||
 | 
						if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
 | 
				
			||||||
		root->ref_cows = 1;
 | 
							root->ref_cows = 1;
 | 
				
			||||||
		ret = btrfs_find_highest_inode(root, &highest_inode);
 | 
							ret = btrfs_find_highest_inode(root, &highest_inode);
 | 
				
			||||||
		if (ret == 0) {
 | 
							if (ret == 0) {
 | 
				
			||||||
			root->highest_inode = highest_inode;
 | 
								root->highest_inode = highest_inode;
 | 
				
			||||||
			root->last_inode_alloc = highest_inode;
 | 
								root->last_inode_alloc = highest_inode;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return root;
 | 
						return root;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -907,7 +977,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
	if (root)
 | 
						if (root)
 | 
				
			||||||
		return root;
 | 
							return root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	root = btrfs_read_fs_root_no_radix(fs_info, location);
 | 
						root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location);
 | 
				
			||||||
	if (IS_ERR(root))
 | 
						if (IS_ERR(root))
 | 
				
			||||||
		return root;
 | 
							return root;
 | 
				
			||||||
	ret = radix_tree_insert(&fs_info->fs_roots_radix,
 | 
						ret = radix_tree_insert(&fs_info->fs_roots_radix,
 | 
				
			||||||
| 
						 | 
					@ -1250,16 +1320,18 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 | 
				
			||||||
	u32 blocksize;
 | 
						u32 blocksize;
 | 
				
			||||||
	u32 stripesize;
 | 
						u32 stripesize;
 | 
				
			||||||
	struct buffer_head *bh;
 | 
						struct buffer_head *bh;
 | 
				
			||||||
	struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root),
 | 
						struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
 | 
				
			||||||
						 GFP_NOFS);
 | 
											 GFP_NOFS);
 | 
				
			||||||
	struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root),
 | 
						struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root),
 | 
				
			||||||
					       GFP_NOFS);
 | 
										       GFP_NOFS);
 | 
				
			||||||
	struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
 | 
						struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
 | 
				
			||||||
						GFP_NOFS);
 | 
											GFP_NOFS);
 | 
				
			||||||
	struct btrfs_root *chunk_root = kmalloc(sizeof(struct btrfs_root),
 | 
						struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
 | 
				
			||||||
						GFP_NOFS);
 | 
											GFP_NOFS);
 | 
				
			||||||
	struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root),
 | 
						struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
 | 
				
			||||||
					      GFP_NOFS);
 | 
										      GFP_NOFS);
 | 
				
			||||||
 | 
						struct btrfs_root *log_tree_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	int err = -EINVAL;
 | 
						int err = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1343,6 +1415,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 | 
				
			||||||
	mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
 | 
						mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_init(&fs_info->trans_mutex);
 | 
						mutex_init(&fs_info->trans_mutex);
 | 
				
			||||||
 | 
						mutex_init(&fs_info->tree_log_mutex);
 | 
				
			||||||
	mutex_init(&fs_info->drop_mutex);
 | 
						mutex_init(&fs_info->drop_mutex);
 | 
				
			||||||
	mutex_init(&fs_info->alloc_mutex);
 | 
						mutex_init(&fs_info->alloc_mutex);
 | 
				
			||||||
	mutex_init(&fs_info->chunk_mutex);
 | 
						mutex_init(&fs_info->chunk_mutex);
 | 
				
			||||||
| 
						 | 
					@ -1352,6 +1425,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 | 
				
			||||||
	init_waitqueue_head(&fs_info->transaction_throttle);
 | 
						init_waitqueue_head(&fs_info->transaction_throttle);
 | 
				
			||||||
	init_waitqueue_head(&fs_info->transaction_wait);
 | 
						init_waitqueue_head(&fs_info->transaction_wait);
 | 
				
			||||||
	init_waitqueue_head(&fs_info->async_submit_wait);
 | 
						init_waitqueue_head(&fs_info->async_submit_wait);
 | 
				
			||||||
 | 
						init_waitqueue_head(&fs_info->tree_log_wait);
 | 
				
			||||||
 | 
						atomic_set(&fs_info->tree_log_commit, 0);
 | 
				
			||||||
 | 
						atomic_set(&fs_info->tree_log_writers, 0);
 | 
				
			||||||
 | 
						fs_info->tree_log_transid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
	ret = add_hasher(fs_info, "crc32c");
 | 
						ret = add_hasher(fs_info, "crc32c");
 | 
				
			||||||
| 
						 | 
					@ -1532,7 +1609,26 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 | 
				
			||||||
	if (!fs_info->transaction_kthread)
 | 
						if (!fs_info->transaction_kthread)
 | 
				
			||||||
		goto fail_cleaner;
 | 
							goto fail_cleaner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (btrfs_super_log_root(disk_super) != 0) {
 | 
				
			||||||
 | 
							u32 blocksize;
 | 
				
			||||||
 | 
							u64 bytenr = btrfs_super_log_root(disk_super);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blocksize =
 | 
				
			||||||
 | 
							     btrfs_level_size(tree_root,
 | 
				
			||||||
 | 
									      btrfs_super_log_root_level(disk_super));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							log_tree_root = kzalloc(sizeof(struct btrfs_root),
 | 
				
			||||||
 | 
											      GFP_NOFS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							__setup_root(nodesize, leafsize, sectorsize, stripesize,
 | 
				
			||||||
 | 
								     log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							log_tree_root->node = read_tree_block(tree_root, bytenr,
 | 
				
			||||||
 | 
											      blocksize, 0);
 | 
				
			||||||
 | 
							ret = btrfs_recover_log_trees(log_tree_root);
 | 
				
			||||||
 | 
							BUG_ON(ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fs_info->last_trans_committed = btrfs_super_generation(disk_super);
 | 
				
			||||||
	return tree_root;
 | 
						return tree_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail_cleaner:
 | 
					fail_cleaner:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 | 
					struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
				      struct btrfs_key *location,
 | 
									      struct btrfs_key *location,
 | 
				
			||||||
				      const char *name, int namelen);
 | 
									      const char *name, int namelen);
 | 
				
			||||||
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
 | 
					struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
 | 
				
			||||||
					       struct btrfs_key *location);
 | 
										       struct btrfs_key *location);
 | 
				
			||||||
struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
 | 
					struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
					      struct btrfs_key *location);
 | 
										      struct btrfs_key *location);
 | 
				
			||||||
| 
						 | 
					@ -74,4 +74,10 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
 | 
				
			||||||
			extent_submit_bio_hook_t *submit_bio_hook);
 | 
								extent_submit_bio_hook_t *submit_bio_hook);
 | 
				
			||||||
int btrfs_congested_async(struct btrfs_fs_info *info, int iodone);
 | 
					int btrfs_congested_async(struct btrfs_fs_info *info, int iodone);
 | 
				
			||||||
unsigned long btrfs_async_submit_limit(struct btrfs_fs_info *info);
 | 
					unsigned long btrfs_async_submit_limit(struct btrfs_fs_info *info);
 | 
				
			||||||
 | 
					int btrfs_write_tree_block(struct extent_buffer *buf);
 | 
				
			||||||
 | 
					int btrfs_wait_tree_block_writeback(struct extent_buffer *buf);
 | 
				
			||||||
 | 
					int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								     struct btrfs_fs_info *fs_info);
 | 
				
			||||||
 | 
					int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								     struct btrfs_fs_info *fs_info);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -496,6 +496,23 @@ static int match_extent_ref(struct extent_buffer *leaf,
 | 
				
			||||||
	return ret == 0;
 | 
						return ret == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* simple helper to search for an existing extent at a given offset */
 | 
				
			||||||
 | 
					int btrfs_lookup_extent(struct btrfs_root *root, struct btrfs_path *path,
 | 
				
			||||||
 | 
								u64 start, u64 len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						struct btrfs_key key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						maybe_lock_mutex(root);
 | 
				
			||||||
 | 
						key.objectid = start;
 | 
				
			||||||
 | 
						key.offset = len;
 | 
				
			||||||
 | 
						btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
 | 
				
			||||||
 | 
						ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path,
 | 
				
			||||||
 | 
									0, 0);
 | 
				
			||||||
 | 
						maybe_unlock_mutex(root);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int noinline lookup_extent_backref(struct btrfs_trans_handle *trans,
 | 
					static int noinline lookup_extent_backref(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					  struct btrfs_root *root,
 | 
										  struct btrfs_root *root,
 | 
				
			||||||
					  struct btrfs_path *path, u64 bytenr,
 | 
										  struct btrfs_path *path, u64 bytenr,
 | 
				
			||||||
| 
						 | 
					@ -1409,7 +1426,7 @@ static u64 first_logical_byte(struct btrfs_root *root, u64 search_start)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int update_pinned_extents(struct btrfs_root *root,
 | 
					int btrfs_update_pinned_extents(struct btrfs_root *root,
 | 
				
			||||||
				u64 bytenr, u64 num, int pin)
 | 
									u64 bytenr, u64 num, int pin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 len;
 | 
						u64 len;
 | 
				
			||||||
| 
						 | 
					@ -1492,7 +1509,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					    EXTENT_DIRTY);
 | 
										    EXTENT_DIRTY);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		update_pinned_extents(root, start, end + 1 - start, 0);
 | 
							btrfs_update_pinned_extents(root, start, end + 1 - start, 0);
 | 
				
			||||||
		clear_extent_dirty(unpin, start, end, GFP_NOFS);
 | 
							clear_extent_dirty(unpin, start, end, GFP_NOFS);
 | 
				
			||||||
		set_extent_dirty(free_space_cache, start, end, GFP_NOFS);
 | 
							set_extent_dirty(free_space_cache, start, end, GFP_NOFS);
 | 
				
			||||||
		if (need_resched()) {
 | 
							if (need_resched()) {
 | 
				
			||||||
| 
						 | 
					@ -1538,14 +1555,11 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED,
 | 
							clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED,
 | 
				
			||||||
				  GFP_NOFS);
 | 
									  GFP_NOFS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		eb = btrfs_find_tree_block(extent_root, ins.objectid,
 | 
							eb = btrfs_find_create_tree_block(extent_root, ins.objectid,
 | 
				
			||||||
					   ins.offset);
 | 
										   ins.offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!btrfs_buffer_uptodate(eb, trans->transid)) {
 | 
							if (!btrfs_buffer_uptodate(eb, trans->transid))
 | 
				
			||||||
			mutex_unlock(&extent_root->fs_info->alloc_mutex);
 | 
					 | 
				
			||||||
			btrfs_read_buffer(eb, trans->transid);
 | 
								btrfs_read_buffer(eb, trans->transid);
 | 
				
			||||||
			mutex_lock(&extent_root->fs_info->alloc_mutex);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		btrfs_tree_lock(eb);
 | 
							btrfs_tree_lock(eb);
 | 
				
			||||||
		level = btrfs_header_level(eb);
 | 
							level = btrfs_header_level(eb);
 | 
				
			||||||
| 
						 | 
					@ -1585,13 +1599,20 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
 | 
				
			||||||
		struct extent_buffer *buf;
 | 
							struct extent_buffer *buf;
 | 
				
			||||||
		buf = btrfs_find_tree_block(root, bytenr, num_bytes);
 | 
							buf = btrfs_find_tree_block(root, bytenr, num_bytes);
 | 
				
			||||||
		if (buf) {
 | 
							if (buf) {
 | 
				
			||||||
 | 
								/* we can reuse a block if it hasn't been written
 | 
				
			||||||
 | 
								 * and it is from this transaction.  We can't
 | 
				
			||||||
 | 
								 * reuse anything from the tree log root because
 | 
				
			||||||
 | 
								 * it has tiny sub-transactions.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
			if (btrfs_buffer_uptodate(buf, 0) &&
 | 
								if (btrfs_buffer_uptodate(buf, 0) &&
 | 
				
			||||||
			    btrfs_try_tree_lock(buf)) {
 | 
								    btrfs_try_tree_lock(buf)) {
 | 
				
			||||||
				u64 transid =
 | 
									u64 transid =
 | 
				
			||||||
				    root->fs_info->running_transaction->transid;
 | 
									    root->fs_info->running_transaction->transid;
 | 
				
			||||||
				u64 header_transid =
 | 
									u64 header_transid =
 | 
				
			||||||
					btrfs_header_generation(buf);
 | 
										btrfs_header_generation(buf);
 | 
				
			||||||
				if (header_transid == transid &&
 | 
									if (btrfs_header_owner(buf) !=
 | 
				
			||||||
 | 
									    BTRFS_TREE_LOG_OBJECTID &&
 | 
				
			||||||
 | 
									    header_transid == transid &&
 | 
				
			||||||
				    !btrfs_header_flag(buf,
 | 
									    !btrfs_header_flag(buf,
 | 
				
			||||||
					       BTRFS_HEADER_FLAG_WRITTEN)) {
 | 
										       BTRFS_HEADER_FLAG_WRITTEN)) {
 | 
				
			||||||
					clean_tree_block(NULL, root, buf);
 | 
										clean_tree_block(NULL, root, buf);
 | 
				
			||||||
| 
						 | 
					@ -1603,7 +1624,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			free_extent_buffer(buf);
 | 
								free_extent_buffer(buf);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		update_pinned_extents(root, bytenr, num_bytes, 1);
 | 
							btrfs_update_pinned_extents(root, bytenr, num_bytes, 1);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		set_extent_bits(&root->fs_info->pending_del,
 | 
							set_extent_bits(&root->fs_info->pending_del,
 | 
				
			||||||
				bytenr, bytenr + num_bytes - 1,
 | 
									bytenr, bytenr + num_bytes - 1,
 | 
				
			||||||
| 
						 | 
					@ -1801,7 +1822,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
 | 
				
			||||||
				  GFP_NOFS);
 | 
									  GFP_NOFS);
 | 
				
			||||||
		if (!test_range_bit(&extent_root->fs_info->extent_ins,
 | 
							if (!test_range_bit(&extent_root->fs_info->extent_ins,
 | 
				
			||||||
				    start, end, EXTENT_LOCKED, 0)) {
 | 
									    start, end, EXTENT_LOCKED, 0)) {
 | 
				
			||||||
			update_pinned_extents(extent_root, start,
 | 
								btrfs_update_pinned_extents(extent_root, start,
 | 
				
			||||||
					      end + 1 - start, 1);
 | 
										      end + 1 - start, 1);
 | 
				
			||||||
			ret = __free_extent(trans, extent_root,
 | 
								ret = __free_extent(trans, extent_root,
 | 
				
			||||||
					     start, end + 1 - start,
 | 
										     start, end + 1 - start,
 | 
				
			||||||
| 
						 | 
					@ -1919,6 +1940,12 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
 | 
						if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
 | 
				
			||||||
		last_ptr = &root->fs_info->last_data_alloc;
 | 
							last_ptr = &root->fs_info->last_data_alloc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
 | 
				
			||||||
 | 
							last_ptr = &root->fs_info->last_log_alloc;
 | 
				
			||||||
 | 
							if (!last_ptr == 0 && root->fs_info->last_alloc) {
 | 
				
			||||||
 | 
								*last_ptr = root->fs_info->last_alloc + empty_cluster;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (last_ptr) {
 | 
						if (last_ptr) {
 | 
				
			||||||
		if (*last_ptr)
 | 
							if (*last_ptr)
 | 
				
			||||||
| 
						 | 
					@ -2268,6 +2295,35 @@ int btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	maybe_unlock_mutex(root);
 | 
						maybe_unlock_mutex(root);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * this is used by the tree logging recovery code.  It records that
 | 
				
			||||||
 | 
					 * an extent has been allocated and makes sure to clear the free
 | 
				
			||||||
 | 
					 * space cache bits as well
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int btrfs_alloc_logged_extent(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
									struct btrfs_root *root,
 | 
				
			||||||
 | 
									u64 root_objectid, u64 ref_generation,
 | 
				
			||||||
 | 
									u64 owner, u64 owner_offset,
 | 
				
			||||||
 | 
									struct btrfs_key *ins)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						struct btrfs_block_group_cache *block_group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						maybe_lock_mutex(root);
 | 
				
			||||||
 | 
						block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
 | 
				
			||||||
 | 
						cache_block_group(root, block_group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clear_extent_dirty(&root->fs_info->free_space_cache,
 | 
				
			||||||
 | 
								   ins->objectid, ins->objectid + ins->offset - 1,
 | 
				
			||||||
 | 
								   GFP_NOFS);
 | 
				
			||||||
 | 
						ret = __btrfs_alloc_reserved_extent(trans, root, root_objectid,
 | 
				
			||||||
 | 
										    ref_generation, owner,
 | 
				
			||||||
 | 
										    owner_offset, ins);
 | 
				
			||||||
 | 
						maybe_unlock_mutex(root);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * finds a free extent and does all the dirty work required for allocation
 | 
					 * finds a free extent and does all the dirty work required for allocation
 | 
				
			||||||
 * returns the key for the extent through ins, and a tree buffer for
 | 
					 * returns the key for the extent through ins, and a tree buffer for
 | 
				
			||||||
| 
						 | 
					@ -2350,9 +2406,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	return buf;
 | 
						return buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
 | 
					int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					   struct btrfs_root *root,
 | 
								struct btrfs_root *root, struct extent_buffer *leaf)
 | 
				
			||||||
					   struct extent_buffer *leaf)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 leaf_owner;
 | 
						u64 leaf_owner;
 | 
				
			||||||
	u64 leaf_generation;
 | 
						u64 leaf_generation;
 | 
				
			||||||
| 
						 | 
					@ -2402,7 +2457,7 @@ static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
 | 
					static int noinline cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					struct btrfs_root *root,
 | 
										struct btrfs_root *root,
 | 
				
			||||||
					struct btrfs_leaf_ref *ref)
 | 
										struct btrfs_leaf_ref *ref)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -2512,7 +2567,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		    btrfs_header_nritems(cur))
 | 
							    btrfs_header_nritems(cur))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		if (*level == 0) {
 | 
							if (*level == 0) {
 | 
				
			||||||
			ret = drop_leaf_ref_no_cache(trans, root, cur);
 | 
								ret = btrfs_drop_leaf_ref(trans, root, cur);
 | 
				
			||||||
			BUG_ON(ret);
 | 
								BUG_ON(ret);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2552,7 +2607,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			btrfs_node_key_to_cpu(cur, &key, path->slots[*level]);
 | 
								btrfs_node_key_to_cpu(cur, &key, path->slots[*level]);
 | 
				
			||||||
			ref = btrfs_lookup_leaf_ref(root, bytenr);
 | 
								ref = btrfs_lookup_leaf_ref(root, bytenr);
 | 
				
			||||||
			if (ref) {
 | 
								if (ref) {
 | 
				
			||||||
				ret = drop_leaf_ref(trans, root, ref);
 | 
									ret = cache_drop_leaf_ref(trans, root, ref);
 | 
				
			||||||
				BUG_ON(ret);
 | 
									BUG_ON(ret);
 | 
				
			||||||
				btrfs_remove_leaf_ref(root, ref);
 | 
									btrfs_remove_leaf_ref(root, ref);
 | 
				
			||||||
				btrfs_free_leaf_ref(root, ref);
 | 
									btrfs_free_leaf_ref(root, ref);
 | 
				
			||||||
| 
						 | 
					@ -3628,6 +3683,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	extent_root = root->fs_info->extent_root;
 | 
						extent_root = root->fs_info->extent_root;
 | 
				
			||||||
	block_group_cache = &root->fs_info->block_group_cache;
 | 
						block_group_cache = &root->fs_info->block_group_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						root->fs_info->last_trans_new_blockgroup = trans->transid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cache = kzalloc(sizeof(*cache), GFP_NOFS);
 | 
						cache = kzalloc(sizeof(*cache), GFP_NOFS);
 | 
				
			||||||
	BUG_ON(!cache);
 | 
						BUG_ON(!cache);
 | 
				
			||||||
	cache->key.objectid = chunk_offset;
 | 
						cache->key.objectid = chunk_offset;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,8 @@
 | 
				
			||||||
#include "btrfs_inode.h"
 | 
					#include "btrfs_inode.h"
 | 
				
			||||||
#include "ioctl.h"
 | 
					#include "ioctl.h"
 | 
				
			||||||
#include "print-tree.h"
 | 
					#include "print-tree.h"
 | 
				
			||||||
 | 
					#include "tree-log.h"
 | 
				
			||||||
 | 
					#include "locking.h"
 | 
				
			||||||
#include "compat.h"
 | 
					#include "compat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -988,10 +990,27 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
 | 
				
			||||||
	*ppos = pos;
 | 
						*ppos = pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (num_written > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
 | 
						if (num_written > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
 | 
				
			||||||
		err = sync_page_range(inode, inode->i_mapping,
 | 
							struct btrfs_trans_handle *trans;
 | 
				
			||||||
				      start_pos, num_written);
 | 
					
 | 
				
			||||||
 | 
							err = btrfs_fdatawrite_range(inode->i_mapping, start_pos,
 | 
				
			||||||
 | 
										     start_pos + num_written -1,
 | 
				
			||||||
 | 
										     WB_SYNC_NONE);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
			num_written = err;
 | 
								num_written = err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = btrfs_wait_on_page_writeback_range(inode->i_mapping,
 | 
				
			||||||
 | 
									 start_pos, start_pos + num_written - 1);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								num_written = err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							trans = btrfs_start_transaction(root, 1);
 | 
				
			||||||
 | 
							ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
 | 
				
			||||||
 | 
							if (ret == 0) {
 | 
				
			||||||
 | 
								btrfs_sync_log(trans, root);
 | 
				
			||||||
 | 
								btrfs_end_transaction(trans, root);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								btrfs_commit_transaction(trans, root);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else if (num_written > 0 && (file->f_flags & O_DIRECT)) {
 | 
						} else if (num_written > 0 && (file->f_flags & O_DIRECT)) {
 | 
				
			||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
 | 
					#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
 | 
				
			||||||
		do_sync_file_range(file, start_pos,
 | 
							do_sync_file_range(file, start_pos,
 | 
				
			||||||
| 
						 | 
					@ -1019,8 +1038,7 @@ int btrfs_release_file(struct inode * inode, struct file * filp)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btrfs_sync_file(struct file *file,
 | 
					int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
 | 
				
			||||||
			   struct dentry *dentry, int datasync)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inode *inode = dentry->d_inode;
 | 
						struct inode *inode = dentry->d_inode;
 | 
				
			||||||
	struct btrfs_root *root = BTRFS_I(inode)->root;
 | 
						struct btrfs_root *root = BTRFS_I(inode)->root;
 | 
				
			||||||
| 
						 | 
					@ -1043,6 +1061,8 @@ static int btrfs_sync_file(struct file *file,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mutex_unlock(&root->fs_info->trans_mutex);
 | 
						mutex_unlock(&root->fs_info->trans_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filemap_fdatawait(inode->i_mapping);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * ok we haven't committed the transaction yet, lets do a commit
 | 
						 * ok we haven't committed the transaction yet, lets do a commit
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -1054,7 +1074,16 @@ static int btrfs_sync_file(struct file *file,
 | 
				
			||||||
		ret = -ENOMEM;
 | 
							ret = -ENOMEM;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						if (ret > 0) {
 | 
				
			||||||
		ret = btrfs_commit_transaction(trans, root);
 | 
							ret = btrfs_commit_transaction(trans, root);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							btrfs_sync_log(trans, root);
 | 
				
			||||||
 | 
							ret = btrfs_end_transaction(trans, root);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return ret > 0 ? EIO : ret;
 | 
						return ret > 0 ? EIO : ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										239
									
								
								fs/btrfs/inode.c
									
									
									
									
									
								
							
							
						
						
									
										239
									
								
								fs/btrfs/inode.c
									
									
									
									
									
								
							| 
						 | 
					@ -46,6 +46,8 @@
 | 
				
			||||||
#include "volumes.h"
 | 
					#include "volumes.h"
 | 
				
			||||||
#include "ordered-data.h"
 | 
					#include "ordered-data.h"
 | 
				
			||||||
#include "xattr.h"
 | 
					#include "xattr.h"
 | 
				
			||||||
 | 
					#include "compat.h"
 | 
				
			||||||
 | 
					#include "tree-log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct btrfs_iget_args {
 | 
					struct btrfs_iget_args {
 | 
				
			||||||
	u64 ino;
 | 
						u64 ino;
 | 
				
			||||||
| 
						 | 
					@ -586,6 +588,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
 | 
				
			||||||
			  &ordered_extent->list);
 | 
								  &ordered_extent->list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_ordered_update_i_size(inode, ordered_extent);
 | 
						btrfs_ordered_update_i_size(inode, ordered_extent);
 | 
				
			||||||
 | 
						btrfs_update_inode(trans, root, inode);
 | 
				
			||||||
	btrfs_remove_ordered_extent(inode, ordered_extent);
 | 
						btrfs_remove_ordered_extent(inode, ordered_extent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* once for us */
 | 
						/* once for us */
 | 
				
			||||||
| 
						 | 
					@ -593,7 +596,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
 | 
				
			||||||
	/* once for the tree */
 | 
						/* once for the tree */
 | 
				
			||||||
	btrfs_put_ordered_extent(ordered_extent);
 | 
						btrfs_put_ordered_extent(ordered_extent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_update_inode(trans, root, inode);
 | 
					 | 
				
			||||||
	btrfs_end_transaction(trans, root);
 | 
						btrfs_end_transaction(trans, root);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1007,7 +1009,8 @@ void btrfs_read_locked_inode(struct inode *inode)
 | 
				
			||||||
	inode->i_ctime.tv_nsec = btrfs_timespec_nsec(leaf, tspec);
 | 
						inode->i_ctime.tv_nsec = btrfs_timespec_nsec(leaf, tspec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inode->i_blocks = btrfs_inode_nblocks(leaf, inode_item);
 | 
						inode->i_blocks = btrfs_inode_nblocks(leaf, inode_item);
 | 
				
			||||||
	inode->i_generation = btrfs_inode_generation(leaf, inode_item);
 | 
						BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item);
 | 
				
			||||||
 | 
						inode->i_generation = BTRFS_I(inode)->generation;
 | 
				
			||||||
	inode->i_rdev = 0;
 | 
						inode->i_rdev = 0;
 | 
				
			||||||
	rdev = btrfs_inode_rdev(leaf, inode_item);
 | 
						rdev = btrfs_inode_rdev(leaf, inode_item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1056,7 +1059,8 @@ void btrfs_read_locked_inode(struct inode *inode)
 | 
				
			||||||
	make_bad_inode(inode);
 | 
						make_bad_inode(inode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fill_inode_item(struct extent_buffer *leaf,
 | 
					static void fill_inode_item(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								    struct extent_buffer *leaf,
 | 
				
			||||||
			    struct btrfs_inode_item *item,
 | 
								    struct btrfs_inode_item *item,
 | 
				
			||||||
			    struct inode *inode)
 | 
								    struct inode *inode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1082,7 +1086,8 @@ static void fill_inode_item(struct extent_buffer *leaf,
 | 
				
			||||||
				inode->i_ctime.tv_nsec);
 | 
									inode->i_ctime.tv_nsec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_set_inode_nblocks(leaf, item, inode->i_blocks);
 | 
						btrfs_set_inode_nblocks(leaf, item, inode->i_blocks);
 | 
				
			||||||
	btrfs_set_inode_generation(leaf, item, inode->i_generation);
 | 
						btrfs_set_inode_generation(leaf, item, BTRFS_I(inode)->generation);
 | 
				
			||||||
 | 
						btrfs_set_inode_transid(leaf, item, trans->transid);
 | 
				
			||||||
	btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
 | 
						btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
 | 
				
			||||||
	btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
 | 
						btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
 | 
				
			||||||
	btrfs_set_inode_block_group(leaf, item,
 | 
						btrfs_set_inode_block_group(leaf, item,
 | 
				
			||||||
| 
						 | 
					@ -1112,7 +1117,7 @@ int noinline btrfs_update_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	inode_item = btrfs_item_ptr(leaf, path->slots[0],
 | 
						inode_item = btrfs_item_ptr(leaf, path->slots[0],
 | 
				
			||||||
				  struct btrfs_inode_item);
 | 
									  struct btrfs_inode_item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fill_inode_item(leaf, inode_item, inode);
 | 
						fill_inode_item(trans, leaf, inode_item, inode);
 | 
				
			||||||
	btrfs_mark_buffer_dirty(leaf);
 | 
						btrfs_mark_buffer_dirty(leaf);
 | 
				
			||||||
	btrfs_set_inode_last_trans(trans, inode);
 | 
						btrfs_set_inode_last_trans(trans, inode);
 | 
				
			||||||
	ret = 0;
 | 
						ret = 0;
 | 
				
			||||||
| 
						 | 
					@ -1122,14 +1127,12 @@ int noinline btrfs_update_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
 | 
					int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		       struct btrfs_root *root,
 | 
							       struct btrfs_root *root,
 | 
				
			||||||
			      struct inode *dir,
 | 
							       struct inode *dir, struct inode *inode,
 | 
				
			||||||
			      struct dentry *dentry)
 | 
							       const char *name, int name_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_path *path;
 | 
						struct btrfs_path *path;
 | 
				
			||||||
	const char *name = dentry->d_name.name;
 | 
					 | 
				
			||||||
	int name_len = dentry->d_name.len;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	struct extent_buffer *leaf;
 | 
						struct extent_buffer *leaf;
 | 
				
			||||||
	struct btrfs_dir_item *di;
 | 
						struct btrfs_dir_item *di;
 | 
				
			||||||
| 
						 | 
					@ -1160,13 +1163,12 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	btrfs_release_path(root, path);
 | 
						btrfs_release_path(root, path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_del_inode_ref(trans, root, name, name_len,
 | 
						ret = btrfs_del_inode_ref(trans, root, name, name_len,
 | 
				
			||||||
				  dentry->d_inode->i_ino,
 | 
									  inode->i_ino,
 | 
				
			||||||
				  dentry->d_parent->d_inode->i_ino, &index);
 | 
									  dir->i_ino, &index);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		printk("failed to delete reference to %.*s, "
 | 
							printk("failed to delete reference to %.*s, "
 | 
				
			||||||
		       "inode %lu parent %lu\n", name_len, name,
 | 
							       "inode %lu parent %lu\n", name_len, name,
 | 
				
			||||||
		       dentry->d_inode->i_ino,
 | 
							       inode->i_ino, dir->i_ino);
 | 
				
			||||||
		       dentry->d_parent->d_inode->i_ino);
 | 
					 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1183,21 +1185,25 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	ret = btrfs_delete_one_dir_name(trans, root, path, di);
 | 
						ret = btrfs_delete_one_dir_name(trans, root, path, di);
 | 
				
			||||||
	btrfs_release_path(root, path);
 | 
						btrfs_release_path(root, path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dentry->d_inode->i_ctime = dir->i_ctime;
 | 
						ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
 | 
				
			||||||
 | 
										 inode, dir->i_ino);
 | 
				
			||||||
 | 
						BUG_ON(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
 | 
				
			||||||
 | 
										   dir, index);
 | 
				
			||||||
 | 
						BUG_ON(ret);
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	btrfs_free_path(path);
 | 
						btrfs_free_path(path);
 | 
				
			||||||
	if (!ret) {
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_i_size_write(dir, dir->i_size - name_len * 2);
 | 
						btrfs_i_size_write(dir, dir->i_size - name_len * 2);
 | 
				
			||||||
		dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 | 
						inode->i_ctime = dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 | 
				
			||||||
	btrfs_update_inode(trans, root, dir);
 | 
						btrfs_update_inode(trans, root, dir);
 | 
				
			||||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
 | 
						btrfs_drop_nlink(inode);
 | 
				
			||||||
		dentry->d_inode->i_nlink--;
 | 
						ret = btrfs_update_inode(trans, root, inode);
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		drop_nlink(dentry->d_inode);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		ret = btrfs_update_inode(trans, root, dentry->d_inode);
 | 
					 | 
				
			||||||
	dir->i_sb->s_dirt = 1;
 | 
						dir->i_sb->s_dirt = 1;
 | 
				
			||||||
	}
 | 
					out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1218,7 +1224,8 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
 | 
				
			||||||
	trans = btrfs_start_transaction(root, 1);
 | 
						trans = btrfs_start_transaction(root, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_set_trans_block_group(trans, dir);
 | 
						btrfs_set_trans_block_group(trans, dir);
 | 
				
			||||||
	ret = btrfs_unlink_trans(trans, root, dir, dentry);
 | 
						ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
 | 
				
			||||||
 | 
									 dentry->d_name.name, dentry->d_name.len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (inode->i_nlink == 0)
 | 
						if (inode->i_nlink == 0)
 | 
				
			||||||
		ret = btrfs_orphan_add(trans, inode);
 | 
							ret = btrfs_orphan_add(trans, inode);
 | 
				
			||||||
| 
						 | 
					@ -1256,7 +1263,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 | 
				
			||||||
		goto fail_trans;
 | 
							goto fail_trans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now the directory is empty */
 | 
						/* now the directory is empty */
 | 
				
			||||||
	err = btrfs_unlink_trans(trans, root, dir, dentry);
 | 
						err = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
 | 
				
			||||||
 | 
									 dentry->d_name.name, dentry->d_name.len);
 | 
				
			||||||
	if (!err) {
 | 
						if (!err) {
 | 
				
			||||||
		btrfs_i_size_write(inode, 0);
 | 
							btrfs_i_size_write(inode, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1283,10 +1291,10 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 | 
				
			||||||
 * min_type is the minimum key type to truncate down to.  If set to 0, this
 | 
					 * min_type is the minimum key type to truncate down to.  If set to 0, this
 | 
				
			||||||
 * will kill all the items on this inode, including the INODE_ITEM_KEY.
 | 
					 * will kill all the items on this inode, including the INODE_ITEM_KEY.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
					noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 | 
				
			||||||
					struct btrfs_root *root,
 | 
										struct btrfs_root *root,
 | 
				
			||||||
					struct inode *inode,
 | 
										struct inode *inode,
 | 
				
			||||||
				   u32 min_type)
 | 
										u64 new_size, u32 min_type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	struct btrfs_path *path;
 | 
						struct btrfs_path *path;
 | 
				
			||||||
| 
						 | 
					@ -1307,7 +1315,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	int extent_type = -1;
 | 
						int extent_type = -1;
 | 
				
			||||||
	u64 mask = root->sectorsize - 1;
 | 
						u64 mask = root->sectorsize - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_drop_extent_cache(inode, inode->i_size & (~mask), (u64)-1);
 | 
						if (root->ref_cows)
 | 
				
			||||||
 | 
							btrfs_drop_extent_cache(inode,
 | 
				
			||||||
 | 
										new_size & (~mask), (u64)-1);
 | 
				
			||||||
	path = btrfs_alloc_path();
 | 
						path = btrfs_alloc_path();
 | 
				
			||||||
	path->reada = -1;
 | 
						path->reada = -1;
 | 
				
			||||||
	BUG_ON(!path);
 | 
						BUG_ON(!path);
 | 
				
			||||||
| 
						 | 
					@ -1324,7 +1334,13 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (ret > 0) {
 | 
						if (ret > 0) {
 | 
				
			||||||
		BUG_ON(path->slots[0] == 0);
 | 
							/* there are no items in the tree for us to truncate, we're
 | 
				
			||||||
 | 
							 * done
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (path->slots[0] == 0) {
 | 
				
			||||||
 | 
								ret = 0;
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		path->slots[0]--;
 | 
							path->slots[0]--;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1358,10 +1374,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (found_type == BTRFS_CSUM_ITEM_KEY) {
 | 
							if (found_type == BTRFS_CSUM_ITEM_KEY) {
 | 
				
			||||||
			ret = btrfs_csum_truncate(trans, root, path,
 | 
								ret = btrfs_csum_truncate(trans, root, path,
 | 
				
			||||||
						  inode->i_size);
 | 
											  new_size);
 | 
				
			||||||
			BUG_ON(ret);
 | 
								BUG_ON(ret);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (item_end < inode->i_size) {
 | 
							if (item_end < new_size) {
 | 
				
			||||||
			if (found_type == BTRFS_DIR_ITEM_KEY) {
 | 
								if (found_type == BTRFS_DIR_ITEM_KEY) {
 | 
				
			||||||
				found_type = BTRFS_INODE_ITEM_KEY;
 | 
									found_type = BTRFS_INODE_ITEM_KEY;
 | 
				
			||||||
			} else if (found_type == BTRFS_EXTENT_ITEM_KEY) {
 | 
								} else if (found_type == BTRFS_EXTENT_ITEM_KEY) {
 | 
				
			||||||
| 
						 | 
					@ -1378,7 +1394,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			btrfs_set_key_type(&key, found_type);
 | 
								btrfs_set_key_type(&key, found_type);
 | 
				
			||||||
			goto next;
 | 
								goto next;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (found_key.offset >= inode->i_size)
 | 
							if (found_key.offset >= new_size)
 | 
				
			||||||
			del_item = 1;
 | 
								del_item = 1;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			del_item = 0;
 | 
								del_item = 0;
 | 
				
			||||||
| 
						 | 
					@ -1394,7 +1410,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			if (!del_item) {
 | 
								if (!del_item) {
 | 
				
			||||||
				u64 orig_num_bytes =
 | 
									u64 orig_num_bytes =
 | 
				
			||||||
					btrfs_file_extent_num_bytes(leaf, fi);
 | 
										btrfs_file_extent_num_bytes(leaf, fi);
 | 
				
			||||||
				extent_num_bytes = inode->i_size -
 | 
									extent_num_bytes = new_size -
 | 
				
			||||||
					found_key.offset + root->sectorsize - 1;
 | 
										found_key.offset + root->sectorsize - 1;
 | 
				
			||||||
				extent_num_bytes = extent_num_bytes &
 | 
									extent_num_bytes = extent_num_bytes &
 | 
				
			||||||
					~((u64)root->sectorsize - 1);
 | 
										~((u64)root->sectorsize - 1);
 | 
				
			||||||
| 
						 | 
					@ -1402,7 +1418,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
							 extent_num_bytes);
 | 
												 extent_num_bytes);
 | 
				
			||||||
				num_dec = (orig_num_bytes -
 | 
									num_dec = (orig_num_bytes -
 | 
				
			||||||
					   extent_num_bytes);
 | 
										   extent_num_bytes);
 | 
				
			||||||
				if (extent_start != 0)
 | 
									if (root->ref_cows && extent_start != 0)
 | 
				
			||||||
					dec_i_blocks(inode, num_dec);
 | 
										dec_i_blocks(inode, num_dec);
 | 
				
			||||||
				btrfs_mark_buffer_dirty(leaf);
 | 
									btrfs_mark_buffer_dirty(leaf);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
| 
						 | 
					@ -1413,22 +1429,29 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
 | 
				
			||||||
				num_dec = btrfs_file_extent_num_bytes(leaf, fi);
 | 
									num_dec = btrfs_file_extent_num_bytes(leaf, fi);
 | 
				
			||||||
				if (extent_start != 0) {
 | 
									if (extent_start != 0) {
 | 
				
			||||||
					found_extent = 1;
 | 
										found_extent = 1;
 | 
				
			||||||
 | 
										if (root->ref_cows)
 | 
				
			||||||
						dec_i_blocks(inode, num_dec);
 | 
											dec_i_blocks(inode, num_dec);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				root_gen = btrfs_header_generation(leaf);
 | 
									if (root->ref_cows) {
 | 
				
			||||||
 | 
										root_gen =
 | 
				
			||||||
 | 
											btrfs_header_generation(leaf);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				root_owner = btrfs_header_owner(leaf);
 | 
									root_owner = btrfs_header_owner(leaf);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
 | 
							} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
 | 
				
			||||||
			if (!del_item) {
 | 
								if (!del_item) {
 | 
				
			||||||
				u32 newsize = inode->i_size - found_key.offset;
 | 
									u32 size = new_size - found_key.offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (root->ref_cows) {
 | 
				
			||||||
					dec_i_blocks(inode, item_end + 1 -
 | 
										dec_i_blocks(inode, item_end + 1 -
 | 
				
			||||||
					    found_key.offset - newsize);
 | 
											    found_key.offset - size);
 | 
				
			||||||
				newsize =
 | 
									}
 | 
				
			||||||
				    btrfs_file_extent_calc_inline_size(newsize);
 | 
									size =
 | 
				
			||||||
 | 
									    btrfs_file_extent_calc_inline_size(size);
 | 
				
			||||||
				ret = btrfs_truncate_item(trans, root, path,
 | 
									ret = btrfs_truncate_item(trans, root, path,
 | 
				
			||||||
							  newsize, 1);
 | 
												  size, 1);
 | 
				
			||||||
				BUG_ON(ret);
 | 
									BUG_ON(ret);
 | 
				
			||||||
			} else {
 | 
								} else if (root->ref_cows) {
 | 
				
			||||||
				dec_i_blocks(inode, item_end + 1 -
 | 
									dec_i_blocks(inode, item_end + 1 -
 | 
				
			||||||
					     found_key.offset);
 | 
										     found_key.offset);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1666,7 +1689,7 @@ void btrfs_delete_inode(struct inode *inode)
 | 
				
			||||||
	trans = btrfs_start_transaction(root, 1);
 | 
						trans = btrfs_start_transaction(root, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_set_trans_block_group(trans, inode);
 | 
						btrfs_set_trans_block_group(trans, inode);
 | 
				
			||||||
	ret = btrfs_truncate_in_trans(trans, root, inode, 0);
 | 
						ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		btrfs_orphan_del(NULL, inode);
 | 
							btrfs_orphan_del(NULL, inode);
 | 
				
			||||||
		goto no_delete_lock;
 | 
							goto no_delete_lock;
 | 
				
			||||||
| 
						 | 
					@ -1753,15 +1776,20 @@ static int fixup_tree_root_location(struct btrfs_root *root,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btrfs_init_locked_inode(struct inode *inode, void *p)
 | 
					static noinline void init_btrfs_i(struct inode *inode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_iget_args *args = p;
 | 
						struct btrfs_inode *bi = BTRFS_I(inode);
 | 
				
			||||||
	inode->i_ino = args->ino;
 | 
					
 | 
				
			||||||
	BTRFS_I(inode)->root = args->root;
 | 
						bi->i_acl = NULL;
 | 
				
			||||||
	BTRFS_I(inode)->delalloc_bytes = 0;
 | 
						bi->i_default_acl = NULL;
 | 
				
			||||||
	inode->i_mapping->writeback_index = 0;
 | 
					
 | 
				
			||||||
	BTRFS_I(inode)->disk_i_size = 0;
 | 
						bi->generation = 0;
 | 
				
			||||||
	BTRFS_I(inode)->index_cnt = (u64)-1;
 | 
						bi->last_trans = 0;
 | 
				
			||||||
 | 
						bi->logged_trans = 0;
 | 
				
			||||||
 | 
						bi->delalloc_bytes = 0;
 | 
				
			||||||
 | 
						bi->disk_i_size = 0;
 | 
				
			||||||
 | 
						bi->flags = 0;
 | 
				
			||||||
 | 
						bi->index_cnt = (u64)-1;
 | 
				
			||||||
	extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
 | 
						extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
 | 
				
			||||||
	extent_io_tree_init(&BTRFS_I(inode)->io_tree,
 | 
						extent_io_tree_init(&BTRFS_I(inode)->io_tree,
 | 
				
			||||||
			     inode->i_mapping, GFP_NOFS);
 | 
								     inode->i_mapping, GFP_NOFS);
 | 
				
			||||||
| 
						 | 
					@ -1771,6 +1799,15 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
 | 
				
			||||||
	btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
 | 
						btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
 | 
				
			||||||
	mutex_init(&BTRFS_I(inode)->csum_mutex);
 | 
						mutex_init(&BTRFS_I(inode)->csum_mutex);
 | 
				
			||||||
	mutex_init(&BTRFS_I(inode)->extent_mutex);
 | 
						mutex_init(&BTRFS_I(inode)->extent_mutex);
 | 
				
			||||||
 | 
						mutex_init(&BTRFS_I(inode)->log_mutex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int btrfs_init_locked_inode(struct inode *inode, void *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btrfs_iget_args *args = p;
 | 
				
			||||||
 | 
						inode->i_ino = args->ino;
 | 
				
			||||||
 | 
						init_btrfs_i(inode);
 | 
				
			||||||
 | 
						BTRFS_I(inode)->root = args->root;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2263,21 +2300,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	 * btrfs_get_inode_index_count has an explanation for the magic
 | 
						 * btrfs_get_inode_index_count has an explanation for the magic
 | 
				
			||||||
	 * number
 | 
						 * number
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						init_btrfs_i(inode);
 | 
				
			||||||
	BTRFS_I(inode)->index_cnt = 2;
 | 
						BTRFS_I(inode)->index_cnt = 2;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
 | 
					 | 
				
			||||||
	extent_io_tree_init(&BTRFS_I(inode)->io_tree,
 | 
					 | 
				
			||||||
			     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
	extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
 | 
					 | 
				
			||||||
			     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
	btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
 | 
					 | 
				
			||||||
	INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes);
 | 
					 | 
				
			||||||
	mutex_init(&BTRFS_I(inode)->csum_mutex);
 | 
					 | 
				
			||||||
	mutex_init(&BTRFS_I(inode)->extent_mutex);
 | 
					 | 
				
			||||||
	BTRFS_I(inode)->delalloc_bytes = 0;
 | 
					 | 
				
			||||||
	inode->i_mapping->writeback_index = 0;
 | 
					 | 
				
			||||||
	BTRFS_I(inode)->disk_i_size = 0;
 | 
					 | 
				
			||||||
	BTRFS_I(inode)->root = root;
 | 
						BTRFS_I(inode)->root = root;
 | 
				
			||||||
 | 
						BTRFS_I(inode)->generation = trans->transid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mode & S_IFDIR)
 | 
						if (mode & S_IFDIR)
 | 
				
			||||||
		owner = 0;
 | 
							owner = 0;
 | 
				
			||||||
| 
						 | 
					@ -2290,7 +2316,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		new_inode_group = group;
 | 
							new_inode_group = group;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	BTRFS_I(inode)->block_group = new_inode_group;
 | 
						BTRFS_I(inode)->block_group = new_inode_group;
 | 
				
			||||||
	BTRFS_I(inode)->flags = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key[0].objectid = objectid;
 | 
						key[0].objectid = objectid;
 | 
				
			||||||
	btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
 | 
						btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
 | 
				
			||||||
| 
						 | 
					@ -2318,7 +2343,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 | 
						inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 | 
				
			||||||
	inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 | 
						inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 | 
				
			||||||
				  struct btrfs_inode_item);
 | 
									  struct btrfs_inode_item);
 | 
				
			||||||
	fill_inode_item(path->nodes[0], inode_item, inode);
 | 
						fill_inode_item(trans, path->nodes[0], inode_item, inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
 | 
						ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
 | 
				
			||||||
			     struct btrfs_inode_ref);
 | 
								     struct btrfs_inode_ref);
 | 
				
			||||||
| 
						 | 
					@ -2349,38 +2374,34 @@ static inline u8 btrfs_inode_type(struct inode *inode)
 | 
				
			||||||
	return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT];
 | 
						return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btrfs_add_link(struct btrfs_trans_handle *trans,
 | 
					int btrfs_add_link(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			    struct dentry *dentry, struct inode *inode,
 | 
							   struct inode *parent_inode, struct inode *inode,
 | 
				
			||||||
			    int add_backref, u64 index)
 | 
							   const char *name, int name_len, int add_backref, u64 index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	struct btrfs_key key;
 | 
						struct btrfs_key key;
 | 
				
			||||||
	struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root;
 | 
						struct btrfs_root *root = BTRFS_I(parent_inode)->root;
 | 
				
			||||||
	struct inode *parent_inode = dentry->d_parent->d_inode;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key.objectid = inode->i_ino;
 | 
						key.objectid = inode->i_ino;
 | 
				
			||||||
	btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
 | 
						btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
 | 
				
			||||||
	key.offset = 0;
 | 
						key.offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_insert_dir_item(trans, root,
 | 
						ret = btrfs_insert_dir_item(trans, root, name, name_len,
 | 
				
			||||||
				    dentry->d_name.name, dentry->d_name.len,
 | 
									    parent_inode->i_ino,
 | 
				
			||||||
				    dentry->d_parent->d_inode->i_ino,
 | 
					 | 
				
			||||||
				    &key, btrfs_inode_type(inode),
 | 
									    &key, btrfs_inode_type(inode),
 | 
				
			||||||
				    index);
 | 
									    index);
 | 
				
			||||||
	if (ret == 0) {
 | 
						if (ret == 0) {
 | 
				
			||||||
		if (add_backref) {
 | 
							if (add_backref) {
 | 
				
			||||||
			ret = btrfs_insert_inode_ref(trans, root,
 | 
								ret = btrfs_insert_inode_ref(trans, root,
 | 
				
			||||||
					     dentry->d_name.name,
 | 
											     name, name_len,
 | 
				
			||||||
					     dentry->d_name.len,
 | 
					 | 
				
			||||||
						     inode->i_ino,
 | 
											     inode->i_ino,
 | 
				
			||||||
						     parent_inode->i_ino,
 | 
											     parent_inode->i_ino,
 | 
				
			||||||
						     index);
 | 
											     index);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		btrfs_i_size_write(parent_inode, parent_inode->i_size +
 | 
							btrfs_i_size_write(parent_inode, parent_inode->i_size +
 | 
				
			||||||
				   dentry->d_name.len * 2);
 | 
									   name_len * 2);
 | 
				
			||||||
		parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
 | 
							parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
 | 
				
			||||||
		ret = btrfs_update_inode(trans, root,
 | 
							ret = btrfs_update_inode(trans, root, parent_inode);
 | 
				
			||||||
					 dentry->d_parent->d_inode);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2389,7 +2410,9 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			    struct dentry *dentry, struct inode *inode,
 | 
								    struct dentry *dentry, struct inode *inode,
 | 
				
			||||||
			    int backref, u64 index)
 | 
								    int backref, u64 index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err = btrfs_add_link(trans, dentry, inode, backref, index);
 | 
						int err = btrfs_add_link(trans, dentry->d_parent->d_inode,
 | 
				
			||||||
 | 
									 inode, dentry->d_name.name,
 | 
				
			||||||
 | 
									 dentry->d_name.len, backref, index);
 | 
				
			||||||
	if (!err) {
 | 
						if (!err) {
 | 
				
			||||||
		d_instantiate(dentry, inode);
 | 
							d_instantiate(dentry, inode);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -2513,19 +2536,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
 | 
				
			||||||
		inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
 | 
							inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
 | 
				
			||||||
		inode->i_fop = &btrfs_file_operations;
 | 
							inode->i_fop = &btrfs_file_operations;
 | 
				
			||||||
		inode->i_op = &btrfs_file_inode_operations;
 | 
							inode->i_op = &btrfs_file_inode_operations;
 | 
				
			||||||
		extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
 | 
					 | 
				
			||||||
		extent_io_tree_init(&BTRFS_I(inode)->io_tree,
 | 
					 | 
				
			||||||
				     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
		extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
 | 
					 | 
				
			||||||
				     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
		INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes);
 | 
					 | 
				
			||||||
		mutex_init(&BTRFS_I(inode)->csum_mutex);
 | 
					 | 
				
			||||||
		mutex_init(&BTRFS_I(inode)->extent_mutex);
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->delalloc_bytes = 0;
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->disk_i_size = 0;
 | 
					 | 
				
			||||||
		inode->i_mapping->writeback_index = 0;
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 | 
							BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 | 
				
			||||||
		btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dir->i_sb->s_dirt = 1;
 | 
						dir->i_sb->s_dirt = 1;
 | 
				
			||||||
	btrfs_update_inode_block_group(trans, inode);
 | 
						btrfs_update_inode_block_group(trans, inode);
 | 
				
			||||||
| 
						 | 
					@ -2556,11 +2567,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 | 
				
			||||||
	if (inode->i_nlink == 0)
 | 
						if (inode->i_nlink == 0)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
 | 
						btrfs_inc_nlink(inode);
 | 
				
			||||||
	inode->i_nlink++;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	inc_nlink(inode);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	err = btrfs_check_free_space(root, 1, 0);
 | 
						err = btrfs_check_free_space(root, 1, 0);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
| 
						 | 
					@ -2650,7 +2657,9 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = btrfs_add_link(trans, dentry, inode, 0, index);
 | 
						err = btrfs_add_link(trans, dentry->d_parent->d_inode,
 | 
				
			||||||
 | 
									 inode, dentry->d_name.name,
 | 
				
			||||||
 | 
									 dentry->d_name.len, 0, index);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3221,7 +3230,7 @@ static void btrfs_truncate(struct inode *inode)
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	/* FIXME, add redo link to tree so we don't leak on crash */
 | 
						/* FIXME, add redo link to tree so we don't leak on crash */
 | 
				
			||||||
	ret = btrfs_truncate_in_trans(trans, root, inode,
 | 
						ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
 | 
				
			||||||
				      BTRFS_EXTENT_DATA_KEY);
 | 
									      BTRFS_EXTENT_DATA_KEY);
 | 
				
			||||||
	btrfs_update_inode(trans, root, inode);
 | 
						btrfs_update_inode(trans, root, inode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3304,6 +3313,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 | 
				
			||||||
	if (!ei)
 | 
						if (!ei)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	ei->last_trans = 0;
 | 
						ei->last_trans = 0;
 | 
				
			||||||
 | 
						ei->logged_trans = 0;
 | 
				
			||||||
	btrfs_ordered_inode_tree_init(&ei->ordered_tree);
 | 
						btrfs_ordered_inode_tree_init(&ei->ordered_tree);
 | 
				
			||||||
	ei->i_acl = BTRFS_ACL_NOT_CACHED;
 | 
						ei->i_acl = BTRFS_ACL_NOT_CACHED;
 | 
				
			||||||
	ei->i_default_acl = BTRFS_ACL_NOT_CACHED;
 | 
						ei->i_default_acl = BTRFS_ACL_NOT_CACHED;
 | 
				
			||||||
| 
						 | 
					@ -3463,31 +3473,39 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_set_trans_block_group(trans, new_dir);
 | 
						btrfs_set_trans_block_group(trans, new_dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	old_dentry->d_inode->i_nlink++;
 | 
						btrfs_inc_nlink(old_dentry->d_inode);
 | 
				
			||||||
	old_dir->i_ctime = old_dir->i_mtime = ctime;
 | 
						old_dir->i_ctime = old_dir->i_mtime = ctime;
 | 
				
			||||||
	new_dir->i_ctime = new_dir->i_mtime = ctime;
 | 
						new_dir->i_ctime = new_dir->i_mtime = ctime;
 | 
				
			||||||
	old_inode->i_ctime = ctime;
 | 
						old_inode->i_ctime = ctime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_unlink_trans(trans, root, old_dir, old_dentry);
 | 
						ret = btrfs_unlink_inode(trans, root, old_dir, old_dentry->d_inode,
 | 
				
			||||||
 | 
									 old_dentry->d_name.name,
 | 
				
			||||||
 | 
									 old_dentry->d_name.len);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (new_inode) {
 | 
						if (new_inode) {
 | 
				
			||||||
		new_inode->i_ctime = CURRENT_TIME;
 | 
							new_inode->i_ctime = CURRENT_TIME;
 | 
				
			||||||
		ret = btrfs_unlink_trans(trans, root, new_dir, new_dentry);
 | 
							ret = btrfs_unlink_inode(trans, root, new_dir,
 | 
				
			||||||
 | 
										 new_dentry->d_inode,
 | 
				
			||||||
 | 
										 new_dentry->d_name.name,
 | 
				
			||||||
 | 
										 new_dentry->d_name.len);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			goto out_fail;
 | 
								goto out_fail;
 | 
				
			||||||
		if (new_inode->i_nlink == 0) {
 | 
							if (new_inode->i_nlink == 0) {
 | 
				
			||||||
			ret = btrfs_orphan_add(trans, new_inode);
 | 
								ret = btrfs_orphan_add(trans, new_dentry->d_inode);
 | 
				
			||||||
			if (ret)
 | 
								if (ret)
 | 
				
			||||||
				goto out_fail;
 | 
									goto out_fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ret = btrfs_set_inode_index(new_dir, old_inode, &index);
 | 
						ret = btrfs_set_inode_index(new_dir, old_inode, &index);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_add_link(trans, new_dentry, old_inode, 1, index);
 | 
						ret = btrfs_add_link(trans, new_dentry->d_parent->d_inode,
 | 
				
			||||||
 | 
								     old_inode, new_dentry->d_name.name,
 | 
				
			||||||
 | 
								     new_dentry->d_name.len, 1, index);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3577,19 +3595,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 | 
				
			||||||
		inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
 | 
							inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
 | 
				
			||||||
		inode->i_fop = &btrfs_file_operations;
 | 
							inode->i_fop = &btrfs_file_operations;
 | 
				
			||||||
		inode->i_op = &btrfs_file_inode_operations;
 | 
							inode->i_op = &btrfs_file_inode_operations;
 | 
				
			||||||
		extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
 | 
					 | 
				
			||||||
		extent_io_tree_init(&BTRFS_I(inode)->io_tree,
 | 
					 | 
				
			||||||
				     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
		extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
 | 
					 | 
				
			||||||
				     inode->i_mapping, GFP_NOFS);
 | 
					 | 
				
			||||||
		INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes);
 | 
					 | 
				
			||||||
		mutex_init(&BTRFS_I(inode)->csum_mutex);
 | 
					 | 
				
			||||||
		mutex_init(&BTRFS_I(inode)->extent_mutex);
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->delalloc_bytes = 0;
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->disk_i_size = 0;
 | 
					 | 
				
			||||||
		inode->i_mapping->writeback_index = 0;
 | 
					 | 
				
			||||||
		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 | 
							BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 | 
				
			||||||
		btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dir->i_sb->s_dirt = 1;
 | 
						dir->i_sb->s_dirt = 1;
 | 
				
			||||||
	btrfs_update_inode_block_group(trans, inode);
 | 
						btrfs_update_inode_block_group(trans, inode);
 | 
				
			||||||
| 
						 | 
					@ -3691,6 +3697,7 @@ static struct file_operations btrfs_dir_file_operations = {
 | 
				
			||||||
	.compat_ioctl	= btrfs_ioctl,
 | 
						.compat_ioctl	= btrfs_ioctl,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	.release        = btrfs_release_file,
 | 
						.release        = btrfs_release_file,
 | 
				
			||||||
 | 
						.fsync		= btrfs_sync_file,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct extent_io_ops btrfs_extent_io_ops = {
 | 
					static struct extent_io_ops btrfs_extent_io_ops = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +202,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
 | 
				
			||||||
		memcpy(&found_key, &key, sizeof(key));
 | 
							memcpy(&found_key, &key, sizeof(key));
 | 
				
			||||||
		key.offset++;
 | 
							key.offset++;
 | 
				
			||||||
		btrfs_release_path(root, path);
 | 
							btrfs_release_path(root, path);
 | 
				
			||||||
		dead_root = btrfs_read_fs_root_no_radix(root->fs_info,
 | 
							dead_root =
 | 
				
			||||||
 | 
								btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
 | 
				
			||||||
						    &found_key);
 | 
											    &found_key);
 | 
				
			||||||
		if (IS_ERR(dead_root)) {
 | 
							if (IS_ERR(dead_root)) {
 | 
				
			||||||
			ret = PTR_ERR(dead_root);
 | 
								ret = PTR_ERR(dead_root);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
#include "transaction.h"
 | 
					#include "transaction.h"
 | 
				
			||||||
#include "locking.h"
 | 
					#include "locking.h"
 | 
				
			||||||
#include "ref-cache.h"
 | 
					#include "ref-cache.h"
 | 
				
			||||||
 | 
					#include "tree-log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int total_trans = 0;
 | 
					static int total_trans = 0;
 | 
				
			||||||
extern struct kmem_cache *btrfs_trans_handle_cachep;
 | 
					extern struct kmem_cache *btrfs_trans_handle_cachep;
 | 
				
			||||||
| 
						 | 
					@ -57,6 +58,7 @@ static noinline int join_transaction(struct btrfs_root *root)
 | 
				
			||||||
		root->fs_info->generation++;
 | 
							root->fs_info->generation++;
 | 
				
			||||||
		root->fs_info->last_alloc = 0;
 | 
							root->fs_info->last_alloc = 0;
 | 
				
			||||||
		root->fs_info->last_data_alloc = 0;
 | 
							root->fs_info->last_data_alloc = 0;
 | 
				
			||||||
 | 
							root->fs_info->last_log_alloc = 0;
 | 
				
			||||||
		cur_trans->num_writers = 1;
 | 
							cur_trans->num_writers = 1;
 | 
				
			||||||
		cur_trans->num_joined = 0;
 | 
							cur_trans->num_joined = 0;
 | 
				
			||||||
		cur_trans->transid = root->fs_info->generation;
 | 
							cur_trans->transid = root->fs_info->generation;
 | 
				
			||||||
| 
						 | 
					@ -83,7 +85,7 @@ static noinline int join_transaction(struct btrfs_root *root)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static noinline int record_root_in_trans(struct btrfs_root *root)
 | 
					noinline int btrfs_record_root_in_trans(struct btrfs_root *root)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_dirty_root *dirty;
 | 
						struct btrfs_dirty_root *dirty;
 | 
				
			||||||
	u64 running_trans_id = root->fs_info->running_transaction->transid;
 | 
						u64 running_trans_id = root->fs_info->running_transaction->transid;
 | 
				
			||||||
| 
						 | 
					@ -151,7 +153,7 @@ static void wait_current_trans(struct btrfs_root *root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 | 
					static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 | 
				
			||||||
					     int num_blocks, int wait)
 | 
										     int num_blocks, int wait)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct btrfs_trans_handle *h =
 | 
						struct btrfs_trans_handle *h =
 | 
				
			||||||
| 
						 | 
					@ -164,7 +166,7 @@ struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 | 
				
			||||||
	ret = join_transaction(root);
 | 
						ret = join_transaction(root);
 | 
				
			||||||
	BUG_ON(ret);
 | 
						BUG_ON(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	record_root_in_trans(root);
 | 
						btrfs_record_root_in_trans(root);
 | 
				
			||||||
	h->transid = root->fs_info->running_transaction->transid;
 | 
						h->transid = root->fs_info->running_transaction->transid;
 | 
				
			||||||
	h->transaction = root->fs_info->running_transaction;
 | 
						h->transaction = root->fs_info->running_transaction;
 | 
				
			||||||
	h->blocks_reserved = num_blocks;
 | 
						h->blocks_reserved = num_blocks;
 | 
				
			||||||
| 
						 | 
					@ -456,6 +458,8 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
 | 
				
			||||||
			BUG_ON(!root->ref_tree);
 | 
								BUG_ON(!root->ref_tree);
 | 
				
			||||||
			dirty = root->dirty_root;
 | 
								dirty = root->dirty_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								btrfs_free_log(trans, root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (root->commit_root == root->node) {
 | 
								if (root->commit_root == root->node) {
 | 
				
			||||||
				WARN_ON(root->node->start !=
 | 
									WARN_ON(root->node->start !=
 | 
				
			||||||
					btrfs_root_bytenr(&root->root_item));
 | 
										btrfs_root_bytenr(&root->root_item));
 | 
				
			||||||
| 
						 | 
					@ -600,7 +604,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
 | 
				
			||||||
		num_bytes -= btrfs_root_used(&dirty->root->root_item);
 | 
							num_bytes -= btrfs_root_used(&dirty->root->root_item);
 | 
				
			||||||
		bytes_used = btrfs_root_used(&root->root_item);
 | 
							bytes_used = btrfs_root_used(&root->root_item);
 | 
				
			||||||
		if (num_bytes) {
 | 
							if (num_bytes) {
 | 
				
			||||||
			record_root_in_trans(root);
 | 
								btrfs_record_root_in_trans(root);
 | 
				
			||||||
			btrfs_set_root_used(&root->root_item,
 | 
								btrfs_set_root_used(&root->root_item,
 | 
				
			||||||
					    bytes_used - num_bytes);
 | 
										    bytes_used - num_bytes);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -745,7 +749,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&dirty_fs_roots);
 | 
						INIT_LIST_HEAD(&dirty_fs_roots);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&root->fs_info->trans_mutex);
 | 
						mutex_lock(&root->fs_info->trans_mutex);
 | 
				
			||||||
	if (trans->transaction->in_commit) {
 | 
						if (trans->transaction->in_commit) {
 | 
				
			||||||
		cur_trans = trans->transaction;
 | 
							cur_trans = trans->transaction;
 | 
				
			||||||
| 
						 | 
					@ -821,10 +824,30 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WARN_ON(cur_trans != trans->transaction);
 | 
						WARN_ON(cur_trans != trans->transaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* btrfs_commit_tree_roots is responsible for getting the
 | 
				
			||||||
 | 
						 * various roots consistent with each other.  Every pointer
 | 
				
			||||||
 | 
						 * in the tree of tree roots has to point to the most up to date
 | 
				
			||||||
 | 
						 * root for every subvolume and other tree.  So, we have to keep
 | 
				
			||||||
 | 
						 * the tree logging code from jumping in and changing any
 | 
				
			||||||
 | 
						 * of the trees.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * At this point in the commit, there can't be any tree-log
 | 
				
			||||||
 | 
						 * writers, but a little lower down we drop the trans mutex
 | 
				
			||||||
 | 
						 * and let new people in.  By holding the tree_log_mutex
 | 
				
			||||||
 | 
						 * from now until after the super is written, we avoid races
 | 
				
			||||||
 | 
						 * with the tree-log code.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						mutex_lock(&root->fs_info->tree_log_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix,
 | 
						ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix,
 | 
				
			||||||
			      &dirty_fs_roots);
 | 
								      &dirty_fs_roots);
 | 
				
			||||||
	BUG_ON(ret);
 | 
						BUG_ON(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* add_dirty_roots gets rid of all the tree log roots, it is now
 | 
				
			||||||
 | 
						 * safe to free the root of tree log roots
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						btrfs_free_log_root_tree(trans, root->fs_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_commit_tree_roots(trans, root);
 | 
						ret = btrfs_commit_tree_roots(trans, root);
 | 
				
			||||||
	BUG_ON(ret);
 | 
						BUG_ON(ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -843,6 +866,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 | 
				
			||||||
				   chunk_root->node->start);
 | 
									   chunk_root->node->start);
 | 
				
			||||||
	btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
 | 
						btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
 | 
				
			||||||
					 btrfs_header_level(chunk_root->node));
 | 
										 btrfs_header_level(chunk_root->node));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!root->fs_info->log_root_recovering) {
 | 
				
			||||||
 | 
							btrfs_set_super_log_root(&root->fs_info->super_copy, 0);
 | 
				
			||||||
 | 
							btrfs_set_super_log_root_level(&root->fs_info->super_copy, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&root->fs_info->super_for_commit, &root->fs_info->super_copy,
 | 
						memcpy(&root->fs_info->super_for_commit, &root->fs_info->super_copy,
 | 
				
			||||||
	       sizeof(root->fs_info->super_copy));
 | 
						       sizeof(root->fs_info->super_copy));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -857,6 +886,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 | 
				
			||||||
	BUG_ON(ret);
 | 
						BUG_ON(ret);
 | 
				
			||||||
	write_ctree_super(trans, root);
 | 
						write_ctree_super(trans, root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * the super is written, we can safely allow the tree-loggers
 | 
				
			||||||
 | 
						 * to go about their business
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						mutex_unlock(&root->fs_info->tree_log_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	btrfs_finish_extent_commit(trans, root, pinned_copy);
 | 
						btrfs_finish_extent_commit(trans, root, pinned_copy);
 | 
				
			||||||
	mutex_lock(&root->fs_info->trans_mutex);
 | 
						mutex_lock(&root->fs_info->trans_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,4 +98,5 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 | 
				
			||||||
int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
 | 
					int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
 | 
				
			||||||
				   struct btrfs_root *root);
 | 
									   struct btrfs_root *root);
 | 
				
			||||||
void btrfs_throttle(struct btrfs_root *root);
 | 
					void btrfs_throttle(struct btrfs_root *root);
 | 
				
			||||||
 | 
					int btrfs_record_root_in_trans(struct btrfs_root *root);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,12 +81,12 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
 | 
				
			||||||
		memcpy(&key, &root->defrag_progress, sizeof(key));
 | 
							memcpy(&key, &root->defrag_progress, sizeof(key));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	path->lowest_level = 1;
 | 
					 | 
				
			||||||
	path->keep_locks = 1;
 | 
						path->keep_locks = 1;
 | 
				
			||||||
	if (cache_only)
 | 
						if (cache_only)
 | 
				
			||||||
		min_trans = root->defrag_trans_start;
 | 
							min_trans = root->defrag_trans_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = btrfs_search_forward(root, &key, path, cache_only, min_trans);
 | 
						ret = btrfs_search_forward(root, &key, NULL, path,
 | 
				
			||||||
 | 
									   cache_only, min_trans);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (ret > 0) {
 | 
						if (ret > 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2804
									
								
								fs/btrfs/tree-log.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2804
									
								
								fs/btrfs/tree-log.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										41
									
								
								fs/btrfs/tree-log.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								fs/btrfs/tree-log.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2008 Oracle.  All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU General Public
 | 
				
			||||||
 | 
					 * License v2 as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public
 | 
				
			||||||
 | 
					 * License along with this program; if not, write to the
 | 
				
			||||||
 | 
					 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
				
			||||||
 | 
					 * Boston, MA 021110-1307, USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __TREE_LOG_
 | 
				
			||||||
 | 
					#define __TREE_LOG_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_sync_log(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
							   struct btrfs_root *root);
 | 
				
			||||||
 | 
					int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root);
 | 
				
			||||||
 | 
					int btrfs_log_dentry(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
							    struct btrfs_root *root, struct dentry *dentry);
 | 
				
			||||||
 | 
					int btrfs_recover_log_trees(struct btrfs_root *tree_root);
 | 
				
			||||||
 | 
					int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								  struct btrfs_root *root, struct dentry *dentry);
 | 
				
			||||||
 | 
					int btrfs_log_inode(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
							    struct btrfs_root *root, struct inode *inode,
 | 
				
			||||||
 | 
							    int inode_only);
 | 
				
			||||||
 | 
					int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
									 struct btrfs_root *root,
 | 
				
			||||||
 | 
									 const char *name, int name_len,
 | 
				
			||||||
 | 
									 struct inode *dir, u64 index);
 | 
				
			||||||
 | 
					int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
 | 
				
			||||||
 | 
								       struct btrfs_root *root,
 | 
				
			||||||
 | 
								       const char *name, int name_len,
 | 
				
			||||||
 | 
								       struct inode *inode, u64 dirid);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Loading…
	
		Reference in a new issue