diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index bef61ee883e1f1093b252dce81b78cc67d510252..f691542dfa1537e8d1e5a1bb3220c2fe9b997e29 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1766,8 +1766,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
 
 	/* first try to make some room by pushing left and right */
 	wret = push_leaf_left(trans, root, path, data_size);
-	if (wret < 0)
+	if (wret < 0) {
 		return wret;
+	}
 	if (wret) {
 		wret = push_leaf_right(trans, root, path, data_size);
 		if (wret < 0)
@@ -1777,8 +1778,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
 
 	/* did the pushes work? */
 	if (btrfs_leaf_free_space(root, l) >=
-	    sizeof(struct btrfs_item) + data_size)
+	    sizeof(struct btrfs_item) + data_size) {
 		return 0;
+	}
 
 	if (!path->nodes[1]) {
 		ret = insert_new_root(trans, root, path, 1);
@@ -1822,7 +1824,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
 				return ret;
 			}
 			mid = slot;
-			double_split = 1;
+			if (mid != nritems &&
+			    leaf_space_used(l, mid, nritems - mid) +
+			    space_needed > BTRFS_LEAF_DATA_SIZE(root)) {
+				double_split = 1;
+			}
 		}
 	} else {
 		if (leaf_space_used(l, 0, mid + 1) + space_needed >
@@ -1910,8 +1916,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
 
 	BUG_ON(path->slots[0] < 0);
 
-	if (!double_split)
+	if (!double_split) {
 		return ret;
+	}
 
 	right = btrfs_alloc_free_block(trans, root, root->leafsize,
 				       l->start, 0);
@@ -2048,7 +2055,11 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
 	old_data = btrfs_item_end_nr(leaf, slot);
 
 	BUG_ON(slot < 0);
-	BUG_ON(slot >= nritems);
+	if (slot >= nritems) {
+		btrfs_print_leaf(root, leaf);
+		printk("slot %d too large, nritems %d\n", slot, nritems);
+		BUG_ON(1);
+	}
 
 	/*
 	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
@@ -2132,6 +2143,9 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 
 	if (btrfs_leaf_free_space(root, leaf) <
 	    sizeof(struct btrfs_item) + data_size) {
+		btrfs_print_leaf(root, leaf);
+		printk("not enough freespace need %u have %d\n",
+		       data_size, btrfs_leaf_free_space(root, leaf));
 		BUG();
 	}
 
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 54c754dd9a148a0bbd7a56dfa713b92e0efc0041..18994c53106cf1125c7a74e7d12ee713a008a61a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1137,7 +1137,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end);
 extern struct file_operations btrfs_file_operations;
 int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 *hint_block);
+		       u64 start, u64 end, u64 inline_end, u64 *hint_block);
 /* tree-defrag.c */
 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
 			struct btrfs_root *root, int cache_only);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 844d8807e44a6aee49c9b9b1ec5d31dfb6875b96..1af2b6534dadd190db5585ad67e9afacadf93401 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -82,8 +82,9 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages)
 
 static int insert_inline_extent(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root, struct inode *inode,
-				u64 offset, ssize_t size,
-				struct page *page, size_t page_offset)
+				u64 offset, size_t size,
+				struct page **pages, size_t page_offset,
+				int num_pages)
 {
 	struct btrfs_key key;
 	struct btrfs_path *path;
@@ -91,9 +92,12 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
 	char *kaddr;
 	unsigned long ptr;
 	struct btrfs_file_extent_item *ei;
+	struct page *page;
 	u32 datasize;
 	int err = 0;
 	int ret;
+	int i;
+	ssize_t cur_size;
 
 	path = btrfs_alloc_path();
 	if (!path)
@@ -104,25 +108,97 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
 	key.objectid = inode->i_ino;
 	key.offset = offset;
 	btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
-	BUG_ON(size >= PAGE_CACHE_SIZE);
-	datasize = btrfs_file_extent_calc_inline_size(size);
+	datasize = btrfs_file_extent_calc_inline_size(offset + size);
 
-	ret = btrfs_insert_empty_item(trans, root, path, &key,
-				      datasize);
-	if (ret) {
+	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+	if (ret < 0) {
 		err = ret;
 		goto fail;
 	}
-	leaf = path->nodes[0];
-	ei = btrfs_item_ptr(leaf, path->slots[0],
-			    struct btrfs_file_extent_item);
-	btrfs_set_file_extent_generation(leaf, ei, trans->transid);
-	btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE);
-	ptr = btrfs_file_extent_inline_start(ei);
-
-	kaddr = kmap_atomic(page, KM_USER1);
-	write_extent_buffer(leaf, kaddr + page_offset, ptr, size);
-	kunmap_atomic(kaddr, KM_USER1);
+	if (ret == 1) {
+		path->slots[0]--;
+		leaf = path->nodes[0];
+		ei = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+
+		if (btrfs_file_extent_type(leaf, ei) !=
+		    BTRFS_FILE_EXTENT_INLINE) {
+			goto insert;
+		}
+		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+		ret = 0;
+	}
+	if (ret == 0) {
+		u32 found_size;
+		u64 found_start;
+
+		leaf = path->nodes[0];
+		ei = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+
+		if (btrfs_file_extent_type(leaf, ei) !=
+		    BTRFS_FILE_EXTENT_INLINE) {
+			err = ret;
+			btrfs_print_leaf(root, leaf);
+			printk("found wasn't inline offset %Lu inode %lu\n",
+			       offset, inode->i_ino);
+			goto fail;
+		}
+		found_start = key.offset;
+		found_size = btrfs_file_extent_inline_len(leaf,
+					  btrfs_item_nr(leaf, path->slots[0]));
+
+		if (found_size < offset + size) {
+			btrfs_release_path(root, path);
+			ret = btrfs_search_slot(trans, root, &key, path,
+						offset + size - found_size -
+						found_start, 1);
+			BUG_ON(ret != 0);
+			ret = btrfs_extend_item(trans, root, path,
+						offset + size - found_size -
+						found_start);
+			if (ret) {
+				err = ret;
+				goto fail;
+			}
+			leaf = path->nodes[0];
+			ei = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
+		}
+	} else {
+insert:
+		btrfs_release_path(root, path);
+		ret = btrfs_insert_empty_item(trans, root, path, &key,
+					      datasize);
+		if (ret) {
+			err = ret;
+			printk("got bad ret %d\n", ret);
+			goto fail;
+		}
+		leaf = path->nodes[0];
+		ei = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		btrfs_set_file_extent_generation(leaf, ei, trans->transid);
+		btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE);
+	}
+	ptr = btrfs_file_extent_inline_start(ei) + offset;
+
+	cur_size = size;
+	i = 0;
+	while (size > 0) {
+		page = pages[i];
+		kaddr = kmap_atomic(page, KM_USER0);
+		cur_size = min(PAGE_CACHE_SIZE - page_offset, size);
+		write_extent_buffer(leaf, kaddr + page_offset, ptr, cur_size);
+		kunmap_atomic(kaddr, KM_USER0);
+		page_offset = 0;
+		ptr += cur_size;
+		size -= cur_size;
+		if (i >= num_pages) {
+			printk("i %d num_pages %d\n", i, num_pages);
+		}
+		i++;
+	}
 	btrfs_mark_buffer_dirty(leaf);
 fail:
 	btrfs_free_path(path);
