Skip to contentSkip to conversation

update btrfs-progs for seed device support

PATCH New Yan Zheng 1 participant 1 message Nov 11, 2008

Subsystems (2)
lore
Share & tools
lore

Yan Zheng

author
#0 lore raw

PATCH 1/1 update btrfs-progs for seed device support

hello,

This patch has following 3 things.

1) Update device management code to match the kernel code.

2) Allocator fixes.

3) Add a program called btrfstune to set/clear the SEEDING super block flags.

Regards

Yan Zheng <[email protected]>

---

btrfstune.c +126 -0
diff -urpN btrfs-progs-orig/btrfstune.c btrfs-progs-2/btrfstune.c
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#define _XOPEN_SOURCE 500
+#define _GNU_SOURCE 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "kerncompat.h"
+#include "ctree.h"
+#include "disk-io.h"
+#include "transaction.h"
+#include "utils.h"
+#include "version.h"
+
+static char *device;
+
+int update_seeding_flag(struct btrfs_root *root, int set_flag)
+{
+	struct btrfs_trans_handle *trans;
+	struct btrfs_super_block *disk_super;
+	u64 super_flags;
+
+	disk_super = &root->fs_info->super_copy;
+	super_flags = btrfs_super_flags(disk_super);
+	if (set_flag) {
+		if (super_flags & BTRFS_SUPER_FLAG_SEEDING) {
+			fprintf(stderr, "seeding flag is already set on %s\n",
+				device);
+			return 1;
+		}
+		super_flags |= BTRFS_SUPER_FLAG_SEEDING;
+	} else {
+		if (!(super_flags & BTRFS_SUPER_FLAG_SEEDING)) {
+			fprintf(stderr, "seeding flag is not set on %s\n",
+				device);
+			return 1;
+		}
+		super_flags &= ~BTRFS_SUPER_FLAG_SEEDING;
+	}
+
+	trans = btrfs_start_transaction(root, 1);
+	btrfs_set_super_flags(disk_super, super_flags);
+	btrfs_commit_transaction(trans, root);
+
+	return 0;
+}
+
+static void print_usage(void)
+{
+	fprintf(stderr, "usage: btrfstune [options] device\n");
+	fprintf(stderr, "\t-S value\tenable/disable seeding\n");
+}
+
+int main(int argc, char *argv[])
+{
+	struct btrfs_root *root;
+	int success = 0;
+	int seeding_flag = 0;
+	int seeding_value = 0;
+	int ret;
+
+	while(1) {
+		int c = getopt(argc, argv, "S:");
+		if (c < 0)
+			break;
+		switch(c) {
+		case 'S':
+			seeding_flag = 1;
+			seeding_value = atoi(optarg);
+			break;
+		default:
+			print_usage();
+			return 1;
+		}
+	}
+
+	argc = argc - optind;
+	device = argv[optind];
+	if (argc != 1) {
+		print_usage();
+		return 1;
+	}
+
+	if (check_mounted(device)) {
+		fprintf(stderr, "%s is mounted\n", device);
+		return 1;
+	}
+
+	root = open_ctree(device, 0, 1);
+
+	if (seeding_flag) {
+		ret = update_seeding_flag(root, seeding_value);
+		if (!ret)
+			success++;
+	}
+
+	if (success > 0) {
+		ret = 0;
+	} else {
+		root->fs_info->readonly = 1;
+		ret = 1;
+	}
+	close_ctree(root);
+
+	return ret;
+}
ctree.c +8 -0
diff -urpN btrfs-progs-orig/ctree.c btrfs-progs-2/ctree.c
@@ -111,6 +111,10 @@ int btrfs_copy_root(struct btrfs_trans_h
 	btrfs_set_header_generation(cow, trans->transid);
 	btrfs_set_header_owner(cow, new_root_objectid);
 	btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);
+	
+	write_extent_buffer(cow, root->fs_info->fsid,
+			    (unsigned long)btrfs_header_fsid(cow),
+			    BTRFS_FSID_SIZE);
 
 	WARN_ON(btrfs_header_generation(buf) > trans->transid);
 	ret = btrfs_inc_ref(trans, new_root, buf, cow, NULL);
@@ -161,6 +165,10 @@ int __btrfs_cow_block(struct btrfs_trans
 	btrfs_set_header_owner(cow, root->root_key.objectid);
 	btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);
 
