summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--man/mkfs.btrfs.8.in6
-rw-r--r--mkfs.c100
3 files changed, 105 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 456dd4f2..bea8ae96 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
INSTALL = install
prefix ?= /usr/local
bindir = $(prefix)/bin
-LIBS=-luuid -lm -lz
+LIBS=-luuid -lblkid -lm -lz
ifeq ("$(origin V)", "command line")
BUILD_VERBOSE = $(V)
diff --git a/man/mkfs.btrfs.8.in b/man/mkfs.btrfs.8.in
index 45386587..41163e03 100644
--- a/man/mkfs.btrfs.8.in
+++ b/man/mkfs.btrfs.8.in
@@ -6,6 +6,7 @@ mkfs.btrfs \- create a btrfs filesystem
[ \fB\-A\fP\fI alloc-start\fP ]
[ \fB\-b\fP\fI byte-count\fP ]
[ \fB\-d\fP\fI data-profile\fP ]
+[ \fB\-f\fP\fI ]
[ \fB\-l\fP\fI leafsize\fP ]
[ \fB\-L\fP\fI label\fP ]
[ \fB\-m\fP\fI metadata profile\fP ]
@@ -38,6 +39,11 @@ mkfs.btrfs uses all the available storage for the filesystem.
Specify how the data must be spanned across the devices specified. Valid
values are raid0, raid1, raid10 or single.
.TP
+\fB\-f\fR
+Force overwrite when an existing filesystem is detected on the device.
+By default, mkfs.btrfs will not write to the device if it suspects that
+there is a filesystem or partition table on the device already.
+.TP
\fB\-l\fR, \fB\-\-leafsize \fIsize\fR
Specify the leaf size, the least data item in which btrfs stores data. The
default value is the page size.
diff --git a/mkfs.c b/mkfs.c
index 2210312c..5ece1867 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -41,7 +41,6 @@
#include <attr/xattr.h>
#include <blkid/blkid.h>
#include <ftw.h>
-#include "kerncompat.h"
#include "ctree.h"
#include "disk-io.h"
#include "volumes.h"
@@ -1260,6 +1259,86 @@ static int is_ssd(const char *file)
return !atoi((const char *)&rotational);
}
+/*
+ * Check for existing filesystem or partition table on device.
+ * Returns:
+ * 1 for existing fs or partition
+ * 0 for nothing found
+ * -1 for internal error
+ */
+static int
+check_overwrite(
+ char *device)
+{
+ const char *type;
+ blkid_probe pr = NULL;
+ int ret;
+ blkid_loff_t size;
+
+ if (!device || !*device)
+ return 0;
+
+ ret = -1; /* will reset on success of all setup calls */
+
+ pr = blkid_new_probe_from_filename(device);
+ if (!pr)
+ goto out;
+
+ size = blkid_probe_get_size(pr);
+ if (size < 0)
+ goto out;
+
+ /* nothing to overwrite on a 0-length device */
+ if (size == 0) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = blkid_probe_enable_partitions(pr, 1);
+ if (ret < 0)
+ goto out;
+
+ ret = blkid_do_fullprobe(pr);
+ if (ret < 0)
+ goto out;
+
+ /*
+ * Blkid returns 1 for nothing found and 0 when it finds a signature,
+ * but we want the exact opposite, so reverse the return value here.
+ *
+ * In addition print some useful diagnostics about what actually is
+ * on the device.
+ */
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
+ fprintf(stderr,
+ "%s appears to contain an existing "
+ "filesystem (%s).\n", device, type);
+ } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
+ fprintf(stderr,
+ "%s appears to contain a partition "
+ "table (%s).\n", device, type);
+ } else {
+ fprintf(stderr,
+ "%s appears to contain something weird "
+ "according to blkid\n", device);
+ }
+ ret = 1;
+
+out:
+ if (pr)
+ blkid_free_probe(pr);
+ if (ret == -1)
+ fprintf(stderr,
+ "probe of %s failed, cannot detect "
+ "existing filesystem.\n", device);
+ return ret;
+}
+
int main(int ac, char **av)
{
char *file;
@@ -1287,6 +1366,7 @@ int main(int ac, char **av)
int metadata_profile_opt = 0;
int nodiscard = 0;
int ssd = 0;
+ int force_overwrite = 0;
char *source_dir = NULL;
int source_dir_set = 0;
@@ -1299,7 +1379,7 @@ int main(int ac, char **av)
while(1) {
int c;
- c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMK", long_options,
+ c = getopt_long(ac, av, "A:b:fl:n:s:m:d:L:r:VMK", long_options,
&option_index);
if (c < 0)
break;
@@ -1307,6 +1387,9 @@ int main(int ac, char **av)
case 'A':
alloc_start = parse_size(optarg);
break;
+ case 'f':
+ force_overwrite = 1;
+ break;
case 'd':
data_profile = parse_profile(optarg);
data_profile_opt = 1;
@@ -1376,6 +1459,12 @@ int main(int ac, char **av)
fprintf(stderr, "%s is a swap device\n", file);
exit(1);
}
+ if (!force_overwrite) {
+ if (check_overwrite(file)) {
+ fprintf(stderr, "Use the -f option to force overwrite.\n");
+ exit(1);
+ }
+ }
ret = check_mounted(file);
if (ret < 0) {
fprintf(stderr, "error checking %s mount status\n", file);
@@ -1485,6 +1574,13 @@ int main(int ac, char **av)
int old_mixed = mixed;
file = av[optind++];
+ if (!force_overwrite) {
+ if (check_overwrite(file)) {
+ fprintf(stderr, "Use the -f option to force overwrite.\n");
+ exit(1);
+ }
+ }
+
ret = is_swap_device(file);
if (ret < 0) {
fprintf(stderr, "error checking %s status: %s\n", file,