diff options
-rw-r--r-- | btrfs-image.c | 8 | ||||
-rw-r--r-- | btrfs-show-super.c | 2 | ||||
-rw-r--r-- | btrfs-vol.c | 2 | ||||
-rw-r--r-- | btrfsck.c | 28 | ||||
-rw-r--r-- | btrfsctl.c | 7 | ||||
-rw-r--r-- | cmds-device.c | 12 | ||||
-rw-r--r-- | cmds-filesystem.c | 14 | ||||
-rw-r--r-- | cmds-inspect.c | 20 | ||||
-rw-r--r-- | cmds-qgroup.c | 3 | ||||
-rw-r--r-- | cmds-receive.c | 8 | ||||
-rw-r--r-- | cmds-scrub.c | 14 | ||||
-rw-r--r-- | cmds-send.c | 6 | ||||
-rw-r--r-- | cmds-subvolume.c | 19 | ||||
-rw-r--r-- | ctree.c | 8 | ||||
-rw-r--r-- | ctree.h | 2 | ||||
-rw-r--r-- | disk-io.c | 27 | ||||
-rw-r--r-- | disk-io.h | 4 | ||||
-rw-r--r-- | extent_io.c | 8 | ||||
-rw-r--r-- | find-root.c | 27 | ||||
-rw-r--r-- | kerncompat.h | 10 | ||||
-rw-r--r-- | mkfs.c | 47 | ||||
-rw-r--r-- | print-tree.c | 1 | ||||
-rw-r--r-- | restore.c | 10 | ||||
-rw-r--r-- | utils.c | 37 | ||||
-rw-r--r-- | utils.h | 5 | ||||
-rw-r--r-- | volumes.c | 4 |
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'; @@ -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; } @@ -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; @@ -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); @@ -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 @@ -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; } @@ -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) @@ -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; @@ -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); @@ -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 @@ -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 @@ -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; } |