btrfs-progs: move mkfs helper implementation out of utils
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
11c83cefb8
commit
ed4c7428b7
3
Makefile
3
Makefile
|
@ -101,7 +101,8 @@ cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
|
|||
cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
|
||||
cmds-restore.o cmds-rescue.o chunk-recover.o super-recover.o \
|
||||
cmds-property.o cmds-fi-usage.o cmds-inspect-dump-tree.o \
|
||||
cmds-inspect-dump-super.o cmds-inspect-tree-stats.o cmds-fi-du.o
|
||||
cmds-inspect-dump-super.o cmds-inspect-tree-stats.o cmds-fi-du.o \
|
||||
mkfs/common.o
|
||||
libbtrfs_objects = send-stream.o send-utils.o kernel-lib/rbtree.o btrfs-list.o \
|
||||
kernel-lib/crc32c.o \
|
||||
uuid-tree.o utils-lib.o rbtree-utils.o
|
||||
|
|
283
mkfs/common.c
283
mkfs/common.c
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <blkid/blkid.h>
|
||||
#include <fcntl.h>
|
||||
#include "ctree.h"
|
||||
#include "disk-io.h"
|
||||
#include "volumes.h"
|
||||
|
@ -437,3 +439,284 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
u64 btrfs_min_dev_size(u32 nodesize)
|
||||
{
|
||||
return 2 * (BTRFS_MKFS_SYSTEM_GROUP_SIZE +
|
||||
btrfs_min_global_blk_rsv_size(nodesize));
|
||||
}
|
||||
|
||||
/*
|
||||
* Btrfs minimum size calculation is complicated, it should include at least:
|
||||
* 1. system group size
|
||||
* 2. minimum global block reserve
|
||||
* 3. metadata used at mkfs
|
||||
* 4. space reservation to create uuid for first mount.
|
||||
* Also, raid factor should also be taken into consideration.
|
||||
* To avoid the overkill calculation, (system group + global block rsv) * 2
|
||||
* for *EACH* device should be good enough.
|
||||
*/
|
||||
u64 btrfs_min_global_blk_rsv_size(u32 nodesize)
|
||||
{
|
||||
return (u64)nodesize << 10;
|
||||
}
|
||||
|
||||
#define isoctal(c) (((c) & ~7) == '0')
|
||||
|
||||
static inline void translate(char *f, char *t)
|
||||
{
|
||||
while (*f != '\0') {
|
||||
if (*f == '\\' &&
|
||||
isoctal(f[1]) && isoctal(f[2]) && isoctal(f[3])) {
|
||||
*t++ = 64*(f[1] & 7) + 8*(f[2] & 7) + (f[3] & 7);
|
||||
f += 4;
|
||||
} else
|
||||
*t++ = *f++;
|
||||
}
|
||||
*t = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the swap device.
|
||||
* Returns 1 if swap device, < 0 on error or 0 if not swap device.
|
||||
*/
|
||||
static int is_swap_device(const char *file)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat st_buf;
|
||||
dev_t dev;
|
||||
ino_t ino = 0;
|
||||
char tmp[PATH_MAX];
|
||||
char buf[PATH_MAX];
|
||||
char *cp;
|
||||
int ret = 0;
|
||||
|
||||
if (stat(file, &st_buf) < 0)
|
||||
return -errno;
|
||||
if (S_ISBLK(st_buf.st_mode))
|
||||
dev = st_buf.st_rdev;
|
||||
else if (S_ISREG(st_buf.st_mode)) {
|
||||
dev = st_buf.st_dev;
|
||||
ino = st_buf.st_ino;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
if ((f = fopen("/proc/swaps", "r")) == NULL)
|
||||
return 0;
|
||||
|
||||
/* skip the first line */
|
||||
if (fgets(tmp, sizeof(tmp), f) == NULL)
|
||||
goto out;
|
||||
|
||||
while (fgets(tmp, sizeof(tmp), f) != NULL) {
|
||||
if ((cp = strchr(tmp, ' ')) != NULL)
|
||||
*cp = '\0';
|
||||
if ((cp = strchr(tmp, '\t')) != NULL)
|
||||
*cp = '\0';
|
||||
translate(tmp, buf);
|
||||
if (stat(buf, &st_buf) != 0)
|
||||
continue;
|
||||
if (S_ISBLK(st_buf.st_mode)) {
|
||||
if (dev == st_buf.st_rdev) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
} else if (S_ISREG(st_buf.st_mode)) {
|
||||
if (dev == st_buf.st_dev && ino == st_buf.st_ino) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(const 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a device is suitable for btrfs
|
||||
* returns:
|
||||
* 1: something is wrong, an error is printed
|
||||
* 0: all is fine
|
||||
*/
|
||||
int test_dev_for_mkfs(const char *file, int force_overwrite)
|
||||
{
|
||||
int ret, fd;
|
||||
struct stat st;
|
||||
|
||||
ret = is_swap_device(file);
|
||||
if (ret < 0) {
|
||||
error("checking status of %s: %s", file, strerror(-ret));
|
||||
return 1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
error("%s is a swap device", file);
|
||||
return 1;
|
||||
}
|
||||
if (!force_overwrite) {
|
||||
if (check_overwrite(file)) {
|
||||
error("use the -f option to force overwrite of %s",
|
||||
file);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ret = check_mounted(file);
|
||||
if (ret < 0) {
|
||||
error("cannot check mount status of %s: %s", file,
|
||||
strerror(-ret));
|
||||
return 1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
error("%s is mounted", file);
|
||||
return 1;
|
||||
}
|
||||
/* check if the device is busy */
|
||||
fd = open(file, O_RDWR|O_EXCL);
|
||||
if (fd < 0) {
|
||||
error("unable to open %s: %s", file, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (fstat(fd, &st)) {
|
||||
error("unable to stat %s: %s", file, strerror(errno));
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
error("%s is not a block device", file);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_vol_small(const char *file)
|
||||
{
|
||||
int fd = -1;
|
||||
int e;
|
||||
struct stat st;
|
||||
u64 size;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
e = -errno;
|
||||
close(fd);
|
||||
return e;
|
||||
}
|
||||
size = btrfs_device_size(fd, &st);
|
||||
if (size == 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (size < BTRFS_MKFS_SMALL_VOLUME_SIZE) {
|
||||
close(fd);
|
||||
return 1;
|
||||
} else {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int test_minimum_size(const char *file, u32 nodesize)
|
||||
{
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (stat(file, &statbuf) < 0) {
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
if (btrfs_device_size(fd, &statbuf) < btrfs_min_dev_size(nodesize)) {
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
281
utils.c
281
utils.c
|
@ -1746,159 +1746,6 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define isoctal(c) (((c) & ~7) == '0')
|
||||
|
||||
static inline void translate(char *f, char *t)
|
||||
{
|
||||
while (*f != '\0') {
|
||||
if (*f == '\\' &&
|
||||
isoctal(f[1]) && isoctal(f[2]) && isoctal(f[3])) {
|
||||
*t++ = 64*(f[1] & 7) + 8*(f[2] & 7) + (f[3] & 7);
|
||||
f += 4;
|
||||
} else
|
||||
*t++ = *f++;
|
||||
}
|
||||
*t = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the swap device.
|
||||
* Returns 1 if swap device, < 0 on error or 0 if not swap device.
|
||||
*/
|
||||
static int is_swap_device(const char *file)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat st_buf;
|
||||
dev_t dev;
|
||||
ino_t ino = 0;
|
||||
char tmp[PATH_MAX];
|
||||
char buf[PATH_MAX];
|
||||
char *cp;
|
||||
int ret = 0;
|
||||
|
||||
if (stat(file, &st_buf) < 0)
|
||||
return -errno;
|
||||
if (S_ISBLK(st_buf.st_mode))
|
||||
dev = st_buf.st_rdev;
|
||||
else if (S_ISREG(st_buf.st_mode)) {
|
||||
dev = st_buf.st_dev;
|
||||
ino = st_buf.st_ino;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
if ((f = fopen("/proc/swaps", "r")) == NULL)
|
||||
return 0;
|
||||
|
||||
/* skip the first line */
|
||||
if (fgets(tmp, sizeof(tmp), f) == NULL)
|
||||
goto out;
|
||||
|
||||
while (fgets(tmp, sizeof(tmp), f) != NULL) {
|
||||
if ((cp = strchr(tmp, ' ')) != NULL)
|
||||
*cp = '\0';
|
||||
if ((cp = strchr(tmp, '\t')) != NULL)
|
||||
*cp = '\0';
|
||||
translate(tmp, buf);
|
||||
if (stat(buf, &st_buf) != 0)
|
||||
continue;
|
||||
if (S_ISBLK(st_buf.st_mode)) {
|
||||
if (dev == st_buf.st_rdev) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
} else if (S_ISREG(st_buf.st_mode)) {
|
||||
if (dev == st_buf.st_dev && ino == st_buf.st_ino) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(const 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;
|
||||
}
|
||||
|
||||
static int group_profile_devs_min(u64 flag)
|
||||
{
|
||||
switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
|
||||
|
@ -1987,84 +1834,6 @@ int group_profile_max_safe_loss(u64 flags)
|
|||
}
|
||||
}
|
||||
|
||||
u64 btrfs_min_dev_size(u32 nodesize)
|
||||
{
|
||||
return 2 * (BTRFS_MKFS_SYSTEM_GROUP_SIZE +
|
||||
btrfs_min_global_blk_rsv_size(nodesize));
|
||||
}
|
||||
|
||||
/*
|
||||
* Btrfs minimum size calculation is complicated, it should include at least:
|
||||
* 1. system group size
|
||||
* 2. minimum global block reserve
|
||||
* 3. metadata used at mkfs
|
||||
* 4. space reservation to create uuid for first mount.
|
||||
* Also, raid factor should also be taken into consideration.
|
||||
* To avoid the overkill calculation, (system group + global block rsv) * 2
|
||||
* for *EACH* device should be good enough.
|
||||
*/
|
||||
u64 btrfs_min_global_blk_rsv_size(u32 nodesize)
|
||||
{
|
||||
return (u64)nodesize << 10;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a device is suitable for btrfs
|
||||
* returns:
|
||||
* 1: something is wrong, an error is printed
|
||||
* 0: all is fine
|
||||
*/
|
||||
int test_dev_for_mkfs(const char *file, int force_overwrite)
|
||||
{
|
||||
int ret, fd;
|
||||
struct stat st;
|
||||
|
||||
ret = is_swap_device(file);
|
||||
if (ret < 0) {
|
||||
error("checking status of %s: %s", file, strerror(-ret));
|
||||
return 1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
error("%s is a swap device", file);
|
||||
return 1;
|
||||
}
|
||||
if (!force_overwrite) {
|
||||
if (check_overwrite(file)) {
|
||||
error("use the -f option to force overwrite of %s",
|
||||
file);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ret = check_mounted(file);
|
||||
if (ret < 0) {
|
||||
error("cannot check mount status of %s: %s", file,
|
||||
strerror(-ret));
|
||||
return 1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
error("%s is mounted", file);
|
||||
return 1;
|
||||
}
|
||||
/* check if the device is busy */
|
||||
fd = open(file, O_RDWR|O_EXCL);
|
||||
if (fd < 0) {
|
||||
error("unable to open %s: %s", file, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (fstat(fd, &st)) {
|
||||
error("unable to stat %s: %s", file, strerror(errno));
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
error("%s is not a block device", file);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_scan_devices(void)
|
||||
{
|
||||
int fd = -1;
|
||||
|
@ -2117,35 +1886,6 @@ int btrfs_scan_devices(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int is_vol_small(const char *file)
|
||||
{
|
||||
int fd = -1;
|
||||
int e;
|
||||
struct stat st;
|
||||
u64 size;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
e = -errno;
|
||||
close(fd);
|
||||
return e;
|
||||
}
|
||||
size = btrfs_device_size(fd, &st);
|
||||
if (size == 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (size < BTRFS_MKFS_SMALL_VOLUME_SIZE) {
|
||||
close(fd);
|
||||
return 1;
|
||||
} else {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This reads a line from the stdin and only returns non-zero if the
|
||||
* first whitespace delimited token is a case insensitive match with yes
|
||||
|
@ -2219,27 +1959,6 @@ int find_mount_root(const char *path, char **mount_root)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int test_minimum_size(const char *file, u32 nodesize)
|
||||
{
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (stat(file, &statbuf) < 0) {
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
if (btrfs_device_size(fd, &statbuf) < btrfs_min_dev_size(nodesize)) {
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test if path is a directory
|
||||
* Returns:
|
||||
|
|
Loading…
Reference in New Issue