X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=utils.c;h=80071e23fe2b7c82b87b3f95d7b8f5d3dc1412cd;hb=b114f7b537972566ff9d3d3fb2ffd87e8b441a81;hp=e7bbefbbf17c69e2c832ed5d756e6c27c5d1d841;hpb=ed4c7428b74a73f07d11bf298b327c8f3119ce72;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/utils.c b/utils.c index e7bbefb..80071e2 100644 --- a/utils.c +++ b/utils.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -179,7 +180,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, u32 sectorsize) { struct btrfs_super_block *disk_super; - struct btrfs_super_block *super = root->fs_info->super_copy; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_super_block *super = fs_info->super_copy; struct btrfs_device *device; struct btrfs_dev_item *dev_item; char *buf = NULL; @@ -214,7 +216,7 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, device->total_bytes = device_total_bytes; device->bytes_used = 0; device->total_ios = 0; - device->dev_root = root->fs_info->dev_root; + device->dev_root = fs_info->dev_root; device->name = strdup(path); if (!device->name) { ret = -ENOMEM; @@ -222,7 +224,7 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, } INIT_LIST_HEAD(&device->dev_list); - ret = btrfs_add_device(trans, root, device); + ret = btrfs_add_device(trans, fs_info, device); if (ret) goto out; @@ -248,8 +250,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, BUG_ON(ret != sectorsize); free(buf); - list_add(&device->dev_list, &root->fs_info->fs_devices->devices); - device->fs_devices = root->fs_info->fs_devices; + list_add(&device->dev_list, &fs_info->fs_devices->devices); + device->fs_devices = fs_info->fs_devices; return 0; out: @@ -378,7 +380,7 @@ int btrfs_make_root_dir(struct btrfs_trans_handle *trans, btrfs_set_stack_inode_generation(&inode_item, trans->transid); btrfs_set_stack_inode_size(&inode_item, 0); btrfs_set_stack_inode_nlink(&inode_item, 1); - btrfs_set_stack_inode_nbytes(&inode_item, root->nodesize); + btrfs_set_stack_inode_nbytes(&inode_item, root->fs_info->nodesize); btrfs_set_stack_inode_mode(&inode_item, S_IFDIR | 0755); btrfs_set_stack_timespec_sec(&inode_item.atime, now); btrfs_set_stack_timespec_nsec(&inode_item.atime, 0); @@ -445,7 +447,7 @@ int is_mount_point(const char *path) return ret; } -static int is_reg_file(const char *path) +int is_reg_file(const char *path) { struct stat statbuf; @@ -454,6 +456,21 @@ static int is_reg_file(const char *path) return S_ISREG(statbuf.st_mode); } +int is_path_exist(const char *path) +{ + struct stat statbuf; + int ret; + + ret = stat(path, &statbuf); + if (ret < 0) { + if (errno == ENOENT) + return 0; + else + return -errno; + } + return 1; +} + /* * This function checks if the given input parameter is * an uuid or a path @@ -567,9 +584,9 @@ int open_path_or_dev_mnt(const char *path, DIR **dirstream, int verbose) /* * Do the following checks before calling open_file_or_dir(): * 1: path is in a btrfs filesystem - * 2: path is a directory + * 2: path is a directory if dir_only is 1 */ -int btrfs_open_dir(const char *path, DIR **dirstream, int verbose) +int btrfs_open(const char *path, DIR **dirstream, int verbose, int dir_only) { struct statfs stfs; struct stat st; @@ -592,7 +609,7 @@ int btrfs_open_dir(const char *path, DIR **dirstream, int verbose) return -1; } - if (!S_ISDIR(st.st_mode)) { + if (dir_only && !S_ISDIR(st.st_mode)) { error_on(verbose, "not a directory: %s", path); return -3; } @@ -606,6 +623,16 @@ int btrfs_open_dir(const char *path, DIR **dirstream, int verbose) return ret; } +int btrfs_open_dir(const char *path, DIR **dirstream, int verbose) +{ + return btrfs_open(path, dirstream, verbose, 1); +} + +int btrfs_open_file_or_dir(const char *path, DIR **dirstream, int verbose) +{ + return btrfs_open(path, dirstream, verbose, 0); +} + /* checks if a device is a loop device */ static int is_loop_device (const char* device) { struct stat statbuf; @@ -1228,6 +1255,7 @@ static int set_label_unmounted(const char *dev, const char *label) return -1; trans = btrfs_start_transaction(root, 1); + BUG_ON(IS_ERR(trans)); __strncpy_null(root->fs_info->super_copy->label, label, BTRFS_LABEL_SIZE - 1); btrfs_commit_transaction(trans, root); @@ -1746,6 +1774,109 @@ out: return ret; } +int get_fsid(const char *path, u8 *fsid, int silent) +{ + int ret; + int fd; + struct btrfs_ioctl_fs_info_args args; + + fd = open(path, O_RDONLY); + if (fd < 0) { + ret = -errno; + if (!silent) + error("failed to open %s: %s", path, + strerror(-ret)); + goto out; + } + + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args); + if (ret < 0) { + ret = -errno; + goto out; + } + + memcpy(fsid, args.fsid, BTRFS_FSID_SIZE); + ret = 0; + +out: + if (fd != -1) + close(fd); + return ret; +} + +int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]) +{ + u8 hash = fsid[0]; + int slot = hash % SEEN_FSID_HASH_SIZE; + struct seen_fsid *seen = seen_fsid_hash[slot]; + + while (seen) { + if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) + return 1; + + seen = seen->next; + } + + return 0; +} + +int add_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[], + int fd, DIR *dirstream) +{ + u8 hash = fsid[0]; + int slot = hash % SEEN_FSID_HASH_SIZE; + struct seen_fsid *seen = seen_fsid_hash[slot]; + struct seen_fsid *alloc; + + if (!seen) + goto insert; + + while (1) { + if (memcmp(seen->fsid, fsid, BTRFS_FSID_SIZE) == 0) + return -EEXIST; + + if (!seen->next) + break; + + seen = seen->next; + } + +insert: + alloc = malloc(sizeof(*alloc)); + if (!alloc) + return -ENOMEM; + + alloc->next = NULL; + memcpy(alloc->fsid, fsid, BTRFS_FSID_SIZE); + alloc->fd = fd; + alloc->dirstream = dirstream; + + if (seen) + seen->next = alloc; + else + seen_fsid_hash[slot] = alloc; + + return 0; +} + +void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]) +{ + int slot; + struct seen_fsid *seen; + struct seen_fsid *next; + + for (slot = 0; slot < SEEN_FSID_HASH_SIZE; slot++) { + seen = seen_fsid_hash[slot]; + while (seen) { + next = seen->next; + close_file_or_dir(seen->fd, seen->dirstream); + free(seen); + seen = next; + } + seen_fsid_hash[slot] = NULL; + } +} + static int group_profile_devs_min(u64 flag) { switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) { @@ -2266,6 +2397,32 @@ unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode) return unit_mode; } +u64 div_factor(u64 num, int factor) +{ + if (factor == 10) + return num; + num *= factor; + num /= 10; + return num; +} +/* + * Get the length of the string converted from a u64 number. + * + * Result is equal to log10(num) + 1, but without the use of math library. + */ +int count_digits(u64 num) +{ + int ret = 0; + + if (num == 0) + return 1; + while (num > 0) { + ret++; + num /= 10; + } + return ret; +} + int string_is_numerical(const char *str) { if (!str) @@ -2279,6 +2436,15 @@ int string_is_numerical(const char *str) return 1; } +int prefixcmp(const char *str, const char *prefix) +{ + for (; ; str++, prefix++) + if (!*prefix) + return 0; + else if (*str != *prefix) + return (unsigned char)*prefix - (unsigned char)*str; +} + /* Subvolume helper functions */ /* * test if name is a correct subvolume name @@ -2397,6 +2563,59 @@ out: return ret; } +int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_id) +{ + int fd; + int ret; + DIR *dirstream = NULL; + + fd = btrfs_open_dir(mnt, &dirstream, 1); + if (fd < 0) + return -EINVAL; + + memset(get_ri, 0, sizeof(*get_ri)); + get_ri->root_id = r_id; + + if (r_id == BTRFS_FS_TREE_OBJECTID) + ret = btrfs_get_toplevel_subvol(fd, get_ri); + else + ret = btrfs_get_subvol(fd, get_ri); + + if (ret) + error("can't find rootid '%llu' on '%s': %d", r_id, mnt, ret); + + close_file_or_dir(fd, dirstream); + + return ret; +} + +int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri, u8 *uuid_arg) +{ + int fd; + int ret; + DIR *dirstream = NULL; + + fd = btrfs_open_dir(mnt, &dirstream, 1); + if (fd < 0) + return -EINVAL; + + memset(get_ri, 0, sizeof(*get_ri)); + uuid_copy(get_ri->uuid, uuid_arg); + + ret = btrfs_get_subvol(fd, get_ri); + if (ret) { + char uuid_parsed[BTRFS_UUID_UNPARSED_SIZE]; + uuid_unparse(uuid_arg, uuid_parsed); + error("can't find uuid '%s' on '%s': %d", + uuid_parsed, mnt, ret); + } + + close_file_or_dir(fd, dirstream); + + return ret; +} + +/* Set the seed manually */ void init_rand_seed(u64 seed) { int i; @@ -2446,6 +2665,7 @@ u32 rand_u32(void) return (u32)jrand48(rand_seed); } +/* Return random number in range [0, upper) */ unsigned int rand_range(unsigned int upper) { __init_seed(); @@ -2456,6 +2676,43 @@ unsigned int rand_range(unsigned int upper) return (unsigned int)(jrand48(rand_seed) % upper); } +int rand_int(void) +{ + return (int)(rand_u32()); +} + +u64 rand_u64(void) +{ + u64 ret = 0; + + ret += rand_u32(); + ret <<= 32; + ret += rand_u32(); + return ret; +} + +u16 rand_u16(void) +{ + return (u16)(rand_u32()); +} + +u8 rand_u8(void) +{ + return (u8)(rand_u32()); +} + void btrfs_config_init(void) { } + +/* Returns total size of main memory in bytes, -1UL if error. */ +unsigned long total_memory(void) +{ + struct sysinfo si; + + if (sysinfo(&si) < 0) { + error("can't determine memory size"); + return -1UL; + } + return si.totalram * si.mem_unit; /* bytes */ +}