@@ -193,6 +269,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
 			err = btrfs_drop_extents(trans, root, inode,
 						 last_pos_in_file,
 						 last_pos_in_file + hole_size,
+						 last_pos_in_file,
 						 &hint_byte);
 			if (err)
 				goto failed;
@@ -210,11 +287,12 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
 	 * either allocate an extent for the new bytes or setup the key
 	 * to show we are doing inline data in the extent
 	 */
-	inline_size = end_pos - start_pos;
-	if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size ||
-	    inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
-	    inline_size >= PAGE_CACHE_SIZE) {
+	inline_size = end_pos;
+	if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
+	    inline_size > 16384 ||
+	    inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
 		u64 last_end;
+
 		for (i = 0; i < num_pages; i++) {
 			struct page *p = pages[i];
 			SetPageUptodate(p);
@@ -225,22 +303,18 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
 		set_extent_delalloc(em_tree, start_pos, end_of_last_block,
 				 GFP_NOFS);
 	} else {
-		struct page *p = pages[0];
+		u64 aligned_end;
 		/* step one, delete the existing extents in this range */
+		aligned_end = (pos + write_bytes + root->sectorsize - 1) &
+			~((u64)root->sectorsize - 1);
 		err = btrfs_drop_extents(trans, root, inode, start_pos,
-			 (pos + write_bytes + root->sectorsize -1) &
-			 ~((u64)root->sectorsize - 1), &hint_byte);
+					 aligned_end, end_pos, &hint_byte);
 		if (err)
 			goto failed;
-
 		err = insert_inline_extent(trans, root, inode, start_pos,
-					   end_pos - start_pos, p, 0);
+					   end_pos - start_pos, pages, 0,
+					   num_pages);
 		BUG_ON(err);
