Btrfs: rework csums and extent item ordering

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 43d4779..5c160c2 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -115,14 +115,14 @@
 		return 1;
 	if (k1.objectid < k2->objectid)
 		return -1;
-	if (k1.offset > k2->offset)
-		return 1;
-	if (k1.offset < k2->offset)
-		return -1;
 	if (k1.flags > k2->flags)
 		return 1;
 	if (k1.flags < k2->flags)
 		return -1;
+	if (k1.offset > k2->offset)
+		return 1;
+	if (k1.offset < k2->offset)
+		return -1;
 	return 0;
 }
 
@@ -1292,7 +1292,6 @@
 				      ioff + size_diff);
 	}
 	/* shift the data */
-printk("truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u\n", new_size, old_size, size_diff, leaf, btrfs_leaf_data(leaf) + data_end + size_diff, old_data_start-data_end, old_data_start, data_end);
 	btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
 		      data_end + size_diff, btrfs_leaf_data(leaf) +
 		      data_end, old_data_start + new_size - data_end);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ca3ab16..d75a4d5 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -44,14 +44,14 @@
  */
 struct btrfs_disk_key {
 	__le64 objectid;
-	__le64 offset;
 	__le32 flags;
+	__le64 offset;
 } __attribute__ ((__packed__));
 
 struct btrfs_key {
 	u64 objectid;
-	u64 offset;
 	u32 flags;
+	u64 offset;
 } __attribute__ ((__packed__));
 
 /*
@@ -227,7 +227,6 @@
 } __attribute__ ((__packed__));
 
 struct btrfs_csum_item {
-	__le64 extent_offset;
 	u8 csum[BTRFS_CSUM_SIZE];
 } __attribute__ ((__packed__));
 
@@ -925,17 +924,6 @@
 	e->num_blocks = cpu_to_le64(val);
 }
 
-static inline u64 btrfs_csum_extent_offset(struct btrfs_csum_item *c)
-{
-	return le64_to_cpu(c->extent_offset);
-}
-
-static inline void btrfs_set_csum_extent_offset(struct btrfs_csum_item *c,
-						u64 val)
-{
-	c->extent_offset = cpu_to_le64(val);
-}
-
 static inline u16 btrfs_device_pathlen(struct btrfs_device_item *d)
 {
 	return le16_to_cpu(d->pathlen);
@@ -1091,7 +1079,6 @@
 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root,
 			  u64 objectid, u64 offset,
-			  u64 extent_offset,
 			  char *data, size_t len);
 int btrfs_csum_verify_file_block(struct btrfs_root *root,
 				 u64 objectid, u64 offset,
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 0ba46bc..cd4137a 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -103,7 +103,7 @@
 	key.objectid = dir;
 	key.flags = 0;
 	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
-	btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1);
+	// btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1);
 	ret = btrfs_name_hash(name, name_len, &key.offset);
 	BUG_ON(ret);
 	while(1) {
@@ -146,19 +146,29 @@
 	int cow = mod != 0;
 	struct btrfs_disk_key *found_key;
 	struct btrfs_leaf *leaf;
+	int overflow = 0;
 
 	key.objectid = dir;
 	key.flags = 0;
 	btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
-	btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1);
 	key.offset = objectid;
-	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
-	if (ret < 0)
-		return ret;
-	if (ret > 0) {
-		if (path->slots[0] == 0)
-			return 1;
-		path->slots[0]--;
+
+	while(1) {
+		btrfs_set_key_overflow(&key, overflow);
+		ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
+		if (ret < 0)
+			return ret;
+		if (ret > 0) {
+			if (overflow >= BTRFS_KEY_OVERFLOW_MAX)
+				return 1;
+			overflow++;
+			btrfs_set_key_overflow(&key, overflow);
+			btrfs_release_path(root, path);
+			continue;
+		} else {
+			/* found */
+			break;
+		}
 	}
 	leaf = btrfs_buffer_leaf(path->nodes[0]);
 	found_key = &leaf->items[path->slots[0]].key;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 06b969c..a2a3f52 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -24,7 +24,6 @@
 			   u64 num_blocks)
 {
 	struct dev_lookup *lookup;
-	char b[BDEVNAME_SIZE];
 	int ret;
 
 	lookup = kmalloc(sizeof(*lookup), GFP_NOFS);
@@ -34,7 +33,6 @@
 	lookup->num_blocks = num_blocks;
 	lookup->bdev = bdev;
 	lookup->device_id = device_id;
-printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks);
 
 	ret = radix_tree_insert(&root->fs_info->dev_radix, block_start +
 				num_blocks - 1, lookup);
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index f49968a..ff8f333 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -62,23 +62,19 @@
 	file_key.offset = offset;
 	file_key.flags = 0;
 	btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
