diff --git a/cmds-check.c b/cmds-check.c
index b962b15..5b8417c 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -1504,15 +1504,121 @@ static int repair_inode_orphan_item(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
+static int add_missing_dir_index(struct btrfs_trans_handle *trans,
+				 struct btrfs_root *root,
+				 struct cache_tree *inode_cache,
+				 struct btrfs_path *path,
+				 struct inode_record *rec,
+				 struct inode_backref *backref)
+{
+	struct btrfs_dir_item *dir_item;
+	struct extent_buffer *leaf;
+	struct btrfs_key key;
+	struct btrfs_disk_key disk_key;
+	struct inode_record *dir_rec;
+	unsigned long name_ptr;
+	u32 data_size = sizeof(*dir_item) + backref->namelen;
+	int ret;
+
+	printf("repairing missing dir index item for inode %llu\n",
+	       (unsigned long long)rec->ino);
+	key.objectid = backref->dir;
+	key.type = BTRFS_DIR_INDEX_KEY;
+	key.offset = backref->index;
+
+	ret = btrfs_insert_empty_item(trans, root, path, &key, data_size);
+	if (ret)
+		return ret;
+
+	leaf = path->nodes[0];
+	dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
+
+	disk_key.objectid = cpu_to_le64(rec->ino);
+	disk_key.type = BTRFS_INODE_ITEM_KEY;
+	disk_key.offset = 0;
+
+	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
+	btrfs_set_dir_type(leaf, dir_item, imode_to_type(rec->imode));
+	btrfs_set_dir_data_len(leaf, dir_item, 0);
+	btrfs_set_dir_name_len(leaf, dir_item, backref->namelen);
+	name_ptr = (unsigned long)(dir_item + 1);
+	write_extent_buffer(leaf, backref->name, name_ptr, backref->namelen);
+	btrfs_mark_buffer_dirty(leaf);
+	btrfs_release_path(path);
+	backref->found_dir_index = 1;
+
+	dir_rec = get_inode_rec(inode_cache, backref->dir, 0);
+	if (!dir_rec)
+		return 0;
+	dir_rec->found_size += backref->namelen;
+	if (dir_rec->found_size == dir_rec->isize &&
+	    (dir_rec->errors & I_ERR_DIR_ISIZE_WRONG))
+		dir_rec->errors &= ~I_ERR_DIR_ISIZE_WRONG;
+	if (dir_rec->found_size != dir_rec->isize)
+		dir_rec->errors |= I_ERR_DIR_ISIZE_WRONG;
+
+	return 0;
+
+}
+
+static int repair_inode_backrefs(struct btrfs_root *root,
+				 struct inode_record *rec,
+				 struct cache_tree *inode_cache)
+{
+	struct btrfs_trans_handle *trans;
+	struct btrfs_path *path;
+	struct inode_backref *tmp, *backref;
+	u64 root_dirid = btrfs_root_dirid(&root->root_item);
+	int ret;
+	int repaired = 0;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	trans = btrfs_start_transaction(root, 1);
+	if (IS_ERR(trans)) {
+		btrfs_free_path(path);
+		return PTR_ERR(trans);
+	}
+
+	list_for_each_entry_safe(backref, tmp, &rec->backrefs, list) {
+		/* Index 0 for root dir's are special, don't mess with it */
+		if (rec->ino == root_dirid && backref->index == 0)
+			continue;
+
+		if (!backref->found_dir_index && backref->found_inode_ref) {
+			ret = add_missing_dir_index(trans, root, inode_cache,
+						    path, rec, backref);
+			if (!ret)
+				repaired = 1;
+			else
+				break;
+		}
+
+		if (backref->found_dir_item && backref->found_dir_index) {
+			if (!backref->errors && backref->found_inode_ref) {
+				list_del(&backref->list);
+				free(backref);
+			}
+		}
+	}
+
+	BUG_ON(repaired && ret); /* Poor mans transaction abort */
+	btrfs_commit_transaction(trans, root);
+	btrfs_free_path(path);
+
+	return ret;
+}
+
 static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 {
 	struct btrfs_trans_handle *trans;
 	struct btrfs_path *path;
 	int ret = 0;
 
-	/* So far we just fix dir isize wrong */
 	if (!(rec->errors & (I_ERR_DIR_ISIZE_WRONG | I_ERR_NO_ORPHAN_ITEM)))
-		return 1;
+		return rec->errors;
 
 	path = btrfs_alloc_path();
 	if (!path)
@@ -1550,6 +1656,27 @@ static int check_inode_recs(struct btrfs_root *root,
 		return 0;
 	}
 
+	/*
+	 * We need to repair backrefs first because we could change some of the
+	 * errors in the inode recs.
+	 *
+	 * For example, if we were missing a dir index then the directories
+	 * isize would be wrong, so if we fixed the isize to what we thought it
+	 * would be and then fixed the backref we'd still have a invalid fs, so
+	 * we need to add back the dir index and then check to see if the isize
+	 * is still wrong.
+	 */
+	cache = search_cache_extent(inode_cache, 0);
+	while (repair && cache) {
+		node = container_of(cache, struct ptr_node, cache);
+		rec = node->data;
+		cache = next_cache_extent(cache);
+
+		if (list_empty(&rec->backrefs))
+			continue;
+		repair_inode_backrefs(root, rec, inode_cache);
+	}
+
 	rec = get_inode_rec(inode_cache, root_dirid, 0);
 	if (rec) {
 		ret = check_root_dir(rec);