-		em->start = start_pos;
-		em->end = end_pos - 1;
-		em->block_start = EXTENT_MAP_INLINE;
-		em->block_end = EXTENT_MAP_INLINE;
-		add_extent_mapping(em_tree, em);
 	}
 	if (end_pos > isize) {
 		i_size_write(inode, end_pos);
@@ -285,7 +359,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end)
  */
 int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 *hint_byte)
+		       u64 start, u64 end, u64 inline_end, u64 *hint_byte)
 {
 	int ret;
 	struct btrfs_key key;
@@ -401,8 +475,8 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 					BUG_ON(ret);
 				}
 			}
-			WARN_ON(found_inline);
-			bookend = 1;
+			if (!found_inline)
+				bookend = 1;
 		}
 		/* truncate existing extent */
 		if (start > key.offset) {
@@ -425,8 +499,14 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 				btrfs_set_file_extent_num_bytes(leaf, extent,
 								new_num);
 				btrfs_mark_buffer_dirty(leaf);
-			} else {
-				WARN_ON(1);
+			} else if (end > extent_end &&
+				   key.offset < inline_end &&
+				   inline_end < extent_end) {
+				u32 new_size;
+				new_size = btrfs_file_extent_calc_inline_size(
+						   inline_end - key.offset);
+				btrfs_truncate_item(trans, root, path,
+						    new_size);
 			}
 		}
 		/* delete the entire extent */
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d6b3a55ed8e0ce462b1522e882ace5a8fd72a018..84f496c838c99d5e25b35d57a820947634946f58 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -87,7 +87,7 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
 	BUG_ON(!trans);
 	num_bytes = (end - start + blocksize) & ~(blocksize - 1);
 	ret = btrfs_drop_extents(trans, root, inode,
-				 start, start + num_bytes, &alloc_hint);
+				 start, start + num_bytes, start, &alloc_hint);
 
 	ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0,
 				 alloc_hint, (u64)-1, &ins, 1);
@@ -776,7 +776,8 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 		trans = btrfs_start_transaction(root, 1);
 		btrfs_set_trans_block_group(trans, inode);
 		err = btrfs_drop_extents(trans, root, inode,
-					 pos, pos + hole_size, &alloc_hint);
+					 pos, pos + hole_size, pos,
+					 &alloc_hint);
 
 		err = btrfs_insert_file_extent(trans, root, inode->i_ino,
 					       pos, 0, 0, hole_size);
@@ -1581,7 +1582,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 	} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
 		unsigned long ptr;
 		char *map;
-		u32 size;
+		size_t size;
+		size_t extent_offset;
+		size_t copy_size;
 
 		size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf,
 						    path->slots[0]));
@@ -1600,26 +1603,31 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 			goto not_found_em;
 		}
 
+		extent_offset = (page->index << PAGE_CACHE_SHIFT) -
+			extent_start;
+		ptr = btrfs_file_extent_inline_start(item) + extent_offset;
+		map = kmap(page);
+		copy_size = min(PAGE_CACHE_SIZE - page_offset,
+				size - extent_offset);
+
 		em->block_start = EXTENT_MAP_INLINE;
 		em->block_end = EXTENT_MAP_INLINE;
-		em->start = extent_start;
-		em->end = extent_end;
+		em->start = extent_start + extent_offset;
+		em->end = (em->start + copy_size -1) |
+			((u64)root->sectorsize -1);
 
 		if (!page) {
 			goto insert;
 		}
 
-		ptr = btrfs_file_extent_inline_start(item);
-		map = kmap(page);
-		read_extent_buffer(leaf, map + page_offset, ptr, size);
+		read_extent_buffer(leaf, map + page_offset, ptr, copy_size);
 		/*
-		memset(map + page_offset + size, 0,
-		       root->sectorsize - (page_offset + size));
+		memset(map + page_offset + copy_size, 0,
+		       PAGE_CACHE_SIZE - copy_size - page_offset);
 		       */
 		flush_dcache_page(page);
 		kunmap(page);
-		set_extent_uptodate(em_tree, extent_start,
-				    extent_end, GFP_NOFS);
+		set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS);
 		goto insert;
 	} else {
 		printk("unkknown found_type %d\n", found_type);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 5c4370f3a5b85046a5f64e677b35bdd1951d6f98..f94aa1f97a0a8999f6c9b1b0e46585a475bd94ed 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -280,7 +280,6 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
 error_bdev:
 	close_bdev_excl(bdev);
 error:
-printk("get_sb failed\n");
 	return error;
 }
 /* end copy & paste */
@@ -295,7 +294,6 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
 	ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
 			btrfs_fill_super, mnt,
 			subvol_name ? subvol_name : "default");
-printk("btrfs_get_sb returns %d\n", ret);
 	return ret;
 }