-printk("__lookup for %Lu\n", offset);
 	ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
 	if (ret < 0)
 		goto fail;
 	leaf = btrfs_buffer_leaf(path->nodes[0]);
 	if (ret > 0) {
 		ret = 1;
-		if (path->slots[0] == 0) {
-printk("fail1\n");
+		if (path->slots[0] == 0)
 			goto fail;
-		}
 		path->slots[0]--;
 		btrfs_disk_key_to_cpu(&found_key,
 				      &leaf->items[path->slots[0]].key);
 		if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
 		    found_key.objectid != objectid) {
-printk("fail2 type %u %Lu %Lu\n", btrfs_key_type(&found_key), found_key.objectid, objectid);
 			goto fail;
 		}
 		csum_offset = (offset - found_key.offset) >>
@@ -86,7 +82,6 @@
 		if (csum_offset >=
 		    btrfs_item_size(leaf->items + path->slots[0]) /
 		    sizeof(struct btrfs_csum_item)) {
-printk("fail3, csum offset %lu size %u\n", csum_offset, btrfs_item_size(leaf->items + path->slots[0]) / sizeof(struct btrfs_csum_item));
 			goto fail;
 		}
 	}
@@ -109,26 +104,18 @@
 	struct btrfs_key file_key;
 	int ins_len = mod < 0 ? -1 : 0;
 	int cow = mod != 0;
-	struct btrfs_csum_item *csum_item;
 
-	csum_item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0);
-	if (IS_ERR(csum_item))
-		return PTR_ERR(csum_item);
 	file_key.objectid = objectid;
-	file_key.offset = btrfs_csum_extent_offset(csum_item);
+	file_key.offset = offset;
 	file_key.flags = 0;
 	btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
-	btrfs_release_path(root, path);
-printk("lookup file extent searches for %Lu\n", file_key.offset);
 	ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
-printk("ret is %d\n", ret);
 	return ret;
 }
 
 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root,
 			  u64 objectid, u64 offset,
-			  u64 extent_offset,
 			  char *data, size_t len)
 {
 	int ret;
@@ -151,10 +138,8 @@
 	file_key.offset = offset;
 	file_key.flags = 0;
 	btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
-printk("searching for csum %Lu %Lu\n", objectid, offset);
 	ret = btrfs_search_slot(trans, root, &file_key, path,
 				sizeof(struct btrfs_csum_item), 1);
-printk("ret %d\n", ret);
 	if (ret < 0)
 		goto fail;
 	if (ret == 0) {
@@ -167,15 +152,12 @@
 	path->slots[0]--;
 	leaf = btrfs_buffer_leaf(path->nodes[0]);
 	btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key);
-printk("found key %Lu %Lu %u\n", found_key.objectid, found_key.offset, found_key.flags);
 	csum_offset = (offset - found_key.offset) >>
 			root->fs_info->sb->s_blocksize_bits;
-printk("csum_offset %Lu\n", csum_offset);
 	if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
 	    found_key.objectid != objectid ||
 	    csum_offset >= MAX_CSUM_ITEMS(root)) {
 		btrfs_release_path(root, path);
-printk("insert1\n");
 		goto insert;
 	}
 	if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) /
@@ -183,13 +165,11 @@
 		ret = btrfs_extend_item(trans, root, path,
 					sizeof(struct btrfs_csum_item));
 		BUG_ON(ret);
-printk("item extended\n");
 		goto csum;
 	}
 
 insert:
 	csum_offset = 0;
-printk("inserting item %Lu %Lu %u\n", file_key.objectid, file_key.offset, file_key.flags);
 	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
 				      sizeof(struct btrfs_csum_item));
 	if (ret != 0 && ret != -EEXIST)
@@ -201,12 +181,10 @@
 	item += csum_offset;
 found:
 	ret = btrfs_csum_data(root, data, len, item->csum);
-	btrfs_set_csum_extent_offset(item, extent_offset);
 	btrfs_mark_buffer_dirty(path->nodes[0]);
 fail:
 	btrfs_release_path(root, path);
 	btrfs_free_path(path);
-printk("return ret %d\n", ret);
 	return ret;
 }
 
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 6a56416..b2a2220 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -524,7 +524,7 @@
 	int advance;
 	unsigned char d_type = DT_UNKNOWN;
 	int over = 0;
-	int key_type = BTRFS_DIR_INDEX_KEY;
+	int key_type = BTRFS_DIR_ITEM_KEY;
 
 	/* FIXME, use a real flag for deciding about the key type */
 	if (root->fs_info->tree_root == root)
