Compare commits
24 commits
devel
...
ci/dev/fuz
Author | SHA1 | Date | |
---|---|---|---|
8adc70d282 | |||
d61f8c4c95 | |||
1dfd256a55 | |||
91a20bc76b | |||
917a7c2f41 | |||
ef53fbdc8e | |||
29f382042b | |||
7c10c72134 | |||
410d82d7b1 | |||
7535c35128 | |||
1487e61a2f | |||
8b240d0625 | |||
751c57f950 | |||
7420ee7721 | |||
a35409328e | |||
6ed16f7b09 | |||
4168fa41cc | |||
22b3246ef9 | |||
9506275242 | |||
12358fa061 | |||
c600fcca81 | |||
2781f669e3 | |||
cc2230e412 | |||
9cfa509133 |
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
|
@ -44,7 +44,7 @@ jobs:
|
|||
- name: Generate lcov results
|
||||
run: |
|
||||
lcov -c -d . -o lcov-info
|
||||
genhtml -o lcov-out lcov-info
|
||||
genhtml --rc geninfo_unexecuted_blocks=1 -o lcov-out lcov-info
|
||||
- name: Save lcov results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
|
|
@ -66,6 +66,11 @@ A subvolume is made read-only after the receiving process finishes successfully
|
|||
dump the stream metadata, one line per operation
|
||||
|
||||
Does not require the *path* parameter. The filesystem remains unchanged.
|
||||
Each stream command is on one line in the form of *key=value* and separated
|
||||
by one or more spaces. Values that contain special characters (like
|
||||
paths or extended attributes) are encoded in C-like way, e.g. *'\\n'* or
|
||||
octal escape sequence like *'\\NNN'* where N is the char value. Same encoding
|
||||
as is used in */proc* files.
|
||||
|
||||
-q|--quiet
|
||||
(deprecated) alias for global *-q* option
|
||||
|
|
7
Makefile
7
Makefile
|
@ -314,8 +314,8 @@ ifeq ("$(origin D)", "command line")
|
|||
endif
|
||||
|
||||
ifneq (,$(findstring gcov,$(D)))
|
||||
DEBUG_CFLAGS_INTERNAL += -fprofile-arcs -ftest-coverage --coverage
|
||||
DEBUG_LDFLAGS_INTERNAL += -fprofile-generate --coverage
|
||||
DEBUG_CFLAGS_INTERNAL += -fprofile-arcs -fprofile-update=atomic -ftest-coverage --coverage
|
||||
DEBUG_LDFLAGS_INTERNAL += -fprofile-generate -fprofile-update=atomic --coverage
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring verbose,$(D)))
|
||||
|
@ -550,7 +550,7 @@ test-mkfs: btrfs mkfs.btrfs
|
|||
@echo " [TEST] mkfs-tests.sh"
|
||||
$(Q)bash tests/mkfs-tests.sh
|
||||
|
||||
test-fuzz: btrfs btrfs-image
|
||||
test-fuzz: btrfs btrfs-image btrfs-sb-mod
|
||||
@echo " [TEST] fuzz-tests.sh"
|
||||
$(Q)bash tests/fuzz-tests.sh
|
||||
|
||||
|
@ -878,6 +878,7 @@ tags: FORCE
|
|||
@echo " [TAGS] $(TAGS_CMD)"
|
||||
$(Q)$(TAGS_CMD) *.[ch] image/*.[ch] convert/*.[ch] mkfs/*.[ch] \
|
||||
check/*.[ch] kernel-lib/*.[ch] kernel-shared/*.[ch] \
|
||||
kernel-shared/*/*.[ch] \
|
||||
cmds/*.[ch] common/*.[ch] tune/*.[ch] \
|
||||
libbtrfsutil/*.[ch]
|
||||
|
||||
|
|
|
@ -1398,7 +1398,7 @@ int main(int argc, char **argv)
|
|||
inode = arg_strtou64(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
strncpy(field, optarg, FIELD_BUF_LEN);
|
||||
strncpy_null(field, optarg, FIELD_BUF_LEN);
|
||||
break;
|
||||
case 'x':
|
||||
file_extent = arg_strtou64(optarg);
|
||||
|
|
|
@ -169,7 +169,7 @@ static int cmd_device_add(const struct cmd_struct *cmd,
|
|||
}
|
||||
|
||||
memset(&ioctl_args, 0, sizeof(ioctl_args));
|
||||
strncpy_null(ioctl_args.name, path);
|
||||
strncpy_null(ioctl_args.name, path, sizeof(ioctl_args.name));
|
||||
res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
|
||||
if (res < 0) {
|
||||
error("error adding device '%s': %m", path);
|
||||
|
@ -287,7 +287,7 @@ static int _cmd_device_remove(const struct cmd_struct *cmd,
|
|||
} else if (strcmp(argv[i], "missing") == 0 ||
|
||||
cancel ||
|
||||
path_is_block_device(argv[i]) == 1) {
|
||||
strncpy_null(argv2.name, argv[i]);
|
||||
strncpy_null(argv2.name, argv[i], sizeof(argv2.name));
|
||||
} else {
|
||||
error("not a block device: %s", argv[i]);
|
||||
ret++;
|
||||
|
@ -312,7 +312,7 @@ static int _cmd_device_remove(const struct cmd_struct *cmd,
|
|||
continue;
|
||||
}
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
strncpy_null(arg.name, argv[i]);
|
||||
strncpy_null(arg.name, argv[i], sizeof(arg.name));
|
||||
res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ static int btrfs_forget_devices(const char *path)
|
|||
|
||||
memset(&args, 0, sizeof(args));
|
||||
if (path)
|
||||
strncpy_null(args.name, path);
|
||||
strncpy_null(args.name, path, sizeof(args.name));
|
||||
ret = ioctl(fd, BTRFS_IOC_FORGET_DEV, &args);
|
||||
if (ret)
|
||||
ret = -errno;
|
||||
|
@ -557,7 +557,7 @@ static int cmd_device_ready(const struct cmd_struct *cmd, int argc, char **argv)
|
|||
}
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
strncpy_null(args.name, path);
|
||||
strncpy_null(args.name, path, sizeof(args.name));
|
||||
ret = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args);
|
||||
if (ret < 0) {
|
||||
error("unable to determine if device '%s' is ready for mount: %m",
|
||||
|
@ -799,9 +799,8 @@ static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
|
|||
char path[BTRFS_DEVICE_PATH_NAME_MAX + 1];
|
||||
int err2;
|
||||
|
||||
strncpy(path, (char *)di_args[i].path,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX);
|
||||
path[BTRFS_DEVICE_PATH_NAME_MAX] = 0;
|
||||
strncpy_null(path, (char *)di_args[i].path,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX + 1);
|
||||
|
||||
args.devid = di_args[i].devid;
|
||||
args.nr_items = BTRFS_DEV_STAT_VALUES_MAX;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include "libbtrfsutil/btrfsutil.h"
|
||||
#include "kernel-lib/list.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include "common/device-utils.h"
|
||||
#include "common/open-utils.h"
|
||||
#include "common/parse-utils.h"
|
||||
#include "common/sysfs-utils.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "common/filesystem-utils.h"
|
||||
#include "common/format-output.h"
|
||||
|
@ -81,6 +83,41 @@ static const char * const cmd_filesystem_df_usage[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void print_df_by_type(int fd, unsigned int unit_mode) {
|
||||
static const char *files[] = {
|
||||
"bg_reclaim_threshold",
|
||||
"bytes_may_use",
|
||||
"bytes_pinned",
|
||||
"bytes_readonly",
|
||||
"bytes_reserved",
|
||||
"bytes_used",
|
||||
"bytes_zone_unusable",
|
||||
"chunk_size",
|
||||
"disk_total",
|
||||
"disk_used",
|
||||
"total_bytes",
|
||||
};
|
||||
char path[PATH_MAX] = { 0 };
|
||||
const char *types[] = { "data", "metadata", "mixed", "system" };
|
||||
u64 tmp;
|
||||
int ret;
|
||||
|
||||
for (int ti = 0; ti < ARRAY_SIZE(types); ti++) {
|
||||
for (int i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
path_cat3_out(path, "allocation", types[ti], files[i]);
|
||||
ret = sysfs_read_fsid_file_u64(fd, path, &tmp);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
if (i == 0)
|
||||
pr_verbose(LOG_INFO, "%c%s:\n", toupper(types[ti][0]), types[ti] + 1);
|
||||
if (strcmp(files[i], "bg_reclaim_threshold") == 0)
|
||||
pr_verbose(LOG_INFO, " %-24s %14llu%%\n", files[i], tmp);
|
||||
else
|
||||
pr_verbose(LOG_INFO, " %-24s %16s\n", files[i], pretty_size_mode(tmp, unit_mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_df_text(int fd, struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
|
||||
{
|
||||
u64 i;
|
||||
|
@ -100,6 +137,7 @@ static void print_df_text(int fd, struct btrfs_ioctl_space_args *sargs, unsigned
|
|||
(ok ? ", zone_unusable=" : ""),
|
||||
(ok ? pretty_size_mode(unusable, unit_mode) : ""));
|
||||
}
|
||||
print_df_by_type(fd, unit_mode);
|
||||
}
|
||||
|
||||
static const struct rowspec filesystem_df_rowspec[] = {
|
||||
|
@ -1441,7 +1479,7 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
|
|||
memset(&args, 0, sizeof(args));
|
||||
if (devid == (u64)-1) {
|
||||
/* Ok to copy the string verbatim. */
|
||||
strncpy_null(args.name, amount);
|
||||
strncpy_null(args.name, amount, sizeof(args.name));
|
||||
} else {
|
||||
/* The implicit devid 1 needs to be adjusted. */
|
||||
snprintf(args.name, sizeof(args.name) - 1, "%llu:%s", devid, amount);
|
||||
|
|
279
cmds/inspect.c
279
cmds/inspect.c
|
@ -258,7 +258,7 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
|
|||
if (name[0] == 0) {
|
||||
path_ptr[-1] = '\0';
|
||||
path_fd = fd;
|
||||
strncpy(mount_path, full_path, PATH_MAX);
|
||||
strncpy_null(mount_path, full_path, PATH_MAX);
|
||||
} else {
|
||||
char *mounted = NULL;
|
||||
char subvol[PATH_MAX];
|
||||
|
@ -291,7 +291,7 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
|
|||
continue;
|
||||
}
|
||||
|
||||
strncpy(mount_path, mounted, PATH_MAX);
|
||||
strncpy_null(mount_path, mounted, PATH_MAX);
|
||||
free(mounted);
|
||||
|
||||
path_fd = btrfs_open_dir(mount_path);
|
||||
|
@ -718,7 +718,7 @@ struct list_chunks_entry {
|
|||
u64 flags;
|
||||
u64 lnumber;
|
||||
u64 used;
|
||||
u32 number;
|
||||
u64 pnumber;
|
||||
};
|
||||
|
||||
struct list_chunks_ctx {
|
||||
|
@ -727,7 +727,19 @@ struct list_chunks_ctx {
|
|||
struct list_chunks_entry *stats;
|
||||
};
|
||||
|
||||
static int cmp_cse_devid_start(const void *va, const void *vb)
|
||||
static int cmp_cse_devid(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
||||
if (a->devid < b->devid)
|
||||
return -1;
|
||||
if (a->devid > b->devid)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmp_cse_devid_pstart(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
@ -739,38 +751,37 @@ static int cmp_cse_devid_start(const void *va, const void *vb)
|
|||
|
||||
if (a->start < b->start)
|
||||
return -1;
|
||||
if (a->start == b->start) {
|
||||
error(
|
||||
"chunks start on same offset in the same device: devid %llu start %llu",
|
||||
a->devid, a->start);
|
||||
if (a->start == b->start)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmp_cse_devid_lstart(const void *va, const void *vb)
|
||||
static int cmp_cse_pstart(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
||||
if (a->devid < b->devid)
|
||||
if (a->start < b->start)
|
||||
return -1;
|
||||
if (a->devid > b->devid)
|
||||
return 1;
|
||||
if (a->start == b->start)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmp_cse_lstart(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
||||
if (a->lstart < b->lstart)
|
||||
return -1;
|
||||
if (a->lstart == b->lstart) {
|
||||
error(
|
||||
"chunks logically start on same offset in the same device: devid %llu start %llu",
|
||||
a->devid, a->lstart);
|
||||
if (a->lstart == b->lstart)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compare entries by usage percent, descending. */
|
||||
static int cmp_cse_devid_usage(const void *va, const void *vb)
|
||||
static int cmp_cse_usage(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
@ -785,7 +796,7 @@ static int cmp_cse_devid_usage(const void *va, const void *vb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmp_cse_length_physical(const void *va, const void *vb)
|
||||
static int cmp_cse_length(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
@ -794,173 +805,126 @@ static int cmp_cse_length_physical(const void *va, const void *vb)
|
|||
return -1;
|
||||
if (a->length > b->length)
|
||||
return 1;
|
||||
|
||||
if (a->start < b->start)
|
||||
return -1;
|
||||
if (a->start > b->start)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmp_cse_length_logical(const void *va, const void *vb)
|
||||
{
|
||||
const struct list_chunks_entry *a = va;
|
||||
const struct list_chunks_entry *b = vb;
|
||||
|
||||
if (a->length < b->length)
|
||||
return -1;
|
||||
if (a->length > b->length)
|
||||
return 1;
|
||||
|
||||
if (a->lstart < b->lstart)
|
||||
return -1;
|
||||
if (a->lstart > b->lstart)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_list_chunks(struct list_chunks_ctx *ctx, const char* sortmode,
|
||||
unsigned unit_mode, bool with_usage, bool with_empty)
|
||||
static int print_list_chunks(struct list_chunks_ctx *ctx, const char *sortmode,
|
||||
unsigned unit_mode)
|
||||
{
|
||||
u64 devid;
|
||||
struct list_chunks_entry e;
|
||||
struct string_table *table;
|
||||
int col_count, col;
|
||||
int i;
|
||||
int chidx;
|
||||
u64 lastend;
|
||||
u64 number;
|
||||
u32 gaps;
|
||||
u32 tabidx;
|
||||
static const struct sortdef sortit[] = {
|
||||
{ .name = "pstart", .comp = (sort_cmp_t)cmp_cse_devid_start,
|
||||
.desc = "sort by physical srart offset, group by device" },
|
||||
{ .name = "lstart", .comp = (sort_cmp_t)cmp_cse_devid_lstart,
|
||||
.desc = "sort by logical offset" },
|
||||
{ .name = "usage", .comp = (sort_cmp_t)cmp_cse_devid_usage,
|
||||
.desc = "sort by chunk usage" },
|
||||
{ .name = "length_p", .comp = (sort_cmp_t)cmp_cse_length_physical,
|
||||
.desc = "sort by lentgh, secondary by physical offset" },
|
||||
{ .name = "length_l", .comp = (sort_cmp_t)cmp_cse_length_logical,
|
||||
.desc = "sort by lentgh, secondary by logical offset" },
|
||||
};
|
||||
enum {
|
||||
CHUNK_SORT_PSTART,
|
||||
CHUNK_SORT_LSTART,
|
||||
CHUNK_SORT_USAGE,
|
||||
CHUNK_SORT_LENGTH_P,
|
||||
CHUNK_SORT_LENGTH_L,
|
||||
CHUNK_SORT_LENGTH,
|
||||
CHUNK_SORT_DEFAULT = CHUNK_SORT_PSTART
|
||||
};
|
||||
unsigned int sort_mode;
|
||||
static const struct sortdef sortit[] = {
|
||||
{ .name = "devid", .comp = (sort_cmp_t)cmp_cse_devid,
|
||||
.desc = "sort by device id (default, with pstart)",
|
||||
.id = CHUNK_SORT_PSTART
|
||||
},
|
||||
{ .name = "pstart", .comp = (sort_cmp_t)cmp_cse_pstart,
|
||||
.desc = "sort by physical start offset",
|
||||
.id = CHUNK_SORT_PSTART
|
||||
},
|
||||
{ .name = "lstart", .comp = (sort_cmp_t)cmp_cse_lstart,
|
||||
.desc = "sort by logical offset",
|
||||
.id = CHUNK_SORT_LSTART
|
||||
},
|
||||
{ .name = "usage", .comp = (sort_cmp_t)cmp_cse_usage,
|
||||
.desc = "sort by chunk usage",
|
||||
.id = CHUNK_SORT_USAGE
|
||||
},
|
||||
{ .name = "length", .comp = (sort_cmp_t)cmp_cse_length,
|
||||
.desc = "sort by lentgh",
|
||||
.id = CHUNK_SORT_LENGTH
|
||||
},
|
||||
SORTDEF_END
|
||||
};
|
||||
const char *tmp;
|
||||
struct compare comp;
|
||||
int id;
|
||||
|
||||
if (!sortmode) {
|
||||
sort_mode = CHUNK_SORT_DEFAULT;
|
||||
sortmode = "pstart";
|
||||
} else if (strcmp(sortmode, "pstart") == 0) {
|
||||
sort_mode = CHUNK_SORT_PSTART;
|
||||
} else if (strcmp(sortmode, "lstart") == 0) {
|
||||
sort_mode = CHUNK_SORT_LSTART;
|
||||
} else if (strcmp(sortmode, "usage") == 0) {
|
||||
sort_mode = CHUNK_SORT_USAGE;
|
||||
with_usage = true;
|
||||
} else if (strcmp(sortmode, "length_p") == 0) {
|
||||
sort_mode = CHUNK_SORT_LENGTH_P;
|
||||
} else if (strcmp(sortmode, "length_l") == 0) {
|
||||
sort_mode = CHUNK_SORT_LENGTH_L;
|
||||
} else {
|
||||
error("unknown sort mode: %s", sortmode);
|
||||
exit(1);
|
||||
}
|
||||
compare_init(&comp, sortit);
|
||||
|
||||
tmp = sortmode;
|
||||
do {
|
||||
id = compare_parse_key_to_id(&comp, &tmp);
|
||||
if (id == -1) {
|
||||
error("unknown sort key: %s", tmp);
|
||||
return 1;
|
||||
}
|
||||
compare_add_sort_id(&comp, id);
|
||||
} while (id >= 0);
|
||||
|
||||
/*
|
||||
* Chunks are sorted logically as found by the ioctl, we need to sort
|
||||
* them once to find the physical ordering. This is the default mode.
|
||||
*/
|
||||
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), cmp_cse_devid_start);
|
||||
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), cmp_cse_devid_pstart);
|
||||
devid = 0;
|
||||
number = 0;
|
||||
gaps = 0;
|
||||
lastend = 0;
|
||||
for (i = 0; i < ctx->length; i++) {
|
||||
e = ctx->stats[i];
|
||||
if (e.devid != devid) {
|
||||
devid = e.devid;
|
||||
number = 0;
|
||||
}
|
||||
ctx->stats[i].number = number;
|
||||
number++;
|
||||
if (with_empty && sort_mode == CHUNK_SORT_PSTART && e.start != lastend)
|
||||
gaps++;
|
||||
lastend = e.start + e.length;
|
||||
ctx->stats[i].pnumber = number++;
|
||||
}
|
||||
|
||||
compare_init(&comp, sortit);
|
||||
compare_add_sort_key(&comp, sortmode);
|
||||
qsort_r(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_r_cmp_t)compare_cmp_multi,
|
||||
&comp);
|
||||
/* Skip additonal sort if nothing defined by user. */
|
||||
if (comp.count > 0)
|
||||
qsort_r(ctx->stats, ctx->length, sizeof(ctx->stats[0]),
|
||||
(sort_r_cmp_t)compare_cmp_multi, &comp);
|
||||
|
||||
/* Optional usage, two rows for header and separator, gaps */
|
||||
table = table_create(7 + (int)with_usage, 2 + ctx->length + gaps);
|
||||
col_count = 9;
|
||||
/* Two rows for header and separator. */
|
||||
table = table_create(col_count, 2 + ctx->length);
|
||||
if (!table) {
|
||||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
return 1;
|
||||
}
|
||||
devid = 0;
|
||||
/* Print header */
|
||||
col = 0;
|
||||
tabidx = 0;
|
||||
chidx = 1;
|
||||
table_printf(table, col++, tabidx, ">Devid");
|
||||
table_printf(table, col++, tabidx, ">PNumber");
|
||||
table_printf(table, col++, tabidx, ">Type/profile");
|
||||
table_printf(table, col++, tabidx, ">PStart");
|
||||
table_printf(table, col++, tabidx, ">Length");
|
||||
table_printf(table, col++, tabidx, ">PEnd");
|
||||
table_printf(table, col++, tabidx, ">LNumber");
|
||||
table_printf(table, col++, tabidx, ">LStart");
|
||||
table_printf(table, col++, tabidx, ">Usage%%");
|
||||
for (int j = 0; j < col_count; j++)
|
||||
table_printf(table, j, tabidx + 1, "*-");
|
||||
|
||||
tabidx = 2;
|
||||
devid = 0;
|
||||
for (i = 0; i < ctx->length; i++) {
|
||||
e = ctx->stats[i];
|
||||
/* TODO: print header and devid */
|
||||
if (e.devid != devid) {
|
||||
int j;
|
||||
|
||||
if (e.devid != devid)
|
||||
devid = e.devid;
|
||||
table_printf(table, 0, tabidx, ">Number");
|
||||
table_printf(table, 1, tabidx, ">Type/profile");
|
||||
table_printf(table, 2, tabidx, ">PStart");
|
||||
table_printf(table, 3, tabidx, ">Length");
|
||||
table_printf(table, 4, tabidx, ">PEnd");
|
||||
table_printf(table, 5, tabidx, ">LNumber");
|
||||
table_printf(table, 6, tabidx, ">LStart");
|
||||
if (with_usage) {
|
||||
table_printf(table, 7, tabidx, ">Usage%%");
|
||||
table_printf(table, 7, tabidx + 1, "*-");
|
||||
}
|
||||
for (j = 0; j < 7; j++)
|
||||
table_printf(table, j, tabidx + 1, "*-");
|
||||
|
||||
chidx = 1;
|
||||
lastend = 0;
|
||||
tabidx += 2;
|
||||
}
|
||||
if (with_empty && sort_mode == CHUNK_SORT_PSTART && e.start != lastend) {
|
||||
table_printf(table, 0, tabidx, ">-");
|
||||
table_printf(table, 1, tabidx, ">%s", "empty");
|
||||
table_printf(table, 2, tabidx, ">-");
|
||||
table_printf(table, 3, tabidx, ">%s",
|
||||
pretty_size_mode(e.start - lastend, unit_mode));
|
||||
table_printf(table, 4, tabidx, ">-");
|
||||
table_printf(table, 5, tabidx, ">-");
|
||||
table_printf(table, 6, tabidx, ">-");
|
||||
if (with_usage)
|
||||
table_printf(table, 7, tabidx, ">-");
|
||||
tabidx++;
|
||||
}
|
||||
|
||||
table_printf(table, 0, tabidx, ">%llu", chidx++);
|
||||
table_printf(table, 1, tabidx, ">%10s/%-6s",
|
||||
col = 0;
|
||||
table_printf(table, col++, tabidx, ">%llu", e.devid);
|
||||
table_printf(table, col++, tabidx, ">%llu", e.pnumber + 1);
|
||||
table_printf(table, col++, tabidx, ">%10s/%-6s",
|
||||
btrfs_group_type_str(e.flags),
|
||||
btrfs_group_profile_str(e.flags));
|
||||
table_printf(table, 2, tabidx, ">%s", pretty_size_mode(e.start, unit_mode));
|
||||
table_printf(table, 3, tabidx, ">%s", pretty_size_mode(e.length, unit_mode));
|
||||
table_printf(table, 4, tabidx, ">%s", pretty_size_mode(e.start + e.length, unit_mode));
|
||||
table_printf(table, 5, tabidx, ">%llu", e.lnumber + 1);
|
||||
table_printf(table, 6, tabidx, ">%s", pretty_size_mode(e.lstart, unit_mode));
|
||||
if (with_usage)
|
||||
table_printf(table, 7, tabidx, ">%6.2f",
|
||||
(float)e.used / e.length * 100);
|
||||
lastend = e.start + e.length;
|
||||
table_printf(table, col++, tabidx, ">%s", pretty_size_mode(e.start, unit_mode));
|
||||
table_printf(table, col++, tabidx, ">%s", pretty_size_mode(e.length, unit_mode));
|
||||
table_printf(table, col++, tabidx, ">%s", pretty_size_mode(e.start + e.length, unit_mode));
|
||||
table_printf(table, col++, tabidx, ">%llu", e.lnumber + 1);
|
||||
table_printf(table, col++, tabidx, ">%s", pretty_size_mode(e.lstart, unit_mode));
|
||||
table_printf(table, col++, tabidx, ">%6.2f", (float)e.used / e.length * 100);
|
||||
tabidx++;
|
||||
}
|
||||
table_dump(table);
|
||||
|
@ -1019,8 +983,6 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
int i;
|
||||
unsigned unit_mode;
|
||||
char *sortmode = NULL;
|
||||
bool with_usage = true;
|
||||
bool with_empty = true;
|
||||
const char *path;
|
||||
struct list_chunks_ctx ctx = {
|
||||
.length = 0,
|
||||
|
@ -1033,15 +995,10 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
while (1) {
|
||||
int c;
|
||||
enum { GETOPT_VAL_SORT = GETOPT_VAL_FIRST,
|
||||
GETOPT_VAL_USAGE, GETOPT_VAL_NO_USAGE,
|
||||
GETOPT_VAL_EMPTY, GETOPT_VAL_NO_EMPTY
|
||||
};
|
||||
static const struct option long_options[] = {
|
||||
{"sort", required_argument, NULL, GETOPT_VAL_SORT },
|
||||
{"usage", no_argument, NULL, GETOPT_VAL_USAGE },
|
||||
{"no-usage", no_argument, NULL, GETOPT_VAL_NO_USAGE },
|
||||
{"empty", no_argument, NULL, GETOPT_VAL_EMPTY },
|
||||
{"no-empty", no_argument, NULL, GETOPT_VAL_NO_EMPTY },
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -1054,14 +1011,6 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
free(sortmode);
|
||||
sortmode = strdup(optarg);
|
||||
break;
|
||||
case GETOPT_VAL_USAGE:
|
||||
case GETOPT_VAL_NO_USAGE:
|
||||
with_usage = (c == GETOPT_VAL_USAGE);
|
||||
break;
|
||||
case GETOPT_VAL_EMPTY:
|
||||
case GETOPT_VAL_NO_EMPTY:
|
||||
with_empty = (c == GETOPT_VAL_EMPTY);
|
||||
break;
|
||||
default:
|
||||
usage_unknown_option(cmd, argv);
|
||||
}
|
||||
|
@ -1136,7 +1085,7 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
e->lstart = sh.offset;
|
||||
e->length = item->length;
|
||||
e->flags = item->type;
|
||||
e->number = -1;
|
||||
e->pnumber = -1;
|
||||
while (devid > lnumber_size) {
|
||||
u64 *tmp;
|
||||
unsigned old_size = lnumber_size;
|
||||
|
@ -1152,13 +1101,9 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
lnumber = tmp;
|
||||
}
|
||||
e->lnumber = lnumber[devid]++;
|
||||
if (with_usage) {
|
||||
if (used == (u64)-1)
|
||||
used = fill_usage(fd, sh.offset);
|
||||
e->used = used;
|
||||
} else {
|
||||
e->used = 0;
|
||||
}
|
||||
if (used == (u64)-1)
|
||||
used = fill_usage(fd, sh.offset);
|
||||
e->used = used;
|
||||
|
||||
ctx.length++;
|
||||
|
||||
|
@ -1184,7 +1129,7 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
|
|||
break;
|
||||
}
|
||||
|
||||
ret = print_list_chunks(&ctx, sortmode, unit_mode, with_usage, with_empty);
|
||||
ret = print_list_chunks(&ctx, sortmode, unit_mode);
|
||||
close(fd);
|
||||
|
||||
out:
|
||||
|
|
|
@ -45,10 +45,9 @@
|
|||
* Returns the length of the escaped characters. Unprintable characters are
|
||||
* escaped as octals.
|
||||
*/
|
||||
static int print_path_escaped(const char *path)
|
||||
static int print_path_escaped_len(const char *path, size_t path_len)
|
||||
{
|
||||
size_t i;
|
||||
size_t path_len = strlen(path);
|
||||
int len = 0;
|
||||
|
||||
for (i = 0; i < path_len; i++) {
|
||||
|
@ -81,6 +80,11 @@ static int print_path_escaped(const char *path)
|
|||
return len;
|
||||
}
|
||||
|
||||
static int print_path_escaped(const char *path)
|
||||
{
|
||||
return print_path_escaped_len(path, strlen(path));
|
||||
}
|
||||
|
||||
enum print_mode {
|
||||
PRINT_DUMP_NORMAL,
|
||||
PRINT_DUMP_SUBVOLUME,
|
||||
|
@ -251,24 +255,37 @@ static int print_clone(const char *path, u64 offset, u64 len,
|
|||
char full_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
PATH_CAT_OR_RET("clone", full_path, r->full_subvol_path, clone_path,
|
||||
ret);
|
||||
return PRINT_DUMP(user, path, "clone",
|
||||
"offset=%llu len=%llu from=%s clone_offset=%llu",
|
||||
offset, len, full_path, clone_offset);
|
||||
PATH_CAT_OR_RET("clone", full_path, r->full_subvol_path, clone_path, ret);
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "clone", "offset=%llu len=%llu from=", offset, len);
|
||||
print_path_escaped(full_path);
|
||||
putchar(' ');
|
||||
printf("clone_offset=%llu\n", clone_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Xattr names are like paths and can potentially contain special characters,
|
||||
* xattr values can be arbitrary.
|
||||
*/
|
||||
static int print_set_xattr(const char *path, const char *name,
|
||||
const void *data, int len, void *user)
|
||||
{
|
||||
return PRINT_DUMP(user, path, "set_xattr", "name=%s data=%.*s len=%d",
|
||||
name, len, (char *)data, len);
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "set_xattr", "name=");
|
||||
print_path_escaped(name);
|
||||
putchar(' ');
|
||||
print_path_escaped_len((char *)data, len);
|
||||
putchar(' ');
|
||||
printf("len=%d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_remove_xattr(const char *path, const char *name, void *user)
|
||||
{
|
||||
|
||||
return PRINT_DUMP(user, path, "remove_xattr", "name=%s", name);
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "remove_xattr", "name=");
|
||||
print_path_escaped(name);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_truncate(const char *path, u64 size, void *user)
|
||||
|
@ -336,9 +353,7 @@ static int print_encoded_write(const char *path, const void *data, u64 offset,
|
|||
u32 compression, u32 encryption, void *user)
|
||||
{
|
||||
return PRINT_DUMP(user, path, "encoded_write",
|
||||
"offset=%llu len=%llu, unencoded_file_len=%llu, "
|
||||
"unencoded_len=%llu, unencoded_offset=%llu, "
|
||||
"compression=%u, encryption=%u",
|
||||
"offset=%llu len=%llu unencoded_file_len=%llu unencoded_len=%llu unencoded_offset=%llu compression=%u encryption=%u",
|
||||
offset, len, unencoded_file_len, unencoded_len,
|
||||
unencoded_offset, compression, encryption);
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
|
|||
}
|
||||
|
||||
if (*rctx->dest_dir_path == 0) {
|
||||
strncpy_null(rctx->cur_subvol_path, path);
|
||||
strncpy_null(rctx->cur_subvol_path, path, sizeof(rctx->cur_subvol_path));
|
||||
} else {
|
||||
ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
|
||||
path);
|
||||
|
@ -209,7 +209,7 @@ static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
|
|||
}
|
||||
|
||||
memset(&args_v1, 0, sizeof(args_v1));
|
||||
strncpy_null(args_v1.name, path);
|
||||
strncpy_null(args_v1.name, path, sizeof(args_v1.name));
|
||||
ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
|
@ -249,7 +249,7 @@ static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
|
|||
}
|
||||
|
||||
if (*rctx->dest_dir_path == 0) {
|
||||
strncpy_null(rctx->cur_subvol_path, path);
|
||||
strncpy_null(rctx->cur_subvol_path, path, sizeof(rctx->cur_subvol_path));
|
||||
} else {
|
||||
ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
|
||||
path);
|
||||
|
@ -281,7 +281,7 @@ static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
|
|||
}
|
||||
|
||||
memset(&args_v2, 0, sizeof(args_v2));
|
||||
strncpy_null(args_v2.name, path);
|
||||
strncpy_null(args_v2.name, path, sizeof(args_v2.name));
|
||||
|
||||
parent_subvol = subvol_uuid_search(rctx->mnt_fd, 0, parent_uuid,
|
||||
parent_ctransid, NULL,
|
||||
|
@ -663,7 +663,7 @@ static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
|
|||
error("cannot open %s: %m", path);
|
||||
goto out;
|
||||
}
|
||||
strncpy_null(rctx->write_path, path);
|
||||
strncpy_null(rctx->write_path, path, sizeof(rctx->write_path));
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
|
|
@ -266,8 +266,8 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
|
|||
goto leave_with_error;
|
||||
}
|
||||
} else if (path_is_block_device(srcdev) > 0) {
|
||||
strncpy((char *)start_args.start.srcdev_name, srcdev,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX);
|
||||
strncpy_null((char *)start_args.start.srcdev_name, srcdev,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX + 1);
|
||||
start_args.start.srcdevid = 0;
|
||||
srcdev_size = device_get_partition_size(srcdev);
|
||||
} else {
|
||||
|
@ -292,8 +292,8 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
|
|||
goto leave_with_error;
|
||||
}
|
||||
|
||||
strncpy((char *)start_args.start.tgtdev_name, dstdev,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX);
|
||||
strncpy_null((char *)start_args.start.tgtdev_name, dstdev,
|
||||
BTRFS_DEVICE_PATH_NAME_MAX + 1);
|
||||
ret = btrfs_prepare_device(fddstdev, dstdev, &dstdev_block_count, 0,
|
||||
PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE |
|
||||
(discard ? PREP_DEVICE_DISCARD : 0) |
|
||||
|
|
|
@ -1535,8 +1535,7 @@ static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
|
|||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
strncpy(dir_name, argv[optind + 1], sizeof dir_name);
|
||||
dir_name[sizeof dir_name - 1] = 0;
|
||||
strncpy_null(dir_name, argv[optind + 1], sizeof(dir_name));
|
||||
|
||||
/* Strip the trailing / on the dir name */
|
||||
len = strlen(dir_name);
|
||||
|
|
|
@ -1437,7 +1437,7 @@ static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
|
|||
sock_path, sizeof(sock_path));
|
||||
/* ignore EOVERFLOW, try using a shorter path for the socket */
|
||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
|
||||
strncpy_null(addr.sun_path, sock_path, sizeof(addr.sun_path));
|
||||
ret = bind(prg_fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret != -1 || errno != EADDRINUSE)
|
||||
break;
|
||||
|
|
|
@ -547,8 +547,7 @@ static int update_root(struct rb_root *root_lookup,
|
|||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
exit(1);
|
||||
}
|
||||
strncpy(ri->name, name, name_len);
|
||||
ri->name[name_len] = 0;
|
||||
strncpy_null(ri->name, name, name_len);
|
||||
}
|
||||
if (ref_tree)
|
||||
ri->ref_tree = ref_tree;
|
||||
|
@ -619,8 +618,7 @@ static int add_root(struct rb_root *root_lookup,
|
|||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
exit(1);
|
||||
}
|
||||
strncpy(ri->name, name, name_len);
|
||||
ri->name[name_len] = 0;
|
||||
strncpy_null(ri->name, name, name_len);
|
||||
}
|
||||
if (ref_tree)
|
||||
ri->ref_tree = ref_tree;
|
||||
|
|
|
@ -197,7 +197,7 @@ static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
|
|||
char dstdir_dup[PATH_MAX];
|
||||
char *token;
|
||||
|
||||
strncpy_null(dstdir_dup, dstdir);
|
||||
strncpy_null(dstdir_dup, dstdir, sizeof(dstdir_dup));
|
||||
if (dstdir_dup[0] == '/')
|
||||
strcat(p, "/");
|
||||
|
||||
|
@ -233,7 +233,7 @@ static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
|
|||
struct btrfs_ioctl_vol_args_v2 args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
strncpy_null(args.name, newname);
|
||||
strncpy_null(args.name, newname, sizeof(args.name));
|
||||
args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
|
||||
args.size = btrfs_qgroup_inherit_size(inherit);
|
||||
args.qgroup_inherit = inherit;
|
||||
|
@ -243,8 +243,7 @@ static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
|
|||
struct btrfs_ioctl_vol_args args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
strncpy_null(args.name, newname);
|
||||
|
||||
strncpy_null(args.name, newname, sizeof(args.name));
|
||||
ret = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
|
||||
}
|
||||
|
||||
|
@ -738,7 +737,7 @@ static int cmd_subvolume_snapshot(const struct cmd_struct *cmd, int argc, char *
|
|||
args.size = btrfs_qgroup_inherit_size(inherit);
|
||||
args.qgroup_inherit = inherit;
|
||||
}
|
||||
strncpy_null(args.name, newname);
|
||||
strncpy_null(args.name, newname, sizeof(args.name));
|
||||
|
||||
res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
|
||||
if (res < 0) {
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "common/utils.h"
|
||||
#include "common/defs.h"
|
||||
#include "common/open-utils.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "common/units.h"
|
||||
|
||||
static int btrfs_scan_done = 0;
|
||||
|
@ -237,7 +238,7 @@ int btrfs_register_one_device(const char *fname)
|
|||
return -errno;
|
||||
}
|
||||
memset(&args, 0, sizeof(args));
|
||||
strncpy_null(args.name, fname);
|
||||
strncpy_null(args.name, fname, sizeof(args.name));
|
||||
ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args);
|
||||
if (ret < 0) {
|
||||
error("device scan failed on '%s': %m", fname);
|
||||
|
@ -468,7 +469,7 @@ int btrfs_scan_devices(int verbose)
|
|||
if (!dev)
|
||||
continue;
|
||||
/* if we are here its definitely a btrfs disk*/
|
||||
strncpy_null(path, blkid_dev_devname(dev));
|
||||
strncpy_null(path, blkid_dev_devname(dev), sizeof(path));
|
||||
|
||||
if (stat(path, &dev_stat) < 0)
|
||||
continue;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "common/filesystem-utils.h"
|
||||
#include "common/messages.h"
|
||||
#include "common/open-utils.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "common/path-utils.h"
|
||||
|
||||
/*
|
||||
|
@ -102,7 +103,7 @@ static int set_label_unmounted(const char *dev, const char *label)
|
|||
error_msg(ERROR_MSG_START_TRANS, "set label");
|
||||
return PTR_ERR(trans);
|
||||
}
|
||||
__strncpy_null(root->fs_info->super_copy->label, label, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(root->fs_info->super_copy->label, label, BTRFS_LABEL_SIZE);
|
||||
|
||||
btrfs_commit_transaction(trans, root);
|
||||
|
||||
|
@ -123,7 +124,7 @@ static int set_label_mounted(const char *mount_path, const char *labelp)
|
|||
}
|
||||
|
||||
memset(label, 0, sizeof(label));
|
||||
__strncpy_null(label, labelp, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(label, labelp, BTRFS_LABEL_SIZE);
|
||||
if (ioctl(fd, BTRFS_IOC_SET_FSLABEL, label) < 0) {
|
||||
error("unable to set label of %s: %m", mount_path);
|
||||
close(fd);
|
||||
|
@ -152,8 +153,7 @@ int get_label_unmounted(const char *dev, char *label)
|
|||
if(!root)
|
||||
return -1;
|
||||
|
||||
__strncpy_null(label, root->fs_info->super_copy->label,
|
||||
BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(label, root->fs_info->super_copy->label, BTRFS_LABEL_SIZE);
|
||||
|
||||
/* Now we close it since we are done. */
|
||||
close_ctree(root);
|
||||
|
@ -187,7 +187,7 @@ int get_label_mounted(const char *mount_path, char *labelp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
__strncpy_null(labelp, label, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(labelp, label, BTRFS_LABEL_SIZE);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -222,6 +222,7 @@ static const struct btrfs_feature mkfs_features[] = {
|
|||
VERSION_NULL(default),
|
||||
.desc = "block group tree, more efficient block group tracking to reduce mount time"
|
||||
},
|
||||
#if EXPERIMENTAL
|
||||
{
|
||||
.name = "rst",
|
||||
.incompat_flag = BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE,
|
||||
|
@ -238,6 +239,7 @@ static const struct btrfs_feature mkfs_features[] = {
|
|||
VERSION_NULL(default),
|
||||
.desc = "raid stripe tree, enhanced file extent tracking"
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "squota",
|
||||
.incompat_flag = BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA,
|
||||
|
|
|
@ -68,8 +68,7 @@ static const struct btrfs_mkfs_features btrfs_convert_allowed_features = {
|
|||
BTRFS_FEATURE_INCOMPAT_BIG_METADATA |
|
||||
BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF |
|
||||
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA |
|
||||
BTRFS_FEATURE_INCOMPAT_NO_HOLES |
|
||||
BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE,
|
||||
BTRFS_FEATURE_INCOMPAT_NO_HOLES,
|
||||
.runtime_flags = BTRFS_FEATURE_RUNTIME_QUOTA,
|
||||
};
|
||||
|
||||
|
|
|
@ -47,8 +47,7 @@ void fixup_argv0(char **argv, const char *token)
|
|||
|
||||
void set_argv0(char **argv)
|
||||
{
|
||||
strncpy(argv0_buf, argv[0], sizeof(argv0_buf));
|
||||
argv0_buf[sizeof(argv0_buf) - 1] = 0;
|
||||
strncpy_null(argv0_buf, argv[0], sizeof(argv0_buf));
|
||||
}
|
||||
|
||||
int check_argc_exact(int nargs, int expected)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "common/messages.h"
|
||||
#include "common/path-utils.h"
|
||||
#include "common/device-scan.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "common/open-utils.h"
|
||||
|
||||
/*
|
||||
|
@ -103,10 +104,9 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
|
|||
}
|
||||
|
||||
/* Did we find an entry in mnt table? */
|
||||
if (mnt && size && where) {
|
||||
strncpy(where, mnt->mnt_dir, size);
|
||||
where[size-1] = 0;
|
||||
}
|
||||
if (mnt && size && where)
|
||||
strncpy_null(where, mnt->mnt_dir, size);
|
||||
|
||||
if (fs_dev_ret)
|
||||
*fs_dev_ret = fs_devices_mnt;
|
||||
else if (noscan)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include "common/string-utils.h"
|
||||
#include "common/path-utils.h"
|
||||
|
||||
/*
|
||||
|
@ -193,10 +194,10 @@ static int is_same_blk_file(const char* a, const char* b)
|
|||
char real_b[PATH_MAX];
|
||||
|
||||
if (!realpath(a, real_a))
|
||||
strncpy_null(real_a, a);
|
||||
strncpy_null(real_a, a, sizeof(real_a));
|
||||
|
||||
if (!realpath(b, real_b))
|
||||
strncpy_null(real_b, b);
|
||||
strncpy_null(real_b, b, sizeof(real_b));
|
||||
|
||||
/* Identical path? */
|
||||
if (strcmp(real_a, real_b) == 0)
|
||||
|
@ -345,26 +346,6 @@ char *path_canonicalize(const char *path)
|
|||
return canonical;
|
||||
}
|
||||
|
||||
/*
|
||||
* __strncpy_null - strncpy with null termination
|
||||
* @dest: the target array
|
||||
* @src: the source string
|
||||
* @n: maximum bytes to copy (size of *dest)
|
||||
*
|
||||
* Like strncpy, but ensures destination is null-terminated.
|
||||
*
|
||||
* Copies the string pointed to by src, including the terminating null
|
||||
* byte ('\0'), to the buffer pointed to by dest, up to a maximum
|
||||
* of n bytes. Then ensure that dest is null-terminated.
|
||||
*/
|
||||
char *__strncpy_null(char *dest, const char *src, size_t n)
|
||||
{
|
||||
strncpy(dest, src, n);
|
||||
if (n > 0)
|
||||
dest[n - 1] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if path is a directory
|
||||
* Returns:
|
||||
|
@ -403,7 +384,7 @@ int path_is_in_dir(const char *parent, const char *path)
|
|||
char *curr_dir = tmp;
|
||||
int ret;
|
||||
|
||||
strncpy_null(tmp, path);
|
||||
strncpy_null(tmp, path, sizeof(tmp));
|
||||
|
||||
while (strcmp(parent, curr_dir) != 0) {
|
||||
if (strcmp(curr_dir, "/") == 0) {
|
||||
|
@ -432,7 +413,7 @@ int arg_copy_path(char *dest, const char *src, int destlen)
|
|||
if (len >= PATH_MAX || len >= destlen)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
__strncpy_null(dest, src, destlen);
|
||||
strncpy_null(dest, src, destlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,11 +26,6 @@ char *path_canonicalize(const char *path);
|
|||
int arg_copy_path(char *dest, const char *src, int destlen);
|
||||
int path_cat_out(char *out, const char *p1, const char *p2);
|
||||
int path_cat3_out(char *out, const char *p1, const char *p2, const char *p3);
|
||||
|
||||
char *__strncpy_null(char *dest, const char *src, size_t n);
|
||||
/* Helper to always get proper size of the destination string */
|
||||
#define strncpy_null(dest, src) __strncpy_null(dest, src, sizeof(dest))
|
||||
|
||||
int path_is_block_device(const char *file);
|
||||
int path_is_a_mount_point(const char *file);
|
||||
int path_exists(const char *file);
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "common/sort-utils.h"
|
||||
#include "common/messages.h"
|
||||
|
||||
int compare_init(struct compare *comp, const struct sortdef *sortdef)
|
||||
{
|
||||
|
@ -55,3 +57,157 @@ int compare_add_sort_key(struct compare *comp, const char *key)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append given sort by its @id from associated sortdef.
|
||||
*
|
||||
* Return: 0 if id is valid
|
||||
* -1 if id not in sortdef
|
||||
*/
|
||||
int compare_add_sort_id(struct compare *comp, int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
if (id < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < SORT_MAX_KEYS; i++) {
|
||||
if (comp->sortdef[i].name == NULL)
|
||||
return -1;
|
||||
if (comp->sortdef[i].id == id) {
|
||||
comp->comp[comp->count] = comp->sortdef[i].comp;
|
||||
comp->count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consume word-like list of key names (coma separated) and return its id if
|
||||
* found in sortdef. The @next pointer is advanced to the next expected key start.
|
||||
* Empty and NULL @next is accepted.
|
||||
*
|
||||
* Key lookup is case insensitive.
|
||||
*
|
||||
* Retrun: id from sortdef if a matching
|
||||
* -1 on error
|
||||
* -2 end of buffer
|
||||
*/
|
||||
int compare_parse_key_to_id(const struct compare *comp, const char **next)
|
||||
{
|
||||
const char *tmp = *next, *start = *next;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
/* No sort string (use defaults), or last. */
|
||||
if (!*next || !**next)
|
||||
return -2;
|
||||
|
||||
do {
|
||||
/* End of word. */
|
||||
if (*tmp == ',' || *tmp == 0) {
|
||||
/* Look up in sortdef. */
|
||||
for (int i = 0; comp->sortdef[i].name; i++) {
|
||||
int len = strlen(comp->sortdef[i].name);
|
||||
|
||||
if (strncasecmp(start, comp->sortdef[i].name, len) == 0) {
|
||||
/* Point to last NUL. */
|
||||
*next = tmp;
|
||||
/* Or the next valid char. */
|
||||
if (*tmp)
|
||||
(*next)++;
|
||||
return comp->sortdef[i].id;
|
||||
}
|
||||
}
|
||||
/* Not found, report which one. */
|
||||
*next = start;
|
||||
return -1;
|
||||
}
|
||||
/* Invalid char found. */
|
||||
if (!isalnum(*tmp)) {
|
||||
*next = tmp;
|
||||
return -1;
|
||||
}
|
||||
tmp++;
|
||||
} while(1);
|
||||
|
||||
/* Not found. */
|
||||
*next = start;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read id of its associated sort @key. Key lookup is case insensitive. */
|
||||
int compare_key_id(const struct compare *comp, const char *key)
|
||||
{
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (strcasecmp(comp->sortdef[i].name, key) == 0)
|
||||
return comp->sortdef[i].id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read sort key name associated to @id. */
|
||||
const char *compare_id_name(const struct compare *comp, int id)
|
||||
{
|
||||
if (!comp->sortdef)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (comp->sortdef[i].id == id)
|
||||
return comp->sortdef[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given @id (must exist in the associated sortdef) enabled in
|
||||
* @comp.
|
||||
*/
|
||||
bool compare_has_id(const struct compare *comp, int id)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return false;
|
||||
|
||||
idx = -1;
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (comp->sortdef[i].id == id)
|
||||
idx = i;
|
||||
|
||||
if (idx < 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < comp->count; i++)
|
||||
if (comp->comp[i] == comp->sortdef[idx].comp)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up compare structure with associated sortdef from a user specified list
|
||||
* of keys.
|
||||
*/
|
||||
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def)
|
||||
{
|
||||
const char *tmp;
|
||||
int id;
|
||||
|
||||
tmp = def;
|
||||
do {
|
||||
id = compare_parse_key_to_id(comp, &tmp);
|
||||
if (id == -1) {
|
||||
error("unknown sort key: %s", tmp);
|
||||
return -1;
|
||||
}
|
||||
compare_add_sort_id(comp, id);
|
||||
} while (id >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#ifndef __COMMON_SORT_UTILS_H__
|
||||
#define __COMMON_SORT_UTILS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Example:
|
||||
|
||||
|
@ -48,7 +50,7 @@ void test() {
|
|||
.desc = "sort by id" },
|
||||
{ .name = "size", .comp = (sort_cmp_t)cmp_entry_size,
|
||||
.desc = "sort by entry size" },
|
||||
{ .name = NULL, .comp = NULL }
|
||||
SORTDEF_END
|
||||
};
|
||||
// List of keys to use for sort (e.g. from command line options)
|
||||
const char *sortby[] = { "size", "id" };
|
||||
|
@ -66,17 +68,24 @@ void test() {
|
|||
}
|
||||
*/
|
||||
|
||||
#define SORTDEF_END { .name = NULL, .comp = NULL }
|
||||
#define SORT_MAX_KEYS 32
|
||||
|
||||
typedef int (*sort_cmp_t)(const void *a, const void *b);
|
||||
typedef int (*sort_r_cmp_t)(const void *a, const void *b, void *data);
|
||||
|
||||
#define SORTDEF_END { .name = NULL, .comp = NULL }
|
||||
|
||||
struct sortdef {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
sort_cmp_t comp;
|
||||
/* User defined identifier of this sort key. */
|
||||
int id;
|
||||
};
|
||||
|
||||
struct compare {
|
||||
sort_cmp_t comp[32];
|
||||
sort_cmp_t comp[SORT_MAX_KEYS];
|
||||
unsigned long invert_map;
|
||||
int count;
|
||||
const struct sortdef *sortdef;
|
||||
|
@ -85,5 +94,11 @@ struct compare {
|
|||
int compare_init(struct compare *comp, const struct sortdef *sortdef);
|
||||
int compare_cmp_multi(const void *a, const void *b, const struct compare *comp);
|
||||
int compare_add_sort_key(struct compare *comp, const char *key);
|
||||
int compare_parse_key_to_id(const struct compare *comp, const char **next);
|
||||
int compare_add_sort_id(struct compare *comp, int id);
|
||||
int compare_key_id(const struct compare *comp, const char *key);
|
||||
const char *compare_id_name(const struct compare *comp, int id);
|
||||
bool compare_has_id(const struct compare *comp, int id);
|
||||
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,26 @@ int string_has_prefix(const char *str, const char *prefix)
|
|||
return (unsigned char)*prefix - (unsigned char)*str;
|
||||
}
|
||||
|
||||
/*
|
||||
* strncpy_null - strncpy with null termination
|
||||
* @dest: the target array
|
||||
* @src: the source string
|
||||
* @n: maximum bytes to copy (size of *dest)
|
||||
*
|
||||
* Like strncpy, but ensures destination is null-terminated.
|
||||
*
|
||||
* Copies the string pointed to by src, including the terminating null
|
||||
* byte ('\0'), to the buffer pointed to by dest, up to a maximum
|
||||
* of n bytes. Then ensure that dest is null-terminated.
|
||||
*/
|
||||
char *strncpy_null(char *dest, const char *src, size_t n)
|
||||
{
|
||||
strncpy(dest, src, n);
|
||||
if (n > 0)
|
||||
dest[n - 1] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should be only used when parsing command arg, it won't return
|
||||
* error to its caller and rather exit directly just like usage().
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
int string_is_numerical(const char *str);
|
||||
int string_has_prefix(const char *str, const char *prefix);
|
||||
|
||||
char *strncpy_null(char *dest, const char *src, size_t n);
|
||||
|
||||
/*
|
||||
* Helpers prefixed by arg_* can exit if the argument is invalid and are supposed
|
||||
* to be used when parsing command line options where the immediate exit is valid
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "kernel-shared/uapi/btrfs_tree.h"
|
||||
#include "common/path-utils.h"
|
||||
#include "common/messages.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "common/fsfeatures.h"
|
||||
#include "mkfs/common.h"
|
||||
#include "convert/common.h"
|
||||
|
@ -148,7 +149,7 @@ static int setup_temp_super(int fd, struct btrfs_mkfs_config *cfg,
|
|||
btrfs_set_super_cache_generation(&super, -1);
|
||||
btrfs_set_super_incompat_flags(&super, cfg->features.incompat_flags);
|
||||
if (cfg->label)
|
||||
__strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE);
|
||||
|
||||
/* Sys chunk array will be re-initialized at chunk tree init time */
|
||||
super.sys_chunk_array_size = 0;
|
||||
|
|
|
@ -1322,8 +1322,7 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
|
|||
|
||||
memset(root->fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE);
|
||||
if (convert_flags & CONVERT_FLAG_COPY_LABEL) {
|
||||
__strncpy_null(root->fs_info->super_copy->label,
|
||||
cctx.label, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(root->fs_info->super_copy->label, cctx.label, BTRFS_LABEL_SIZE);
|
||||
printf("Copy label '%s'\n", root->fs_info->super_copy->label);
|
||||
} else if (convert_flags & CONVERT_FLAG_SET_LABEL) {
|
||||
strcpy(root->fs_info->super_copy->label, fslabel);
|
||||
|
@ -1938,7 +1937,7 @@ int BOX_MAIN(convert)(int argc, char *argv[])
|
|||
"label too long, trimmed to %d bytes",
|
||||
BTRFS_LABEL_SIZE - 1);
|
||||
}
|
||||
__strncpy_null(fslabel, optarg, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(fslabel, optarg, BTRFS_LABEL_SIZE);
|
||||
break;
|
||||
case 'L':
|
||||
copylabel = CONVERT_FLAG_COPY_LABEL;
|
||||
|
@ -1997,7 +1996,7 @@ int BOX_MAIN(convert)(int argc, char *argv[])
|
|||
error("invalid UUID: %s\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
strncpy(fsid, optarg, sizeof(fsid));
|
||||
strncpy_null(fsid, optarg, sizeof(fsid));
|
||||
}
|
||||
break;
|
||||
case GETOPT_VAL_HELP:
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "kernel-shared/file-item.h"
|
||||
#include "common/extent-cache.h"
|
||||
#include "common/messages.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "convert/common.h"
|
||||
#include "convert/source-fs.h"
|
||||
#include "convert/source-ext2.h"
|
||||
|
@ -638,7 +639,7 @@ static int ext2_copy_single_xattr(struct btrfs_trans_handle *trans,
|
|||
data = databuf;
|
||||
datalen = bufsize;
|
||||
}
|
||||
strncpy(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX);
|
||||
strncpy_null(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX);
|
||||
strncat(namebuf, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len);
|
||||
if (name_len + datalen > BTRFS_LEAF_DATA_SIZE(root->fs_info) -
|
||||
sizeof(struct btrfs_item) - sizeof(struct btrfs_dir_item)) {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "common/defs.h"
|
||||
#include "common/internal.h"
|
||||
#include "common/messages.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "uapi/btrfs.h"
|
||||
|
||||
static void print_dir_item_type(struct extent_buffer *eb,
|
||||
|
@ -186,7 +187,7 @@ static void bg_flags_to_str(u64 flags, char *ret)
|
|||
ret[0] = '\0';
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA) {
|
||||
empty = 0;
|
||||
strncpy(ret, "DATA", BG_FLAG_STRING_LEN);
|
||||
strncpy_null(ret, "DATA", BG_FLAG_STRING_LEN);
|
||||
}
|
||||
if (flags & BTRFS_BLOCK_GROUP_METADATA) {
|
||||
if (!empty)
|
||||
|
@ -209,7 +210,7 @@ static void bg_flags_to_str(u64 flags, char *ret)
|
|||
* Thus here we only fill @profile if it's not single.
|
||||
*/
|
||||
if (strncmp(name, "SINGLE", strlen("SINGLE")) != 0)
|
||||
strncpy(profile, name, BG_FLAG_STRING_LEN);
|
||||
strncpy_null(profile, name, BG_FLAG_STRING_LEN);
|
||||
}
|
||||
if (profile[0]) {
|
||||
strncat(ret, "|", BG_FLAG_STRING_LEN);
|
||||
|
@ -1398,7 +1399,7 @@ static void print_header_info(struct extent_buffer *eb, unsigned int mode)
|
|||
#define DEV_REPLACE_STRING_LEN 64
|
||||
#define CASE_DEV_REPLACE_MODE_ENTRY(dest, name) \
|
||||
case BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_##name: \
|
||||
strncpy((dest), #name, DEV_REPLACE_STRING_LEN); \
|
||||
strncpy_null((dest), #name, DEV_REPLACE_STRING_LEN); \
|
||||
break;
|
||||
|
||||
static void replace_mode_to_str(u64 flags, char *ret)
|
||||
|
@ -1415,7 +1416,7 @@ static void replace_mode_to_str(u64 flags, char *ret)
|
|||
|
||||
#define CASE_DEV_REPLACE_STATE_ENTRY(dest, name) \
|
||||
case BTRFS_IOCTL_DEV_REPLACE_STATE_##name: \
|
||||
strncpy((dest), #name, DEV_REPLACE_STRING_LEN); \
|
||||
strncpy_null((dest), #name, DEV_REPLACE_STRING_LEN); \
|
||||
break;
|
||||
|
||||
static void replace_state_to_str(u64 flags, char *ret)
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "common/path-utils.h"
|
||||
#include "common/device-utils.h"
|
||||
#include "common/open-utils.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "mkfs/common.h"
|
||||
|
||||
static u64 reference_root_table[] = {
|
||||
|
@ -476,7 +477,7 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
|||
btrfs_set_super_nr_global_roots(&super, 1);
|
||||
|
||||
if (cfg->label)
|
||||
__strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE - 1);
|
||||
strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE);
|
||||
|
||||
/* create the tree of root objects */
|
||||
memset(buf->data, 0, cfg->nodesize);
|
||||
|
|
|
@ -1361,8 +1361,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
|||
source_dir = strdup(optarg);
|
||||
break;
|
||||
case 'U':
|
||||
strncpy(fs_uuid, optarg,
|
||||
BTRFS_UUID_UNPARSED_SIZE - 1);
|
||||
strncpy_null(fs_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE);
|
||||
break;
|
||||
case 'K':
|
||||
opt_discard = false;
|
||||
|
@ -1371,7 +1370,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
|||
bconf_be_quiet();
|
||||
break;
|
||||
case GETOPT_VAL_DEVICE_UUID:
|
||||
strncpy(dev_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE - 1);
|
||||
strncpy_null(dev_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE);
|
||||
break;
|
||||
case GETOPT_VAL_SHRINK:
|
||||
shrink_rootdir = true;
|
||||
|
@ -1693,7 +1692,9 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
|||
case BTRFS_BLOCK_GROUP_RAID1C4:
|
||||
case BTRFS_BLOCK_GROUP_RAID0:
|
||||
case BTRFS_BLOCK_GROUP_RAID10:
|
||||
#if EXPERIMENTAL
|
||||
features.incompat_flags |= BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -6,7 +6,7 @@ source "$TEST_TOP/common" || exit
|
|||
check_prereq btrfs
|
||||
|
||||
# returns 1
|
||||
run_mayfail $TOP/btrfs || true
|
||||
run_mayfail "$TOP/btrfs" || true
|
||||
run_check "$TOP/btrfs" version
|
||||
run_check "$TOP/btrfs" version --
|
||||
run_check "$TOP/btrfs" help
|
||||
|
|
|
@ -13,7 +13,7 @@ prepare_test_dev
|
|||
run_check_mkfs_test_dev
|
||||
run_check_mount_test_dev
|
||||
|
||||
here=`pwd`
|
||||
here=$(pwd)
|
||||
cd "$TEST_MNT" || _fail "cannot chdir to TEST_MNT"
|
||||
|
||||
run_check $SUDO_HELPER "$TOP/btrfs" subvolume create subv-parent
|
||||
|
|
|
@ -13,14 +13,14 @@ check_default_id()
|
|||
{
|
||||
id=$(run_check_stdout $SUDO_HELPER "$TOP/btrfs" subvolume get-default .) \
|
||||
|| { echo "$id"; exit 1; }
|
||||
if $(echo "$id" | grep -vq "ID $1"); then
|
||||
if echo "$id" | grep -vq "ID $1"; then
|
||||
_fail "subvolume get-default: default id is not $1, but $id"
|
||||
fi
|
||||
}
|
||||
|
||||
run_check_mkfs_test_dev
|
||||
run_check_mount_test_dev
|
||||
cd "$TEST_MNT"
|
||||
cd "$TEST_MNT" || _fail "Cannot cd into TEST_MNT $TEST_MNT"
|
||||
|
||||
check_default_id 5
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ test_run_commands() {
|
|||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -d single -m single "${loopdevs[@]}"
|
||||
run_check_mount_test_dev
|
||||
run_check "$TOP/btrfs" filesystem usage "$TEST_MNT"
|
||||
for i in `seq 10`; do
|
||||
run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT"/file$i bs=100M count=1 status=none
|
||||
for i in $(seq 10); do
|
||||
run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT/file$i" bs=100M count=1 status=none
|
||||
done
|
||||
# Create filesystem with single and RAID1 profiles
|
||||
run_check $SUDO_HELPER "$TOP/btrfs" balance start -dconvert=raid1,limit=1 "$TEST_MNT"
|
||||
|
@ -76,8 +76,8 @@ run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f --mixed -d single -m single "${loopd
|
|||
run_check_mount_test_dev
|
||||
run_check "$TOP/btrfs" filesystem usage "$TEST_MNT"
|
||||
# Create 1 and a half of 1G chunks
|
||||
for i in `seq 14`; do
|
||||
run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT"/file$i bs=100M count=1 status=none
|
||||
for i in $(seq 14); do
|
||||
run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT/file$i" bs=100M count=1 status=none
|
||||
done
|
||||
# Create filesystem with single and RAID1 profiles, the limit=1 trick does not work
|
||||
# so use the usage filter to convert about half of the filesystem
|
||||
|
|
|
@ -63,7 +63,7 @@ test_raid1()
|
|||
set -- $i
|
||||
IFS=$OLDIFS
|
||||
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -d"$1" ${loopdevs[@]}
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -d"$1" "${loopdevs[@]}"
|
||||
run_check_mount_test_dev
|
||||
vars=($(report_numbers))
|
||||
data_chunk_size=${vars[1]}
|
||||
|
@ -87,7 +87,7 @@ test_raid0()
|
|||
local used_on_dev
|
||||
local data_ratio
|
||||
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -draid0 ${loopdevs[@]}
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -draid0 "${loopdevs[@]}"
|
||||
run_check_mount_test_dev
|
||||
vars=($(report_numbers))
|
||||
data_chunk_size=${vars[1]}
|
||||
|
@ -118,7 +118,7 @@ test_raid56()
|
|||
set -- $i
|
||||
IFS=$OLDIFS
|
||||
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -d"$1" ${loopdevs[@]}
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -d"$1" "${loopdevs[@]}"
|
||||
run_check_mount_test_dev
|
||||
vars=($(report_numbers))
|
||||
data_chunk_size=${vars[1]}
|
||||
|
|
|
@ -36,11 +36,11 @@ fi
|
|||
|
||||
# Set the limits by command
|
||||
here=`pwd`
|
||||
cd "$sysfs/devinfo"
|
||||
cd "$sysfs/devinfo" || _fail "Cannot cd to $sysfs/devinfo"
|
||||
for i in *; do
|
||||
run_check $SUDO_HELPER "$TOP/btrfs" scrub limit -d "$i" -l 20m "$TEST_MNT"
|
||||
done
|
||||
cd "$here"
|
||||
cd "$here" || _fail "Cannot cd to $here"
|
||||
run_check "$TOP/btrfs" scrub limit "$TEST_MNT"
|
||||
|
||||
# Set limits for all devices
|
||||
|
|
40
tests/common
40
tests/common
|
@ -6,6 +6,22 @@
|
|||
# Temporary array for building the final command, injecting arguments as needed
|
||||
declare -a cmd_array
|
||||
|
||||
# Check if a given option in config.h is set to 1
|
||||
# $1: config option name
|
||||
_test_config()
|
||||
{
|
||||
local feature="$1"
|
||||
|
||||
if [ ! -f "$TOP/include/config.h" ]; then
|
||||
echo "include/config.h not exists"
|
||||
exit 1
|
||||
fi
|
||||
if grep -q "$feature.*1" "${TOP}/include/config.h"; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# assert that argument is not empty and is an existing path (file or directory)
|
||||
_assert_path()
|
||||
{
|
||||
|
@ -220,7 +236,13 @@ run_check()
|
|||
echo "====== RUN CHECK ${cmd_array[@]}" >> "$RESULTS" 2>&1
|
||||
if [[ $TEST_LOG =~ tty ]]; then echo "CMD: ${cmd_array[@]}" > /dev/tty; fi
|
||||
|
||||
"${cmd_array[@]}" >> "$RESULTS" 2>&1 || _fail "failed: ${cmd_array[@]}"
|
||||
"${cmd_array[@]}" >> "$RESULTS" 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
if cat "${cmd_array[@]}" | grep -q mount; then
|
||||
dmesg | tail -n 15 >> "$RESULTS"
|
||||
fi
|
||||
_fail "failed: ${cmd_array[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# same as run_check but the stderr+stdout output is duplicated on stdout and
|
||||
|
@ -370,11 +392,25 @@ run_mustfail_stdout()
|
|||
fi
|
||||
}
|
||||
|
||||
check_experimental_build()
|
||||
{
|
||||
if ! _test_config "EXPERIMENTAL"; then
|
||||
_not_run "This test requires experimental build"
|
||||
fi
|
||||
}
|
||||
|
||||
check_regular_build()
|
||||
{
|
||||
if _test_config "EXPERIMENTAL"; then
|
||||
_not_run "This test requires non-experimental build"
|
||||
fi
|
||||
}
|
||||
|
||||
check_prereq()
|
||||
{
|
||||
# Internal tools for testing, not shipped with the package
|
||||
case "$1" in
|
||||
btrfs-corrupt-block|btrfs-find-root|btrfs-select-super|fssum)
|
||||
btrfs-corrupt-block|btrfs-find-root|btrfs-select-super|fssum|btrfs-sb-mod)
|
||||
if ! [ -f "$INTERNAL_BIN/$1" ]; then
|
||||
_fail "Failed prerequisites: $INTERNAL_BIN/$1";
|
||||
fi
|
||||
|
|
|
@ -12,7 +12,7 @@ check_kernel_support_acl
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree'; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
convert_test ext2 "$feature" "ext2 4k nodesize" 4096 mke2fs -b 4096
|
||||
convert_test ext2 "$feature" "ext2 16k nodesize" 16384 mke2fs -b 4096
|
||||
convert_test ext2 "$feature" "ext2 64k nodesize" 65536 mke2fs -b 4096
|
||||
|
|
|
@ -12,7 +12,7 @@ check_kernel_support_acl
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree' ; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
convert_test ext4 "$feature" "ext4 4k nodesize" 4096 mke2fs -t ext4 -b 4096
|
||||
convert_test ext4 "$feature" "ext4 16k nodesize" 16384 mke2fs -t ext4 -b 4096
|
||||
convert_test ext4 "$feature" "ext4 64k nodesize" 65536 mke2fs -t ext4 -b 4096
|
||||
|
|
|
@ -68,7 +68,7 @@ do_test() {
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree' ; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
do_test "$feature" "ext4 4k nodesize" 4096 mke2fs -t ext4 -b 4096
|
||||
do_test "$feature" "ext4 16k nodesize" 16384 mke2fs -t ext4 -b 4096
|
||||
do_test "$feature" "ext4 64k nodesize" 65536 mke2fs -t ext4 -b 4096
|
||||
|
|
|
@ -15,7 +15,7 @@ prepare_test_dev
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree'; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
convert_test reiserfs "$feature" "reiserfs 4k nodesize" 4096 mkreiserfs -b 4096
|
||||
convert_test reiserfs "$feature" "reiserfs 16k nodesize" 16384 mkreiserfs -b 4096
|
||||
convert_test reiserfs "$feature" "reiserfs 64k nodesize" 65536 mkreiserfs -b 4096
|
||||
|
|
|
@ -70,7 +70,7 @@ do_test() {
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree'; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
do_test "$feature" "reiserfs 4k nodesize" 4096 mkreiserfs -b 4096
|
||||
do_test "$feature" "reiserfs 16k nodesize" 16384 mkreiserfs -b 4096
|
||||
do_test "$feature" "reiserfs 64k nodesize" 65536 mkreiserfs -b 4096
|
||||
|
|
|
@ -17,6 +17,6 @@ prepare_test_dev
|
|||
|
||||
# Iterate over defaults and options that are not tied to hardware capabilities
|
||||
# or number of devices. Test only 4K block size as minimum.
|
||||
for feature in '' 'block-group-tree' 'raid-stripe-tree'; do
|
||||
for feature in '' 'block-group-tree'; do
|
||||
convert_test ntfs "$feature" "ntfs 4k nodesize" 4096 mkfs.ntfs -s 4096
|
||||
done
|
||||
|
|
|
@ -524,6 +524,7 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in)
|
|||
int ret;
|
||||
int fd;
|
||||
int excl;
|
||||
int error = 0;
|
||||
sum_file_data_t sum_file_data = flags[FLAG_STRUCTURE] ?
|
||||
sum_file_data_strict : sum_file_data_permissive;
|
||||
struct stat dir_st;
|
||||
|
@ -542,18 +543,22 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in)
|
|||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
||||
continue;
|
||||
if (entries == alloclen) {
|
||||
void *tmp;
|
||||
|
||||
alloclen += CHUNKS;
|
||||
namelist = realloc(namelist,
|
||||
alloclen * sizeof(*namelist));
|
||||
if (!namelist) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
tmp = realloc(namelist, alloclen * sizeof(*namelist));
|
||||
if (!tmp) {
|
||||
fprintf(stderr, "realloc failed\n");
|
||||
error = 1;
|
||||
goto free_namelist;
|
||||
}
|
||||
namelist = tmp;
|
||||
}
|
||||
namelist[entries] = strdup(de->d_name);
|
||||
if (!namelist[entries]) {
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
fprintf(stderr, "stdup failed\n");
|
||||
error = 1;
|
||||
goto free_namelist;
|
||||
}
|
||||
++entries;
|
||||
}
|
||||
|
@ -577,13 +582,15 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in)
|
|||
ret = fchdir(dirfd);
|
||||
if (ret == -1) {
|
||||
perror("fchdir");
|
||||
exit(-1);
|
||||
error = 1;
|
||||
goto free_namelist;
|
||||
}
|
||||
ret = lstat(namelist[i], &st);
|
||||
if (ret) {
|
||||
fprintf(stderr, "stat failed for %s/%s: %m\n",
|
||||
path_prefix, path);
|
||||
exit(-1);
|
||||
error = 1;
|
||||
goto free_namelist;
|
||||
}
|
||||
|
||||
/* We are crossing into a different subvol, skip this subtree. */
|
||||
|
@ -704,6 +711,14 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in)
|
|||
next:
|
||||
free(path);
|
||||
}
|
||||
|
||||
free_namelist:
|
||||
closedir(d);
|
||||
for (i = 0; i < entries; i++)
|
||||
free(namelist[i]);
|
||||
free(namelist);
|
||||
if (error)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
68
tests/fuzz-tests/010-simple-sb/test.sh
Executable file
68
tests/fuzz-tests/010-simple-sb/test.sh
Executable file
|
@ -0,0 +1,68 @@
|
|||
#!/bin/bash
|
||||
# Change fields in super block and do test run of 'btrfs check'
|
||||
|
||||
source "$TEST_TOP/common" || exit
|
||||
source "$TEST_TOP/common.convert" || exit
|
||||
|
||||
check_prereq btrfs-sb-mod
|
||||
|
||||
setup_root_helper
|
||||
prepare_test_dev
|
||||
|
||||
run_check_mkfs_test_dev
|
||||
run_check_mount_test_dev
|
||||
#populate_fs
|
||||
generate_dataset "small"
|
||||
generate_dataset "sparse"
|
||||
run_check_umount_test_dev
|
||||
|
||||
# See btrfs-sb-mod --help
|
||||
fields=(
|
||||
bytenr
|
||||
flags
|
||||
magic
|
||||
generation
|
||||
root
|
||||
chunk_root
|
||||
log_root
|
||||
total_bytes
|
||||
bytes_used
|
||||
root_dir_objectid
|
||||
num_devices
|
||||
sectorsize
|
||||
nodesize
|
||||
stripesize
|
||||
sys_chunk_array_size
|
||||
chunk_root_generation
|
||||
compat_flags
|
||||
compat_ro_flags
|
||||
incompat_flags
|
||||
csum_type
|
||||
root_level
|
||||
chunk_root_level
|
||||
log_root_level
|
||||
cache_generation
|
||||
uuid_tree_generation
|
||||
dev_item.devid
|
||||
dev_item.total_bytes
|
||||
dev_item.bytes_used
|
||||
dev_item.io_align
|
||||
dev_item.io_width
|
||||
dev_item.sector_size
|
||||
dev_item.type
|
||||
dev_item.generation
|
||||
dev_item.start_offset
|
||||
dev_item.dev_group
|
||||
dev_item.seek_speed
|
||||
dev_item.bandwidth)
|
||||
|
||||
for field in "${fields[@]}"; do
|
||||
for op in -1 +1 ^2 ^4 ^256 +4096 -4096 @; do
|
||||
run_check $SUDO_HELPER truncate -s 0 image.test
|
||||
run_check $SUDO_HELPER cp --reflink=auto --sparse=auto "$TEST_DEV" image.test
|
||||
run_check $SUDO_HELPER "$TOP/btrfs-sb-mod" image.test "$field" "$op"
|
||||
run_mayfail $SUDO_HELPER "$TOP/btrfs" check image.test
|
||||
done
|
||||
done
|
||||
|
||||
run_check $SUDO_HELPER rm -f -- image.test
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
# Verify that receive --dump escapes paths for rename, symlink and hardlink
|
||||
# when it's the "dest=" value
|
||||
# when it's the "dest=" value, clone (source path) and xattr name and value
|
||||
|
||||
source "$TEST_TOP/common" || exit
|
||||
|
||||
|
@ -19,7 +19,7 @@ run_check $SUDO_HELPER ln -s "$TEST_MNT/subv1/file
|
|||
failed symlink source" "$TEST_MNT/subv1/file
|
||||
failed symlink target"
|
||||
|
||||
# Hardlinke
|
||||
# Hardlink
|
||||
run_check $SUDO_HELPER touch "$TEST_MNT/subv1/file
|
||||
failed link source"
|
||||
|
||||
|
@ -27,6 +27,19 @@ run_check $SUDO_HELPER ln "$TEST_MNT/subv1/file
|
|||
failed link source" "$TEST_MNT/subv1/file
|
||||
failed link target"
|
||||
|
||||
# Xattr name and value, create
|
||||
run_check $SUDO_HELPER touch "$TEST_MNT/subv1/xattr-file"
|
||||
run_check $SUDO_HELPER setfattr -n user.'name
|
||||
failed xattr name' -v '123
|
||||
failed xattr value' "$TEST_MNT/subv1/xattr-file"
|
||||
|
||||
# Clone
|
||||
run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT/subv1/clone-source
|
||||
failed clone source write" bs=1M count=1
|
||||
run_check $SUDO_HELPER cp --reflink=always "$TEST_MNT/subv1/clone-source
|
||||
failed clone source write" "$TEST_MNT/subv1/clone-target
|
||||
failed clone target"
|
||||
|
||||
run_check $SUDO_HELPER "$TOP/btrfs" subvolume snapshot -r "$TEST_MNT/subv1" "$TEST_MNT/snap1"
|
||||
_mktemp_local send.stream
|
||||
run_check $SUDO_HELPER "$TOP/btrfs" send -f send.stream "$TEST_MNT/snap1"
|
||||
|
|
30
tests/misc-tests/064-csum-conversion-basic/test.sh
Executable file
30
tests/misc-tests/064-csum-conversion-basic/test.sh
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/bin/bash
|
||||
# Verify the csum conversion works as expected.
|
||||
|
||||
source "$TEST_TOP/common" || exit
|
||||
source "$TEST_TOP/common.convert" || exit
|
||||
|
||||
check_experimental_build
|
||||
setup_root_helper
|
||||
prepare_test_dev
|
||||
|
||||
convert_to_csum()
|
||||
{
|
||||
local new_csum="$1"
|
||||
|
||||
run_check "$TOP/btrfstune" --csum "$new_csum" "$TEST_DEV"
|
||||
run_check "$TOP/btrfs" check --check-data-csum "$TEST_DEV"
|
||||
}
|
||||
|
||||
run_check_mkfs_test_dev --csum crc32c
|
||||
|
||||
# We only mount the filesystem once to populate its contents, later one we
|
||||
# would never mount the fs (to reduce the dependency on kernel features).
|
||||
run_check_mount_test_dev
|
||||
populate_fs
|
||||
run_check_umount_test_dev
|
||||
|
||||
convert_to_csum xxhash
|
||||
convert_to_csum blake2
|
||||
convert_to_csum sha256
|
||||
convert_to_csum crc32c
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
source "$TEST_TOP/common" || exit
|
||||
|
||||
check_experimental_build
|
||||
check_prereq mkfs.btrfs
|
||||
check_prereq btrfs
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
source "$TEST_TOP/common" || exit
|
||||
|
||||
check_experimental_build
|
||||
setup_root_helper
|
||||
setup_nullbdevs 4 128 4
|
||||
prepare_nullbdevs
|
||||
|
|
34
tests/mkfs-tests/033-zoned-reject-rst/test.sh
Executable file
34
tests/mkfs-tests/033-zoned-reject-rst/test.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
# Verify mkfs for all currently supported profiles of zoned + raid-stripe-tree
|
||||
|
||||
source "$TEST_TOP/common" || exit
|
||||
|
||||
check_regular_build
|
||||
setup_root_helper
|
||||
setup_nullbdevs 4 128 4
|
||||
prepare_nullbdevs
|
||||
TEST_DEV=${nullb_devs[1]}
|
||||
|
||||
profiles="dup raid1 raid1c3 raid1c4 raid10"
|
||||
|
||||
# The existing supported profiles.
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned -d single -m single "${nullb_devs[@]}"
|
||||
run_check $SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned -d single -m DUP "${nullb_devs[@]}"
|
||||
|
||||
# RST feature is rejected
|
||||
run_mustfail "RST feature created" \
|
||||
$SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned,raid-stripe-tree -d single -m DUP "${nullb_devs[@]}"
|
||||
|
||||
for dprofile in $profiles; do
|
||||
# Make sure additional data profiles won't enable RST for non-experimental build
|
||||
run_mustfail "unsupported profile created" \
|
||||
$SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned -d "$dprofile" -m DUP "${nullb_devs[@]}"
|
||||
done
|
||||
|
||||
# The old unsupported profiles should fail no matter if experimental build is enabled or not.
|
||||
run_mustfail "unsupported profile raid56 created" \
|
||||
$SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned -d raid5 -m raid5 "${nullb_devs[@]}"
|
||||
run_mustfail "unsupported profile raid56 created" \
|
||||
$SUDO_HELPER "$TOP/mkfs.btrfs" -f -O zoned -d raid6 -m raid6 "${nullb_devs[@]}"
|
||||
|
||||
cleanup_nullbdevs
|
|
@ -224,14 +224,25 @@ out:
|
|||
* item.
|
||||
*/
|
||||
#define CSUM_CHANGE_BYTES_THRESHOLD (SZ_2M)
|
||||
|
||||
static unsigned int calc_csum_change_nr_items(struct btrfs_fs_info *fs_info,
|
||||
u16 new_csum_type)
|
||||
{
|
||||
const u32 new_csum_size = btrfs_csum_type_size(new_csum_type);
|
||||
const u32 csum_item_size = CSUM_CHANGE_BYTES_THRESHOLD /
|
||||
fs_info->sectorsize * new_csum_size;
|
||||
|
||||
return round_up(csum_item_size, fs_info->nodesize) / fs_info->nodesize * 2;
|
||||
}
|
||||
|
||||
static int generate_new_data_csums_range(struct btrfs_fs_info *fs_info, u64 start,
|
||||
u16 new_csum_type)
|
||||
{
|
||||
const unsigned int nr_items = calc_csum_change_nr_items(fs_info, new_csum_type);
|
||||
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, 0);
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_path path = { 0 };
|
||||
struct btrfs_key key;
|
||||
const u32 new_csum_size = btrfs_csum_type_size(new_csum_type);
|
||||
void *csum_buffer;
|
||||
u64 converted_bytes = 0;
|
||||
u64 last_csum;
|
||||
|
@ -248,9 +259,7 @@ static int generate_new_data_csums_range(struct btrfs_fs_info *fs_info, u64 star
|
|||
if (!csum_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
trans = btrfs_start_transaction(csum_root,
|
||||
CSUM_CHANGE_BYTES_THRESHOLD / fs_info->sectorsize *
|
||||
new_csum_size);
|
||||
trans = btrfs_start_transaction(csum_root, nr_items);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
errno = -ret;
|
||||
|
@ -306,9 +315,7 @@ static int generate_new_data_csums_range(struct btrfs_fs_info *fs_info, u64 star
|
|||
return -EUCLEAN;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
trans = btrfs_start_transaction(csum_root,
|
||||
CSUM_CHANGE_BYTES_THRESHOLD /
|
||||
fs_info->sectorsize * new_csum_size);
|
||||
trans = btrfs_start_transaction(csum_root, nr_items);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
goto out;
|
||||
|
|
Loading…
Reference in a new issue