+	write_extent_buffer(cow, root->fs_info->fsid,
+			    (unsigned long)btrfs_header_fsid(cow),
+			    BTRFS_FSID_SIZE);
+
 	WARN_ON(btrfs_header_generation(buf) > trans->transid);
 	if (btrfs_header_generation(buf) != trans->transid) {
 		different_trans = 1;
ctree.h +18 -0
diff -urpN btrfs-progs-orig/ctree.h btrfs-progs-2/ctree.h
@@ -160,6 +160,9 @@ struct btrfs_dev_item {
 	/* type and info about this device */
 	__le64 type;
 
+	/* expected generation for this device */
+	__le64 generation;
+
 	/* grouping information for allocation decisions */
 	__le32 dev_group;
 
@@ -171,6 +174,9 @@ struct btrfs_dev_item {
 
 	/* btrfs generated uuid for this device */
 	u8 uuid[BTRFS_UUID_SIZE];
+
+	/* uuid of FS who owns this device */
+	u8 fsid[BTRFS_UUID_SIZE];
 } __attribute__ ((__packed__));
 
 struct btrfs_stripe {
@@ -246,6 +252,8 @@ struct btrfs_header {
 					sizeof(struct btrfs_item) - \
 					sizeof(struct btrfs_file_extent_item))
 
+#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32)
+
 /*
  * this is a very generous portion of the super block, giving us
  * room to translate 14 chunks with 3 stripes each.
@@ -524,6 +532,7 @@ struct btrfs_block_group_cache {
 	u64 pinned;
 	u64 flags;
 	int cached;
+	int ro;
 };
 
 struct btrfs_extent_ops {
@@ -744,6 +753,7 @@ BTRFS_SETGET_FUNCS(device_id, struct btr
 BTRFS_SETGET_FUNCS(device_group, struct btrfs_dev_item, dev_group, 32);
 BTRFS_SETGET_FUNCS(device_seek_speed, struct btrfs_dev_item, seek_speed, 8);
 BTRFS_SETGET_FUNCS(device_bandwidth, struct btrfs_dev_item, bandwidth, 8);
+BTRFS_SETGET_FUNCS(device_generation, struct btrfs_dev_item, generation, 64);
 
 BTRFS_SETGET_STACK_FUNCS(stack_device_type, struct btrfs_dev_item, type, 64);
 BTRFS_SETGET_STACK_FUNCS(stack_device_total_bytes, struct btrfs_dev_item,
@@ -763,12 +773,19 @@ BTRFS_SETGET_STACK_FUNCS(stack_device_se
 			 seek_speed, 8);
 BTRFS_SETGET_STACK_FUNCS(stack_device_bandwidth, struct btrfs_dev_item,
 			 bandwidth, 8);
+BTRFS_SETGET_STACK_FUNCS(stack_device_generation, struct btrfs_dev_item,
+			 generation, 64);
 
 static inline char *btrfs_device_uuid(struct btrfs_dev_item *d)
 {
 	return (char *)d + offsetof(struct btrfs_dev_item, uuid);
 }
 
+static inline char *btrfs_device_fsid(struct btrfs_dev_item *d)
+{
+	return (char *)d + offsetof(struct btrfs_dev_item, fsid);
+}
+
 BTRFS_SETGET_FUNCS(chunk_length, struct btrfs_chunk, length, 64);
 BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64);
 BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64);
@@ -1259,6 +1276,7 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snaps
 
 /* struct btrfs_super_block */
 BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
+BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
 BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
 			 generation, 64);
 BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
disk-io.c +23 -6
diff -urpN btrfs-progs-orig/disk-io.c btrfs-progs-2/disk-io.c
@@ -37,14 +37,24 @@
 
 static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
 {
+
+	struct btrfs_fs_devices *fs_devices;
+	int ret = 1;
+
 	if (buf->start != btrfs_header_bytenr(buf))
-		return 1;
+		return ret;
 
-	if (memcmp_extent_buffer(buf, root->fs_info->fsid,
-				 (unsigned long)btrfs_header_fsid(buf),
-				 BTRFS_FSID_SIZE))
-		return 1;
-	return 0;
+	fs_devices = root->fs_info->fs_devices;
+	while (fs_devices) {
+		if (!memcmp_extent_buffer(buf, fs_devices->fsid,
+					  (unsigned long)btrfs_header_fsid(buf),
+					  BTRFS_FSID_SIZE)) {
+			ret = 0;
+			break;
+		}
+		fs_devices = fs_devices->seed;
+	}
+	return ret;
 }
 
 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
@@ -685,6 +695,10 @@ int write_all_supers(struct btrfs_root *
 						      dev_item);
 	list_for_each(cur, head) {
 		dev = list_entry(cur, struct btrfs_device, dev_list);
+		if (!dev->writeable)
+			continue;
+
+		btrfs_set_device_generation(sb, dev_item, 0);
 		btrfs_set_device_type(sb, dev_item, dev->type);
 		btrfs_set_device_id(sb, dev_item, dev->devid);
 		btrfs_set_device_total_bytes(sb, dev_item, dev->total_bytes);
@@ -695,6 +709,9 @@ int write_all_supers(struct btrfs_root *
 		write_extent_buffer(sb, dev->uuid,
 				    (unsigned long)btrfs_device_uuid(dev_item),
 				    BTRFS_UUID_SIZE);
+		write_extent_buffer(sb, dev->fs_devices->fsid,
+				    (unsigned long)btrfs_device_fsid(dev_item),
+				    BTRFS_UUID_SIZE);
 		sb->fd = dev->fd;
 		sb->dev_bytenr = sb->start;
 		btrfs_set_header_flag(sb, BTRFS_HEADER_FLAG_WRITTEN);
extent-tree.c +47 -34

198 lines not on this page · raw message

Makefile +4 -1
diff -urpN btrfs-progs-orig/Makefile btrfs-progs-2/Makefile
@@ -15,7 +15,7 @@ prefix ?= /usr/local
 bindir = $(prefix)/bin
 LIBS=-luuid
 
-progs = btrfsctl btrfsck mkfs.btrfs debug-tree btrfs-show btrfs-vol
+progs = btrfsctl btrfsck mkfs.btrfs debug-tree btrfs-show btrfs-vol btrfstune
 
 # make C=1 to enable sparse
 ifdef C
@@ -52,6 +52,9 @@ mkfs.btrfs: $(objects) mkfs.o
 debug-tree: $(objects) debug-tree.o
 	gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o $(LDFLAGS) $(LIBS)
 
+btrfstune: $(objects) btrfstune.o
+	gcc $(CFLAGS) -o btrfstune $(objects) btrfstune.o $(LDFLAGS) $(LIBS)
+
 dir-test: $(objects) dir-test.o
 	gcc $(CFLAGS) -o dir-test $(objects) dir-test.o $(LDFLAGS) $(LIBS)
 
utils.c +7 -1
diff -urpN btrfs-progs-orig/utils.c btrfs-progs-2/utils.c
@@ -96,7 +96,7 @@ int make_btrfs(int fd, const char *devic
 	btrfs_set_super_root(&super, blocks[1]);
 	btrfs_set_super_chunk_root(&super, blocks[3]);
 	btrfs_set_super_total_bytes(&super, num_bytes);
-	btrfs_set_super_bytes_used(&super, first_free + 5 * leafsize);
+	btrfs_set_super_bytes_used(&super, 5 * leafsize);
 	btrfs_set_super_sectorsize(&super, sectorsize);
 	btrfs_set_super_leafsize(&super, leafsize);
 	btrfs_set_super_nodesize(&super, nodesize);
@@ -252,6 +252,7 @@ int make_btrfs(int fd, const char *devic
 
 	dev_item = btrfs_item_ptr(buf, nritems, struct btrfs_dev_item);
 	btrfs_set_device_id(buf, dev_item, 1);
+	btrfs_set_device_generation(buf, dev_item, 0);
 	btrfs_set_device_total_bytes(buf, dev_item, num_bytes);
 	btrfs_set_device_bytes_used(buf, dev_item,
 				    BTRFS_MKFS_SYSTEM_GROUP_SIZE);
@@ -263,6 +264,9 @@ int make_btrfs(int fd, const char *devic
 	write_extent_buffer(buf, super.dev_item.uuid,
 			    (unsigned long)btrfs_device_uuid(dev_item),
 			    BTRFS_UUID_SIZE);
+	write_extent_buffer(buf, super.fsid,
+			    (unsigned long)btrfs_device_fsid(dev_item),
+			    BTRFS_UUID_SIZE);
 	read_extent_buffer(buf, &super.dev_item, (unsigned long)dev_item,
 			   sizeof(*dev_item));
 
@@ -456,6 +460,7 @@ int btrfs_add_to_fsid(struct btrfs_trans
 	device->io_align = io_align;
 	device->sector_size = sectorsize;
 	device->fd = fd;
+	device->writeable = 1;
 	device->total_bytes = block_count;
 	device->bytes_used = 0;
 	device->total_ios = 0;
@@ -489,6 +494,7 @@ int btrfs_add_to_fsid(struct btrfs_trans
 
 	kfree(buf);
 	list_add(&device->dev_list, &root->fs_info->fs_devices->devices);
+	device->fs_devices = root->fs_info->fs_devices;
 	ret = btrfs_bootstrap_super_map(&root->fs_info->mapping_tree,
 					root->fs_info->fs_devices);
 	BUG_ON(ret);
volumes.c +102 -10

197 lines not on this page · raw message

volumes.h +7 -0
diff -urpN btrfs-progs-orig/volumes.h btrfs-progs-2/volumes.h
@@ -21,11 +21,14 @@
 struct btrfs_device {
 	struct list_head dev_list;
 	struct btrfs_root *dev_root;
+	struct btrfs_fs_devices *fs_devices;
 
 	u64 total_ios;
 
 	int fd;
 
+	int writeable;
+
 	char *name;
 
 	/* these are read off the super block, only in the progs */
@@ -69,6 +72,9 @@ struct btrfs_fs_devices {
 	int lowest_bdev;
 	struct list_head devices;
 	struct list_head list;
+
+	int seeding;
+	struct btrfs_fs_devices *seed;
 };
 
 struct btrfs_bio_stripe {
@@ -120,4 +126,5 @@ struct list_head *btrfs_scanned_uuids(vo
 int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
 			   struct btrfs_root *root, struct btrfs_key *key,
 			   struct btrfs_chunk *chunk, int item_size);
+int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
 #endif