summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-image.c8
-rw-r--r--btrfs-show-super.c2
-rw-r--r--btrfs-vol.c2
-rw-r--r--btrfsck.c28
-rw-r--r--btrfsctl.c7
-rw-r--r--cmds-device.c12
-rw-r--r--cmds-filesystem.c14
-rw-r--r--cmds-inspect.c20
-rw-r--r--cmds-qgroup.c3
-rw-r--r--cmds-receive.c8
-rw-r--r--cmds-scrub.c14
-rw-r--r--cmds-send.c6
-rw-r--r--cmds-subvolume.c19
-rw-r--r--ctree.c8
-rw-r--r--ctree.h2
-rw-r--r--disk-io.c27
-rw-r--r--disk-io.h4
-rw-r--r--extent_io.c8
-rw-r--r--find-root.c27
-rw-r--r--kerncompat.h10
-rw-r--r--mkfs.c47
-rw-r--r--print-tree.c1
-rw-r--r--restore.c10
-rw-r--r--utils.c37
-rw-r--r--utils.h5
-rw-r--r--volumes.c4
26 files changed, 181 insertions, 152 deletions
diff --git a/btrfs-image.c b/btrfs-image.c
index 7dc131db..a54e6c9d 100644
--- a/btrfs-image.c
+++ b/btrfs-image.c
@@ -660,7 +660,7 @@ out:
pthread_exit(NULL);
}
-static int mdresotre_init(struct mdrestore_struct *mdres,
+static int mdrestore_init(struct mdrestore_struct *mdres,
FILE *in, FILE *out, int num_threads)
{
int i, ret = 0;
@@ -688,7 +688,7 @@ static int mdresotre_init(struct mdrestore_struct *mdres,
return ret;
}
-static void mdresotre_destroy(struct mdrestore_struct *mdres)
+static void mdrestore_destroy(struct mdrestore_struct *mdres)
{
int i;
pthread_mutex_lock(&mdres->mutex);
@@ -785,7 +785,7 @@ static int restore_metadump(const char *input, FILE *out, int num_threads)
cluster = malloc(BLOCK_SIZE);
BUG_ON(!cluster);
- ret = mdresotre_init(&mdrestore, in, out, num_threads);
+ ret = mdrestore_init(&mdrestore, in, out, num_threads);
BUG_ON(ret);
while (1) {
@@ -805,7 +805,7 @@ static int restore_metadump(const char *input, FILE *out, int num_threads)
wait_for_worker(&mdrestore);
}
- mdresotre_destroy(&mdrestore);
+ mdrestore_destroy(&mdrestore);
free(cluster);
if (in != stdin)
fclose(in);
diff --git a/btrfs-show-super.c b/btrfs-show-super.c
index 45eb1024..3614c527 100644
--- a/btrfs-show-super.c
+++ b/btrfs-show-super.c
@@ -187,7 +187,7 @@ static void dump_superblock(struct btrfs_super_block *sb)
s = (char *) &sb->magic;
for (i = 0; i < 8; i++)
putchar(isprint(s[i]) ? s[i] : '.');
- if (!memcmp(BTRFS_MAGIC, &sb->magic, 8))
+ if (sb->magic == cpu_to_le64(BTRFS_MAGIC))
printf(" [match]\n");
else
printf(" [DON'T MATCH]\n");
diff --git a/btrfs-vol.c b/btrfs-vol.c
index ad824bd8..3cc1c327 100644
--- a/btrfs-vol.c
+++ b/btrfs-vol.c
@@ -159,7 +159,7 @@ int main(int ac, char **av)
}
fd = dirfd(dirstream);
if (device)
- strcpy(args.name, device);
+ strncpy_null(args.name, device);
else
args.name[0] = '\0';
diff --git a/btrfsck.c b/btrfsck.c
index dd0f18bf..a7b47911 100644
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -1970,8 +1970,10 @@ static int check_owner_ref(struct btrfs_root *root,
struct btrfs_root *ref_root;
struct btrfs_key key;
struct btrfs_path path;
+ struct extent_buffer *parent;
int level;
int found = 0;
+ int ret;
list_for_each_entry(node, &rec->backrefs, list) {
if (node->is_data)
@@ -2002,10 +2004,13 @@ static int check_owner_ref(struct btrfs_root *root,
btrfs_init_path(&path);
path.lowest_level = level + 1;
- btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0);
+ ret = btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0);
+ if (ret < 0)
+ return 0;
- if (buf->start == btrfs_node_blockptr(path.nodes[level + 1],
- path.slots[level + 1]))
+ parent = path.nodes[level + 1];
+ if (parent && buf->start == btrfs_node_blockptr(parent,
+ path.slots[level + 1]))
found = 1;
btrfs_release_path(ref_root, &path);
@@ -2793,12 +2798,9 @@ out:
}
static int add_root_to_pending(struct extent_buffer *buf,
- struct block_info *bits,
- int bits_nr,
struct cache_tree *extent_cache,
struct cache_tree *pending,
struct cache_tree *seen,
- struct cache_tree *reada,
struct cache_tree *nodes,
struct btrfs_key *root_key)
{
@@ -3460,12 +3462,12 @@ static int check_extents(struct btrfs_trans_handle *trans,
exit(1);
}
- add_root_to_pending(root->fs_info->tree_root->node, bits, bits_nr,
- &extent_cache, &pending, &seen, &reada, &nodes,
+ add_root_to_pending(root->fs_info->tree_root->node,
+ &extent_cache, &pending, &seen, &nodes,
&root->fs_info->tree_root->root_key);
- add_root_to_pending(root->fs_info->chunk_root->node, bits, bits_nr,
- &extent_cache, &pending, &seen, &reada, &nodes,
+ add_root_to_pending(root->fs_info->chunk_root->node,
+ &extent_cache, &pending, &seen, &nodes,
&root->fs_info->chunk_root->root_key);
btrfs_init_path(&path);
@@ -3496,9 +3498,8 @@ static int check_extents(struct btrfs_trans_handle *trans,
btrfs_root_bytenr(&ri),
btrfs_level_size(root,
btrfs_root_level(&ri)), 0);
- add_root_to_pending(buf, bits, bits_nr, &extent_cache,
- &pending, &seen, &reada, &nodes,
- &found_key);
+ add_root_to_pending(buf, &extent_cache, &pending,
+ &seen, &nodes, &found_key);
free_extent_buffer(buf);
}
path.slots[0]++;
@@ -3519,6 +3520,7 @@ static int check_extents(struct btrfs_trans_handle *trans,
root->fs_info->corrupt_blocks = NULL;
}
+ free(bits);
return ret;
}
diff --git a/btrfsctl.c b/btrfsctl.c
index 049a5f35..8fd8cc32 100644
--- a/btrfsctl.c
+++ b/btrfsctl.c
@@ -242,10 +242,9 @@ int main(int ac, char **av)
fd = btrfsctl_open_file_or_dir(fname);
}
- if (name) {
- strncpy(args.name, name, BTRFS_PATH_NAME_MAX + 1);
- args.name[BTRFS_PATH_NAME_MAX] = 0;
- } else
+ if (name)
+ strncpy_null(args.name, name);
+ else
args.name[0] = '\0';
if (command == BTRFS_IOC_SNAP_CREATE) {
diff --git a/cmds-device.c b/cmds-device.c
index d4938f4e..198ad689 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -87,9 +87,8 @@ static int cmd_add_dev(int argc, char **argv)
}
devfd = open(argv[i], O_RDWR);
- if (!devfd) {
+ if (devfd < 0) {
fprintf(stderr, "ERROR: Unable to open device '%s'\n", argv[i]);
- close(devfd);
ret++;
continue;
}
@@ -117,8 +116,7 @@ static int cmd_add_dev(int argc, char **argv)
}
close(devfd);
- strncpy(ioctl_args.name, argv[i], BTRFS_PATH_NAME_MAX);
- ioctl_args.name[BTRFS_PATH_NAME_MAX-1] = 0;
+ strncpy_null(ioctl_args.name, argv[i]);
res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
e = errno;
if(res<0){
@@ -162,8 +160,7 @@ static int cmd_rm_dev(int argc, char **argv)
struct btrfs_ioctl_vol_args arg;
int res;
- strncpy(arg.name, argv[i], BTRFS_PATH_NAME_MAX);
- arg.name[BTRFS_PATH_NAME_MAX-1] = 0;
+ strncpy_null(arg.name, argv[i]);
res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
e = errno;
if(res<0){
@@ -228,8 +225,7 @@ static int cmd_scan_dev(int argc, char **argv)
printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]);
- strncpy(args.name, argv[i], BTRFS_PATH_NAME_MAX);
- args.name[BTRFS_PATH_NAME_MAX-1] = 0;
+ strncpy_null(args.name, argv[i]);
/*
* FIXME: which are the error code returned by this ioctl ?
* it seems that is impossible to understand if there no is
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 5332f801..bdbd2eed 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -470,11 +470,6 @@ static int cmd_resize(int argc, char **argv)
amount = argv[1];
path = argv[2];
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
len = strlen(amount);
if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
fprintf(stderr, "ERROR: size value too long ('%s)\n",
@@ -482,9 +477,14 @@ static int cmd_resize(int argc, char **argv)
return 14;
}
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
printf("Resize '%s' of '%s'\n", path, amount);
- strncpy(args.name, amount, BTRFS_PATH_NAME_MAX);
- args.name[BTRFS_PATH_NAME_MAX-1] = 0;
+ strncpy_null(args.name, amount);
res = ioctl(fd, BTRFS_IOC_RESIZE, &args);
e = errno;
close(fd);
diff --git a/cmds-inspect.c b/cmds-inspect.c
index f10bf55e..ff6d00fe 100644
--- a/cmds-inspect.c
+++ b/cmds-inspect.c
@@ -44,6 +44,7 @@ static int __ino_to_path_fd(u64 inum, int fd, int verbose, const char *prepend)
if (!fspath)
return 1;
+ memset(fspath, 0, sizeof(*fspath));
ipa.inum = inum;
ipa.size = 4096;
ipa.fspath = (uintptr_t)fspath;
@@ -85,6 +86,7 @@ static int cmd_inode_resolve(int argc, char **argv)
{
int fd;
int verbose = 0;
+ int ret;
optind = 1;
while (1) {
@@ -110,8 +112,11 @@ static int cmd_inode_resolve(int argc, char **argv)
return 12;
}
- return __ino_to_path_fd(atoll(argv[optind]), fd, verbose,
- argv[optind+1]);
+ ret = __ino_to_path_fd(atoll(argv[optind]), fd, verbose,
+ argv[optind+1]);
+ close(fd);
+ return ret;
+
}
static const char * const cmd_logical_resolve_usage[] = {
@@ -168,6 +173,7 @@ static int cmd_logical_resolve(int argc, char **argv)
if (!inodes)
return 1;
+ memset(inodes, 0, sizeof(*inodes));
loi.logical = atoll(argv[optind]);
loi.size = size;
loi.inodes = (uintptr_t)inodes;
@@ -208,8 +214,10 @@ static int cmd_logical_resolve(int argc, char **argv)
if (getpath) {
name = btrfs_list_path_for_root(fd, root);
- if (IS_ERR(name))
- return PTR_ERR(name);
+ if (IS_ERR(name)) {
+ ret = PTR_ERR(name);
+ goto out;
+ }
if (!name) {
path_ptr[-1] = '\0';
path_fd = fd;
@@ -227,6 +235,8 @@ static int cmd_logical_resolve(int argc, char **argv)
}
}
__ino_to_path_fd(inum, path_fd, verbose, full_path);
+ if (path_fd != fd)
+ close(path_fd);
} else {
printf("inode %llu offset %llu root %llu\n", inum,
offset, root);
@@ -234,6 +244,8 @@ static int cmd_logical_resolve(int argc, char **argv)
}
out:
+ if (fd >= 0)
+ close(fd);
free(inodes);
return ret;
}
diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 085881f3..26f0ab09 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -315,13 +315,12 @@ static int cmd_qgroup_show(int argc, char **argv)
}
ret = list_qgroups(fd);
+ close(fd);
if (ret < 0) {
fprintf(stderr, "ERROR: can't list qgroups\n");
return 30;
}
- close(fd);
-
return ret;
}
diff --git a/cmds-receive.c b/cmds-receive.c
index 973687f3..6688d0c8 100644
--- a/cmds-receive.c
+++ b/cmds-receive.c
@@ -43,6 +43,7 @@
#include "ctree.h"
#include "ioctl.h"
#include "commands.h"
+#include "utils.h"
#include "list.h"
#include "send.h"
@@ -71,7 +72,6 @@ static int finish_subvol(struct btrfs_receive *r)
{
int ret;
int subvol_fd = -1;
- int info_fd = -1;
struct btrfs_ioctl_received_subvol_args rs_args;
char uuid_str[128];
u64 flags;
@@ -132,8 +132,6 @@ static int finish_subvol(struct btrfs_receive *r)
out:
if (subvol_fd != -1)
close(subvol_fd);
- if (info_fd != -1)
- close(info_fd);
return ret;
}
@@ -168,7 +166,7 @@ static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
}
memset(&args_v1, 0, sizeof(args_v1));
- strcpy(args_v1.name, path);
+ strncpy_null(args_v1.name, path);
ret = ioctl(r->mnt_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
if (ret < 0) {
ret = -errno;
@@ -216,7 +214,7 @@ static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
}
memset(&args_v2, 0, sizeof(args_v2));
- strcpy(args_v2.name, path);
+ strncpy_null(args_v2.name, path);
r->parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
parent_ctransid, NULL, subvol_search_by_received_uuid);
diff --git a/cmds-scrub.c b/cmds-scrub.c
index efdfdb4f..b984e969 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -754,7 +754,7 @@ static int scrub_write_progress(pthread_mutex_t *m, const char *fsid,
{
int ret;
int err;
- int fd = 0;
+ int fd = -1;
int old;
ret = pthread_mutex_lock(m);
@@ -782,7 +782,7 @@ static int scrub_write_progress(pthread_mutex_t *m, const char *fsid,
goto out;
out:
- if (fd > 0) {
+ if (fd >= 0) {
ret = close(fd);
if (ret)
err = -errno;
@@ -1192,6 +1192,7 @@ static int scrub_start(int argc, char **argv, int resume)
/* ... yes, so scrub must be running. error out */
fprintf(stderr, "ERROR: scrub already running\n");
close(prg_fd);
+ prg_fd = -1;
goto out;
}
/*
@@ -1456,14 +1457,14 @@ static int cmd_scrub_cancel(int argc, char **argv)
again:
ret = ioctl(fdmnt, BTRFS_IOC_SCRUB_CANCEL, NULL);
err = errno;
- close(fdmnt);
if (ret && err == EINVAL) {
- /* path is no mounted btrfs. try if it's a device */
+ /* path is not a btrfs mount point. See if it's a device. */
ret = check_mounted_where(fdmnt, path, mp, sizeof(mp),
&fs_devices_mnt);
- close(fdmnt);
if (ret) {
+ /* It is a device; open the mountpoint. */
+ close(fdmnt);
fdmnt = open_file_or_dir(mp);
if (fdmnt >= 0) {
path = mp;
@@ -1472,6 +1473,8 @@ again:
}
}
+ close(fdmnt);
+
if (ret) {
fprintf(stderr, "ERROR: scrub cancel failed on %s: %s\n", path,
err == ENOTCONN ? "not running" : strerror(errno));
@@ -1584,6 +1587,7 @@ static int cmd_scrub_status(int argc, char **argv)
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
ret = connect(fdres, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
+ close(fdres);
fdres = scrub_open_file_r(SCRUB_DATA_FILE, fsid);
if (fdres < 0 && fdres != -ENOENT) {
fprintf(stderr, "WARNING: failed to open status file: "
diff --git a/cmds-send.c b/cmds-send.c
index 69e9bcea..b2a340e0 100644
--- a/cmds-send.c
+++ b/cmds-send.c
@@ -245,7 +245,7 @@ static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root_id)
struct subvol_info *si;
void *t_err = NULL;
int subvol_fd = -1;
- int pipefd[2];
+ int pipefd[2] = {-1, -1};
si = subvol_uuid_search(&send->sus, root_id, NULL, 0, NULL,
subvol_search_by_root_id);
@@ -327,9 +327,9 @@ static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root_id)
out:
if (subvol_fd != -1)
close(subvol_fd);
- if (pipefd[0])
+ if (pipefd[0] != -1)
close(pipefd[0]);
- if (pipefd[1])
+ if (pipefd[1] != -1)
close(pipefd[1]);
return ret;
}
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index 63c5990f..ea128fce 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -32,6 +32,7 @@
#include "ctree.h"
#include "commands.h"
+#include "utils.h"
#include "btrfs-list.h"
#include "utils.h"
@@ -138,8 +139,7 @@ static int cmd_subvol_create(int argc, char **argv)
struct btrfs_ioctl_vol_args_v2 args;
memset(&args, 0, sizeof(args));
- strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
- args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
+ strncpy_null(args.name, newname);
args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
args.size = qgroup_inherit_size(inherit);
args.qgroup_inherit = inherit;
@@ -149,8 +149,7 @@ static int cmd_subvol_create(int argc, char **argv)
struct btrfs_ioctl_vol_args args;
memset(&args, 0, sizeof(args));
- strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
- args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
+ strncpy_null(args.name, newname);
res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
}
@@ -158,13 +157,13 @@ static int cmd_subvol_create(int argc, char **argv)
e = errno;
close(fddst);
+ free(inherit);
if(res < 0 ){
fprintf( stderr, "ERROR: cannot create subvolume - %s\n",
strerror(e));
return 11;
}
- free(inherit);
return 0;
}
@@ -244,15 +243,13 @@ again:
fd = open_file_or_dir(dname);
if (fd < 0) {
- close(fd);
fprintf(stderr, "ERROR: can't access to '%s'\n", dname);
ret = 12;
goto out;
}
printf("Delete subvolume '%s/%s'\n", dname, vname);
- strncpy(args.name, vname, BTRFS_PATH_NAME_MAX);
- args.name[BTRFS_PATH_NAME_MAX-1] = 0;
+ strncpy_null(args.name, vname);
res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
e = errno;
@@ -598,20 +595,19 @@ static int cmd_snapshot(int argc, char **argv)
args.size = qgroup_inherit_size(inherit);
args.qgroup_inherit = inherit;
}
- strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
- args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
+ strncpy_null(args.name, newname);
res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
e = errno;
close(fd);
close(fddst);
+ free(inherit);
if(res < 0 ){
fprintf( stderr, "ERROR: cannot snapshot '%s' - %s\n",
subvol, strerror(e));
return 11;
}
- free(inherit);
return 0;
}
@@ -765,6 +761,7 @@ static int cmd_find_new(int argc, char **argv)
return 12;
}
ret = btrfs_list_find_updated_files(fd, 0, last_gen);
+ close(fd);
if (ret)
return 19;
return 0;
diff --git a/ctree.c b/ctree.c
index 2d86b1e7..1778a51b 100644
--- a/ctree.c
+++ b/ctree.c
@@ -1960,7 +1960,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_item_offset_nr(right, push_items - 1),
push_space);
old_left_nritems = btrfs_header_nritems(left);
- BUG_ON(old_left_nritems < 0);
+ BUG_ON(old_left_nritems == 0);
old_left_item_size = btrfs_item_offset_nr(left, old_left_nritems - 1);
for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
@@ -2872,9 +2872,6 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
}
slot--;
- if (next)
- free_extent_buffer(next);
-
next = read_node_slot(root, c, slot);
break;
}
@@ -2920,9 +2917,6 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
continue;
}
- if (next)
- free_extent_buffer(next);
-
if (path->reada)
reada_for_search(root, path, level, slot, 0);
diff --git a/ctree.h b/ctree.h
index 9bdcf6b6..12f8fe30 100644
--- a/ctree.h
+++ b/ctree.h
@@ -28,7 +28,7 @@
struct btrfs_root;
struct btrfs_trans_handle;
-#define BTRFS_MAGIC "_BHRfS_M"
+#define BTRFS_MAGIC 0x4D5F53665248425F /* ascii _BHRfS_M, no null */
#define BTRFS_MAX_LEVEL 8
diff --git a/disk-io.c b/disk-io.c
index a7d5c583..27befca4 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -459,7 +459,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
return 0;
}
-static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
+int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
u32 stripesize, struct btrfs_root *root,
struct btrfs_fs_info *fs_info, u64 objectid)
{
@@ -517,14 +517,17 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
struct btrfs_root *root;
struct list_head *next;
struct extent_buffer *eb;
+ int ret;
if (fs_info->readonly)
return 0;
eb = fs_info->tree_root->node;
extent_buffer_get(eb);
- btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb);
+ ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb);
free_extent_buffer(eb);
+ if (ret)
+ return ret;
while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
@@ -1107,8 +1110,7 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
return -1;
if (btrfs_super_bytenr(&buf) != sb_bytenr ||
- strncmp((char *)(&buf.magic), BTRFS_MAGIC,
- sizeof(buf.magic)))
+ buf.magic != cpu_to_le64(BTRFS_MAGIC))
return -1;
memcpy(sb, &buf, sizeof(*sb));
@@ -1126,8 +1128,7 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
/* if magic is NULL, the device was removed */
if (buf.magic == 0 && i == 0)
return -1;
- if (strncmp((char *)(&buf.magic), BTRFS_MAGIC,
- sizeof(buf.magic)))
+ if (buf.magic != cpu_to_le64(BTRFS_MAGIC))
continue;
if (!fsid_is_initialized) {
@@ -1157,6 +1158,10 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
u64 bytenr;
u32 crc;
int i, ret;
+ void *buf;
+
+ buf = calloc(1, BTRFS_SUPER_INFO_SIZE);
+ BUG_ON(!buf);
if (root->fs_info->super_bytenr != BTRFS_SUPER_INFO_OFFSET) {
btrfs_set_super_bytenr(sb, root->fs_info->super_bytenr);
@@ -1165,10 +1170,11 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
btrfs_csum_final(crc, (char *)&sb->csum[0]);
- ret = pwrite64(device->fd, sb, BTRFS_SUPER_INFO_SIZE,
+ memcpy(buf, sb, sizeof(*sb));
+ ret = pwrite64(device->fd, buf, BTRFS_SUPER_INFO_SIZE,
root->fs_info->super_bytenr);
BUG_ON(ret != BTRFS_SUPER_INFO_SIZE);
- return 0;
+ goto out;
}
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
@@ -1183,9 +1189,12 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
btrfs_csum_final(crc, (char *)&sb->csum[0]);
- ret = pwrite64(device->fd, sb, BTRFS_SUPER_INFO_SIZE, bytenr);
+ memcpy(buf, sb, sizeof(*sb));
+ ret = pwrite64(device->fd, buf, BTRFS_SUPER_INFO_SIZE, bytenr);
BUG_ON(ret != BTRFS_SUPER_INFO_SIZE);
}
+out:
+ free(buf);
return 0;
}
diff --git a/disk-io.h b/disk-io.h
index 53ef0238..ff879581 100644
--- a/disk-io.h
+++ b/disk-io.h
@@ -41,6 +41,10 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
u64 parent_transid);
struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
u64 bytenr, u32 blocksize);
+
+int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
+ u32 stripesize, struct btrfs_root *root,
+ struct btrfs_fs_info *fs_info, u64 objectid);
int clean_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf);
struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes);
diff --git a/extent_io.c b/extent_io.c
index 45fa6bf6..987452e1 100644
--- a/extent_io.c
+++ b/extent_io.c
@@ -300,9 +300,11 @@ int set_extent_bits(struct extent_io_tree *tree, u64 start,
u64 last_start;
u64 last_end;
again:
- prealloc = alloc_extent_state();
- if (!prealloc)
- return -ENOMEM;
+ if (!prealloc) {
+ prealloc = alloc_extent_state();
+ if (!prealloc)
+ return -ENOMEM;
+ }
/*
* this search will find the extents that end after
diff --git a/find-root.c b/find-root.c
index 3d713235..20ff9721 100644
--- a/find-root.c
+++ b/find-root.c
@@ -65,32 +65,6 @@ int csum_block(void *buf, u32 len)
return ret;
}
-static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
- u32 stripesize, struct btrfs_root *root,
- struct btrfs_fs_info *fs_info, u64 objectid)
-{
- root->node = NULL;
- root->commit_root = NULL;
- root->sectorsize = sectorsize;
- root->nodesize = nodesize;
- root->leafsize = leafsize;
- root->stripesize = stripesize;
- root->ref_cows = 0;
- root->track_dirty = 0;
-
- root->fs_info = fs_info;
- root->objectid = objectid;
- root->last_trans = 0;
- root->highest_inode = 0;
- root->last_inode_alloc = 0;
-
- INIT_LIST_HEAD(&root->dirty_list);
- memset(&root->root_key, 0, sizeof(root->root_key));
- memset(&root->root_item, 0, sizeof(root->root_item));
- root->root_key.objectid = objectid;
- return 0;
-}
-
static int close_all_devices(struct btrfs_fs_info *fs_info)
{
struct list_head *list;
@@ -386,6 +360,7 @@ static int find_root(struct btrfs_root *root)
if (!(type & BTRFS_BLOCK_GROUP_METADATA)) {
offset += map_length;
+ kfree(multi);
continue;
}
diff --git a/kerncompat.h b/kerncompat.h
index 0ab2baf9..9c116b4f 100644
--- a/kerncompat.h
+++ b/kerncompat.h
@@ -207,6 +207,16 @@ static inline long IS_ERR(const void *ptr)
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
+/*
* printk
*/
#define printk(fmt, args...) fprintf(stderr, fmt, ##args)
diff --git a/mkfs.c b/mkfs.c
index 9dd10d68..2d3c2af8 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -40,6 +40,8 @@
#include <ctype.h>
#include <attr/xattr.h>
#include <blkid/blkid.h>
+#include <ftw.h>
+#include "kerncompat.h"
#include "ctree.h"
#include "disk-io.h"
#include "volumes.h"
@@ -794,7 +796,7 @@ static int add_file_items(struct btrfs_trans_handle *trans,
fd = open(path_name, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "%s open failed\n", path_name);
- goto end;
+ return ret;
}
blocks = st->st_size / sectorsize;
@@ -1111,16 +1113,30 @@ fail:
return -1;
}
+/*
+ * This ignores symlinks with unreadable targets and subdirs that can't
+ * be read. It's a best-effort to give a rough estimate of the size of
+ * a subdir. It doesn't guarantee that prepopulating btrfs from this
+ * tree won't still run out of space.
+ *
+ * The rounding up to 4096 is questionable. Previous code used du -B 4096.
+ */
+static u64 global_total_size;
+static int ftw_add_entry_size(const char *fpath, const struct stat *st,
+ int type)
+{
+ if (type == FTW_F || type == FTW_D)
+ global_total_size += round_up(st->st_size, 4096);
+
+ return 0;
+}
+
static u64 size_sourcedir(char *dir_name, u64 sectorsize,
u64 *num_of_meta_chunks_ret, u64 *size_of_data_ret)
{
u64 dir_size = 0;
u64 total_size = 0;
int ret;
- char command[1024];
- char path[512];
- char *file_name = "temp_file";
- FILE *file;
u64 default_chunk_size = 8 * 1024 * 1024; /* 8MB */
u64 allocated_meta_size = 8 * 1024 * 1024; /* 8MB */
u64 allocated_total_size = 20 * 1024 * 1024; /* 20MB */
@@ -1128,23 +1144,14 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize,
u64 num_of_allocated_meta_chunks =
allocated_meta_size / default_chunk_size;
- ret = sprintf(command, "du -B 4096 -s ");
+ global_total_size = 0;
+ ret = ftw(dir_name, ftw_add_entry_size, 10);
+ dir_size = global_total_size;
if (ret < 0) {
- fprintf(stderr, "error executing sprintf for du command\n");
- return -1;
+ fprintf(stderr, "ftw subdir walk of '%s' failed: %s\n",
+ dir_name, strerror(errno));
+ exit(1);
}
- strcat(command, dir_name);
- strcat(command, " > ");
- strcat(command, file_name);
- ret = system(command);
-
- file = fopen(file_name, "r");
- ret = fscanf(file, "%lld %s\n", &dir_size, path);
- fclose(file);
- remove(file_name);
-
- dir_size *= sectorsize;
- *size_of_data_ret = dir_size;
num_of_meta_chunks = (dir_size / 2) / default_chunk_size;
if (((dir_size / 2) % default_chunk_size) != 0)
diff --git a/print-tree.c b/print-tree.c
index 5739e19b..c9e891bc 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -569,6 +569,7 @@ static void print_objectid(u64 objectid, u8 type)
break;
case BTRFS_FREE_INO_OBJECTID:
printf("FREE_INO");
+ break;
case BTRFS_QUOTA_TREE_OBJECTID:
printf("QUOTA_TREE");
break;
diff --git a/restore.c b/restore.c
index cd85092d..5cdb8443 100644
--- a/restore.c
+++ b/restore.c
@@ -102,9 +102,6 @@ int next_leaf(struct btrfs_root *root, struct btrfs_path *path)
continue;
}
- if (next)
- free_extent_buffer(next);
-
if (path->reada)
reada_for_search(root, path, level, slot, 0);
@@ -173,7 +170,7 @@ static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos)
done = pwrite(fd, outbuf, ram_size, pos);
free(outbuf);
- if (done < len) {
+ if (done < ram_size) {
fprintf(stderr, "Short compressed inline write, wanted %d, "
"did %zd: %d\n", ram_size, done, errno);
return -1;
@@ -624,6 +621,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
PTR_ERR(search_root));
if (ignore_errors)
goto next;
+ btrfs_free_path(path);
return PTR_ERR(search_root);
}
@@ -713,7 +711,7 @@ static int find_first_dir(struct btrfs_root *root, u64 *objectid)
path = btrfs_alloc_path();
if (!path) {
fprintf(stderr, "Ran out of memory\n");
- goto out;
+ return ret;
}
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
@@ -831,7 +829,7 @@ int main(int argc, char **argv)
return ret;
} else if (ret) {
fprintf(stderr, "%s is currently mounted. Aborting.\n", argv[optind]);
- return -EBUSY;
+ return 1;
}
root = open_fs(argv[optind], tree_location, super_mirror);
diff --git a/utils.c b/utils.c
index d92f3178..f9ee8121 100644
--- a/utils.c
+++ b/utils.c
@@ -112,7 +112,7 @@ int make_btrfs(int fd, const char *device, const char *label,
btrfs_set_super_bytenr(&super, blocks[0]);
btrfs_set_super_num_devices(&super, 1);
- strncpy((char *)&super.magic, BTRFS_MAGIC, sizeof(super.magic));
+ super.magic = cpu_to_le64(BTRFS_MAGIC);
btrfs_set_super_generation(&super, 1);
btrfs_set_super_root(&super, blocks[1]);
btrfs_set_super_chunk_root(&super, blocks[3]);
@@ -922,7 +922,7 @@ int get_mountpt(char *dev, char *mntpt, size_t size)
struct pending_dir {
struct list_head list;
- char name[256];
+ char name[PATH_MAX];
};
void btrfs_register_one_device(char *fname)
@@ -958,7 +958,6 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl)
int ret;
int fd;
int dirname_len;
- int pathlen;
char *fullpath;
struct list_head pending_list;
struct btrfs_fs_devices *tmp_devices;
@@ -973,8 +972,7 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl)
again:
dirname_len = strlen(pending->name);
- pathlen = 1024;
- fullpath = malloc(pathlen);
+ fullpath = malloc(PATH_MAX);
dirname = pending->name;
if (!fullpath) {
@@ -993,11 +991,11 @@ again:
break;
if (dirent->d_name[0] == '.')
continue;
- if (dirname_len + strlen(dirent->d_name) + 2 > pathlen) {
+ if (dirname_len + strlen(dirent->d_name) + 2 > PATH_MAX) {
ret = -EFAULT;
goto fail;
}
- snprintf(fullpath, pathlen, "%s/%s", dirname, dirent->d_name);
+ snprintf(fullpath, PATH_MAX, "%s/%s", dirname, dirent->d_name);
ret = lstat(fullpath, &st);
if (ret < 0) {
fprintf(stderr, "failed to stat %s\n", fullpath);
@@ -1085,8 +1083,7 @@ int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
ret = 0;
disk_super = (struct btrfs_super_block *)buf;
- if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
- sizeof(disk_super->magic)))
+ if (disk_super->magic != cpu_to_le64(BTRFS_MAGIC))
goto brelse;
if (!memcmp(disk_super->fsid, root->fs_info->super_copy.fsid,
@@ -1119,7 +1116,7 @@ char *pretty_sizes(u64 size)
num_divs ++;
}
- if (num_divs > ARRAY_SIZE(size_strs))
+ if (num_divs >= ARRAY_SIZE(size_strs))
return NULL;
fraction = (float)last_size / 1024;
}
@@ -1129,6 +1126,26 @@ char *pretty_sizes(u64 size)
}
/*
+ * __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;
+}
+
+/*
* Checks to make sure that the label matches our requirements.
* Returns:
0 if everything is safe and usable
diff --git a/utils.h b/utils.h
index 2d2c23d2..bbcaf6a7 100644
--- a/utils.h
+++ b/utils.h
@@ -53,4 +53,9 @@ int get_device_info(int fd, u64 devid,
struct btrfs_ioctl_dev_info_args *di_args);
int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
struct btrfs_ioctl_dev_info_args **di_ret);
+
+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))
+
#endif
diff --git a/volumes.c b/volumes.c
index de9f2642..c8fbde3d 100644
--- a/volumes.c
+++ b/volumes.c
@@ -1668,7 +1668,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
if (!sb)
return -ENOMEM;
btrfs_set_buffer_uptodate(sb);
- write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
+ write_extent_buffer(sb, super_copy, 0, sizeof(*super_copy));
array_size = btrfs_super_sys_array_size(super_copy);
/*
@@ -1767,9 +1767,9 @@ again:
goto again;
}
- btrfs_free_path(path);
ret = 0;
error:
+ btrfs_free_path(path);
return ret;
}