#include <linux/magic.h>
#include <getopt.h>
#include <sys/utsname.h>
+#include <linux/version.h>
#include "kerncompat.h"
#include "radix-tree.h"
static int rand_seed_initlized = 0;
static unsigned short rand_seed[3];
+struct btrfs_config bconf;
+
const char *get_argv0_buf(void)
{
return argv0_buf;
*/
if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
char *cur;
+ u32 array_size;
- cur = (char *)sb->sys_chunk_array + sb->sys_chunk_array_size;
+ cur = (char *)sb->sys_chunk_array
+ + btrfs_super_sys_array_size(sb);
memcpy(cur, &disk_key, sizeof(disk_key));
cur += sizeof(disk_key);
read_extent_buffer(buf, cur, (unsigned long int)chunk,
btrfs_chunk_item_size(1));
- sb->sys_chunk_array_size += btrfs_chunk_item_size(1) +
+ array_size = btrfs_super_sys_array_size(sb);
+ array_size += btrfs_chunk_item_size(1) +
sizeof(disk_key);
+ btrfs_set_super_sys_array_size(sb, array_size);
ret = write_temp_super(fd, sb, cfg->super_bytenr);
}
* Split into small blocks and reuse codes.
* TODO: Reuse tree operation facilities by introducing new flags
*/
-static int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
+int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
struct btrfs_convert_context *cctx)
{
struct cache_tree *free = &cctx->free;
* The superblock signature is not valid, denotes a partially created
* filesystem, needs to be finalized.
*/
-int make_btrfs(int fd, struct btrfs_mkfs_config *cfg,
- struct btrfs_convert_context *cctx)
+int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
{
struct btrfs_super_block super;
struct extent_buffer *buf;
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA);
u64 num_bytes;
- if (cctx)
- return make_convert_btrfs(fd, cfg, cctx);
buf = malloc(sizeof(*buf) + max(cfg->sectorsize, cfg->nodesize));
if (!buf)
return -ENOMEM;
return ret;
}
+#define VERSION_TO_STRING3(a,b,c) #a "." #b "." #c, KERNEL_VERSION(a,b,c)
+#define VERSION_TO_STRING2(a,b) #a "." #b, KERNEL_VERSION(a,b,0)
+
+/*
+ * Feature stability status and versions: compat <= safe <= default
+ */
static const struct btrfs_fs_feature {
const char *name;
u64 flag;
+ const char *sysfs_name;
+ /*
+ * Compatibility with kernel of given version. Filesystem can be
+ * mounted.
+ */
+ const char *compat_str;
+ u32 compat_ver;
+ /*
+ * Considered safe for use, but is not on by default, even if the
+ * kernel supports the feature.
+ */
+ const char *safe_str;
+ u32 safe_ver;
+ /*
+ * Considered safe for use and will be turned on by default if
+ * supported by the running kernel.
+ */
+ const char *default_str;
+ u32 default_ver;
const char *desc;
} mkfs_features[] = {
{ "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
+ "mixed_groups",
+ VERSION_TO_STRING3(2,6,37),
+ VERSION_TO_STRING3(2,6,37),
+ NULL, 0,
"mixed data and metadata block groups" },
{ "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
+ "extended_iref",
+ VERSION_TO_STRING2(3,7),
+ VERSION_TO_STRING2(3,12),
+ VERSION_TO_STRING2(3,12),
"increased hardlink limit per file to 65536" },
{ "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
+ "raid56",
+ VERSION_TO_STRING2(3,9),
+ NULL, 0,
+ NULL, 0,
"raid56 extended format" },
{ "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
+ "skinny_metadata",
+ VERSION_TO_STRING2(3,10),
+ VERSION_TO_STRING2(3,18),
+ VERSION_TO_STRING2(3,18),
"reduced-size metadata extent refs" },
{ "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
+ "no_holes",
+ VERSION_TO_STRING2(3,14),
+ VERSION_TO_STRING2(4,0),
+ NULL, 0,
"no explicit hole extents for files" },
/* Keep this one last */
{ "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
fprintf(stderr, "Filesystem features available:\n");
for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
- char *is_default = "";
+ const struct btrfs_fs_feature *feat = &mkfs_features[i];
- if (mkfs_features[i].flag & mask_disallowed)
+ if (feat->flag & mask_disallowed)
continue;
- if (mkfs_features[i].flag & BTRFS_MKFS_DEFAULT_FEATURES)
- is_default = ", default";
- fprintf(stderr, "%-20s- %s (0x%llx%s)\n",
- mkfs_features[i].name,
- mkfs_features[i].desc,
- mkfs_features[i].flag,
- is_default);
+ fprintf(stderr, "%-20s- %s (0x%llx", feat->name, feat->desc,
+ feat->flag);
+ if (feat->compat_ver)
+ fprintf(stderr, ", compat=%s", feat->compat_str);
+ if (feat->safe_ver)
+ fprintf(stderr, ", safe=%s", feat->safe_str);
+ if (feat->default_ver)
+ fprintf(stderr, ", default=%s", feat->default_str);
+ fprintf(stderr, ")\n");
}
}
*/
if (discard_range(fd, 0, 0) == 0) {
if (opflags & PREP_DEVICE_VERBOSE)
- printf("Performing full device TRIM (%s) ...\n",
- pretty_size(block_count));
+ printf("Performing full device TRIM %s (%s) ...\n",
+ file, pretty_size(block_count));
discard_blocks(fd, 0, block_count);
}
}
int mult = 0;
const char** suffix = NULL;
u64 last_size;
+ int negative;
if (str_size == 0)
return 0;
+ negative = !!(unit_mode & UNITS_NEGATIVE);
+ unit_mode &= ~UNITS_NEGATIVE;
+
if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
- snprintf(str, str_size, "%llu", size);
+ if (negative)
+ snprintf(str, str_size, "%lld", size);
+ else
+ snprintf(str, str_size, "%llu", size);
return 0;
}
num_divs = 0;
break;
default:
- while (size >= mult) {
- last_size = size;
- size /= mult;
- num_divs++;
+ if (negative) {
+ s64 ssize = (s64)size;
+ s64 last_ssize = ssize;
+
+ while ((ssize < 0 ? -ssize : ssize) >= mult) {
+ last_ssize = ssize;
+ ssize /= mult;
+ num_divs++;
+ }
+ last_size = (u64)last_ssize;
+ } else {
+ while (size >= mult) {
+ last_size = size;
+ size /= mult;
+ num_divs++;
+ }
}
/*
* If the value is smaller than base, we didn't do any
assert(0);
return -1;
}
- fraction = (float)last_size / base;
+
+ if (negative) {
+ fraction = (float)(s64)last_size / base;
+ } else {
+ fraction = (float)last_size / base;
+ }
return snprintf(str, str_size, "%.2f%s", fraction, suffix[num_divs]);
}
}
/*
- * For a given:
- * - file or directory return the containing tree root id
- * - subvolume return its own tree id
- * - BTRFS_EMPTY_SUBVOL_DIR_OBJECTID (directory with ino == 2) the result is
- * undefined and function returns -1
- */
-int lookup_path_rootid(int fd, u64 *rootid)
-{
- struct btrfs_ioctl_ino_lookup_args args;
- int ret;
-
- memset(&args, 0, sizeof(args));
- args.treeid = 0;
- args.objectid = BTRFS_FIRST_FREE_OBJECTID;
-
- ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
- if (ret < 0)
- return -errno;
-
- *rootid = args.treeid;
-
- return 0;
-}
-
-/*
* return 0 if a btrfs mount point is found
* return 1 if a mount point is found but not btrfs
* return <0 if something goes wrong
int string_is_numerical(const char *str)
{
+ if (!str)
+ return 0;
if (!(*str >= '0' && *str <= '9'))
return 0;
while (*str >= '0' && *str <= '9')
*/
return (unsigned int)(jrand48(rand_seed) % upper);
}
+
+void btrfs_config_init(void)
+{
+}