@@ -561,9 +561,6 @@
 		item = leaf->items + slot;
 		if (btrfs_disk_key_objectid(&item->key) != key.objectid)
 			break;
-		if (key_type == BTRFS_DIR_INDEX_KEY &&
-		    btrfs_disk_key_offset(&item->key) > root->highest_inode)
-			break;
 		if (btrfs_disk_key_type(&item->key) != key_type)
 			continue;
 		if (btrfs_disk_key_offset(&item->key) < filp->f_pos)
@@ -1119,7 +1116,6 @@
 out:
 	btrfs_release_path(root, path);
 	btrfs_free_path(path);
-printk("mapping iblock %lu to %lu\n", iblock, result->b_blocknr);
 	if (trans)
 		btrfs_end_transaction(trans, root);
 	return err;
@@ -1233,7 +1229,6 @@
 				   struct file *file,
 				   struct page **pages,
 				   size_t num_pages,
-				   u64 extent_offset,
 				   loff_t pos,
 				   size_t write_bytes)
 {
@@ -1253,7 +1248,6 @@
 		trans = btrfs_start_transaction(root, 1);
 		btrfs_csum_file_block(trans, root, inode->i_ino,
 				      pages[i]->index << PAGE_CACHE_SHIFT,
-				      extent_offset,
 				      kmap(pages[i]), PAGE_CACHE_SIZE);
 		kunmap(pages[i]);
 		SetPageChecked(pages[i]);
@@ -1275,86 +1269,6 @@
 	return err;
 }
 
-static int drop_csums(struct btrfs_trans_handle *trans,
-			  struct btrfs_root *root,
-			  struct inode *inode,
-			  u64 start, u64 end)
-{
-	struct btrfs_path *path;
-	struct btrfs_leaf *leaf;
-	struct btrfs_key key;
-	int slot;
-	struct btrfs_csum_item *item;
-	char *old_block = NULL;
-	u64 cur = start;
-	u64 found_end;
-	u64 num_csums;
-	u64 item_size;
-	int ret;
-
-	path = btrfs_alloc_path();
-	if (!path)
-		return -ENOMEM;
-	while(cur < end) {
-		item = btrfs_lookup_csum(trans, root, path,
-					 inode->i_ino, cur, 1);
-		if (IS_ERR(item)) {
-			cur += root->blocksize;
-			continue;
-		}
-		leaf = btrfs_buffer_leaf(path->nodes[0]);
-		slot = path->slots[0];
-		btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
-		item_size = btrfs_item_size(leaf->items + slot);
-		num_csums = item_size / sizeof(struct btrfs_csum_item);
-		found_end = key.offset + (num_csums << inode->i_blkbits);
-		cur = found_end;
-
-		if (found_end > end) {
-			char *src;
-			old_block = kmalloc(root->blocksize, GFP_NOFS);
-			src = btrfs_item_ptr(leaf, slot, char);
-			memcpy(old_block, src, item_size);
-		}
-		if (key.offset < start) {
-			u64 new_size = (start - key.offset) >>
-					inode->i_blkbits;
-			new_size *= sizeof(struct btrfs_csum_item);
-			ret = btrfs_truncate_item(trans, root, path, new_size);
-			BUG_ON(ret);
-		} else {
-			btrfs_del_item(trans, root, path);
-		}
-		btrfs_release_path(root, path);
-		if (found_end > end) {
-			char *dst;
-			int i;
-			int new_size;
-
-			num_csums = (found_end - end) >> inode->i_blkbits;
-			new_size = num_csums * sizeof(struct btrfs_csum_item);
-			key.offset = end;
-			ret = btrfs_insert_empty_item(trans, root, path,
-						      &key, new_size);
-			BUG_ON(ret);
-			dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
-					     path->slots[0], char);
-			memcpy(dst, old_block + item_size - new_size,
-			       new_size);
-			item = (struct btrfs_csum_item *)dst;
-			for (i = 0; i < num_csums; i++) {
-				btrfs_set_csum_extent_offset(item, end);
-				item++;
-			}
-			mark_buffer_dirty(path->nodes[0]);
-			kfree(old_block);
-			break;
-		}
-	}
-	btrfs_free_path(path);
-	return 0;
-}
-
 static int drop_extents(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root,
 			  struct inode *inode,
@@ -1376,12 +1290,16 @@
 	if (!path)
 		return -ENOMEM;
 search_again:
-printk("drop extent inode %lu start %Lu end %Lu\n", inode->i_ino, start, end);
 	ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
 				       search_start, -1);
