summaryrefslogtreecommitdiff
path: root/btrfstune.c
diff options
context:
space:
mode:
Diffstat (limited to 'btrfstune.c')
-rw-r--r--btrfstune.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/btrfstune.c b/btrfstune.c
new file mode 100644
index 00000000..47830c5a
--- /dev/null
+++ b/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;
+}