From ddaf7b2a8747bf03255c2c8b05b10755ef6fdd41 Mon Sep 17 00:00:00 2001
From: David Marcin <djmarcin@google.com>
Date: Mon, 21 Nov 2011 20:31:01 -0600
Subject: [PATCH 15/46] btrfs-progs: Add the ability to use the earliest super
 found when opening the ctree.

Signed-off-by: David Marcin <djmarcin@google.com>
---
 convert.c |  6 +++---
 disk-io.c | 20 +++++++++++++-------
 disk-io.h |  2 +-
 volumes.c |  9 ++++++++-
 volumes.h |  6 +++++-
 5 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/convert.c b/convert.c
index 2b3f42f..32250b5 100644
--- a/convert.c
+++ b/convert.c
@@ -2329,7 +2329,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 		fprintf(stderr, "unable to update system chunk\n");
 		goto fail;
 	}
-	root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR);
+	root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR, 0);
 	if (!root) {
 		fprintf(stderr, "unable to open ctree\n");
 		goto fail;
@@ -2390,7 +2390,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 		goto fail;
 	}
 
-	root = open_ctree_fd(fd, devname, 0, O_RDWR);
+	root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
 	if (!root) {
 		fprintf(stderr, "unable to open ctree\n");
 		goto fail;
@@ -2489,7 +2489,7 @@ int do_rollback(const char *devname, int force)
 		fprintf(stderr, "unable to open %s\n", devname);
 		goto fail;
 	}
-	root = open_ctree_fd(fd, devname, 0, O_RDWR);
+	root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
 	if (!root) {
 		fprintf(stderr, "unable to open ctree\n");
 		goto fail;
diff --git a/disk-io.c b/disk-io.c
index 5aa9aa3..2180d69 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -793,7 +793,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
 					     u64 sb_bytenr,
 					     u64 root_tree_bytenr, int writes,
-					     int partial)
+					     int partial, int use_earliest_bdev)
 {
 	u32 sectorsize;
 	u32 nodesize;
@@ -871,8 +871,14 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
 
 	fs_info->super_bytenr = sb_bytenr;
 	disk_super = &fs_info->super_copy;
-	ret = btrfs_read_dev_super(fs_devices->latest_bdev,
-				   disk_super, sb_bytenr);
+	if (use_earliest_bdev) {
+		ret = btrfs_read_dev_super(fs_devices->earliest_bdev,
+					   disk_super, sb_bytenr);
+	} else {
+		ret = btrfs_read_dev_super(fs_devices->latest_bdev,
+					   disk_super, sb_bytenr);
+	}
+
 	if (ret) {
 		printk("No valid btrfs found\n");
 		goto out_devices;
@@ -1049,7 +1055,7 @@ struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
 		fprintf (stderr, "Could not open %s\n", filename);
 		return NULL;
 	}
-	info = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, partial);
+	info = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, partial, 0);
 	close(fp);
 	return info;
 }
@@ -1077,7 +1083,7 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
 		return NULL;
 	}
 	info = __open_ctree_fd(fp, filename, sb_bytenr,
-			       root_tree_bytenr, 0, 0);
+			       root_tree_bytenr, 0, 0, 0);
 	close(fp);
 
 	if (!info)
@@ -1086,10 +1092,10 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
 }
 
 struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
-				 int writes)
+				 int writes, int use_earliest_bdev)
 {
 	struct btrfs_fs_info *info;
-	info = __open_ctree_fd(fp, path, sb_bytenr, 0, writes, 0);
+	info = __open_ctree_fd(fp, path, sb_bytenr, 0, writes, 0, use_earliest_bdev);
 	if (!info)
 		return NULL;
 	return info->fs_root;
diff --git a/disk-io.h b/disk-io.h
index ff87958..28573a9 100644
--- a/disk-io.h
+++ b/disk-io.h
@@ -49,7 +49,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,
 		     struct btrfs_root *root, struct extent_buffer *buf);
 struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes);
 struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
-				 int writes);
+				 int writes, int use_earliest_bdev);
 struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
 				       u64 root_tree_bytenr);
 struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
diff --git a/volumes.c b/volumes.c
index c8fbde3..ba18a5e 100644
--- a/volumes.c
+++ b/volumes.c
@@ -104,6 +104,8 @@ static int device_list_add(const char *path,
 		memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
 		fs_devices->latest_devid = devid;
 		fs_devices->latest_trans = found_transid;
+		fs_devices->earliest_devid = devid;
+		fs_devices->earliest_trans = found_transid;
 		fs_devices->lowest_devid = (u64)-1;
 		device = NULL;
 	} else {
@@ -145,8 +147,11 @@ static int device_list_add(const char *path,
 	if (found_transid > fs_devices->latest_trans) {
 		fs_devices->latest_devid = devid;
 		fs_devices->latest_trans = found_transid;
+	} else if (found_transid < fs_devices->earliest_trans) {
+		fs_devices->earliest_devid = devid;
+		fs_devices->earliest_trans = found_transid;
 	}
-	if (fs_devices->lowest_devid > devid) {
+	if (devid < fs_devices->lowest_devid) {
 		fs_devices->lowest_devid = devid;
 	}
 	*fs_devices_ret = fs_devices;
@@ -197,6 +202,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)
 
 		if (device->devid == fs_devices->latest_devid)
 			fs_devices->latest_bdev = fd;
+		if (device->devid == fs_devices->earliest_devid)
+			fs_devices->earliest_bdev = fd;
 		if (device->devid == fs_devices->lowest_devid)
 			fs_devices->lowest_bdev = fd;
 		device->fd = fd;
diff --git a/volumes.h b/volumes.h
index 911f788..541cd0f 100644
--- a/volumes.h
+++ b/volumes.h
@@ -65,11 +65,15 @@ struct btrfs_device {
 struct btrfs_fs_devices {
 	u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
 
-	/* the device with this id has the most recent coyp of the super */
+	/* the device with this id has the most recent copy of the super */
 	u64 latest_devid;
 	u64 latest_trans;
+	/* the device with this id has the least recent copy of the super */
+	u64 earliest_devid;
+	u64 earliest_trans;
 	u64 lowest_devid;
 	int latest_bdev;
+	int earliest_bdev;
 	int lowest_bdev;
 	struct list_head devices;
 	struct list_head list;
-- 
1.8.0.2