-	if (ret != 0) {
-printk("lookup failed\n");
+	if (ret < 0)
 		goto out;
+	if (ret > 0) {
+		if (path->slots[0] == 0) {
+			ret = -ENOENT;
+			goto out;
+		}
+		path->slots[0]--;
 	}
 	while(1) {
 		keep = 0;
@@ -1390,14 +1308,11 @@
 		slot = path->slots[0];
 		btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
 
-printk("found key %Lu %Lu %u\n", key.objectid, key.offset, key.flags);
-
 		extent = btrfs_item_ptr(leaf, slot,
 					struct btrfs_file_extent_item);
 		extent_end = key.offset +
 			(btrfs_file_extent_num_blocks(extent) <<
 			 inode->i_blkbits);
-printk("extent end is %Lu\n", extent_end);
 		if (key.offset >= end || key.objectid != inode->i_ino) {
 			ret = 0;
 			goto out;
@@ -1420,16 +1335,12 @@
 			keep = 1;
 			WARN_ON(start & (root->blocksize - 1));
 			new_num = (start - key.offset) >> inode->i_blkbits;
-printk("truncating existing extent, was %Lu ", btrfs_file_extent_num_blocks(extent));
 			btrfs_set_file_extent_num_blocks(extent, new_num);
-printk("now %Lu\n", btrfs_file_extent_num_blocks(extent));
-
 			mark_buffer_dirty(path->nodes[0]);
 		}
 		if (!keep) {
 			u64 disk_blocknr;
 			u64 disk_num_blocks;
-printk("del old\n");
 			disk_blocknr = btrfs_file_extent_disk_blocknr(extent);
 			disk_num_blocks =
 				btrfs_file_extent_disk_num_blocks(extent);
@@ -1454,15 +1365,12 @@
 		if (bookend) {
 			/* create bookend */
 			struct btrfs_key ins;
-printk("bookend! extent end %Lu\n", extent_end);
 			ins.objectid = inode->i_ino;
 			ins.offset = end;
 			ins.flags = 0;
 			btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
 
 			btrfs_release_path(root, path);
-			ret = drop_csums(trans, root, inode, start, end);
-			BUG_ON(ret);
 			ret = btrfs_insert_empty_item(trans, root, path, &ins,
 						      sizeof(*extent));
 			BUG_ON(ret);
@@ -1486,10 +1394,9 @@
 
 			btrfs_set_file_extent_generation(extent,
 				    btrfs_file_extent_generation(&old));
-printk("new bookend at offset %Lu, file_extent_offset %Lu, file_extent_num_blocks %Lu\n", end, btrfs_file_extent_offset(extent), btrfs_file_extent_num_blocks(extent));
 			btrfs_mark_buffer_dirty(path->nodes[0]);
 			ret = 0;
-			goto out_nocsum;
+			goto out;
 		}
 next_leaf:
 		if (slot >= btrfs_header_nritems(&leaf->header) - 1) {
@@ -1504,10 +1411,6 @@
 	}
 
 out:
-	ret = drop_csums(trans, root, inode, start, end);
-	BUG_ON(ret);
-
-out_nocsum:
 	btrfs_free_path(path);
 	return ret;
 }
@@ -1556,7 +1459,6 @@
 		head = page_buffers(pages[i]);
 		bh = head;
 		do {
-printk("mapping page %lu to block %Lu\n", pages[i]->index, alloc_extent_start);
 			err = btrfs_map_bh_to_logical(root, bh,
 						      alloc_extent_start);
 			BUG_ON(err);
@@ -1597,7 +1499,6 @@
 	u64 start_pos;
 	u64 num_blocks;
 	u64 alloc_extent_start;
-	u64 orig_extent_start;
 	struct btrfs_trans_handle *trans;
 	struct btrfs_key ins;
 
@@ -1640,7 +1541,6 @@
 				   (pos + count + root->blocksize -1) &
 				   ~(root->blocksize - 1));
 	}
-	orig_extent_start = start_pos;
 	ret = btrfs_alloc_extent(trans, root, num_blocks, 1,
 				 (u64)-1, &ins);
 	BUG_ON(ret);
@@ -1656,7 +1556,6 @@
 		size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset);
 		size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >>
 					PAGE_CACHE_SHIFT;
-printk("num_pages is %lu\n", num_pages);
 
 		memset(pages, 0, sizeof(pages));
 		ret = prepare_pages(root, file, pages, num_pages,
@@ -1670,10 +1569,8 @@
 					   write_bytes, pages, buf);
 		BUG_ON(ret);
 
-printk("2num_pages is %lu\n", num_pages);
 		ret = dirty_and_release_pages(NULL, root, file, pages,
-					      num_pages, orig_extent_start,
-					      pos, write_bytes);
+					      num_pages, pos, write_bytes);
 		BUG_ON(ret);
 		btrfs_drop_pages(pages, num_pages);