X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-filesystem.c;h=25d3c0cfae00051336326357b6ebecc39ab31985;hb=de802a47e0d7474bd446c5eb6974a33dacca5100;hp=c66709b35449050833ee8f0fe607bc220857787a;hpb=281e476b4dd89d1e1314d3123d566c83b4253a2d;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-filesystem.c b/cmds-filesystem.c index c66709b..25d3c0c 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -30,98 +30,20 @@ #include "kerncompat.h" #include "ctree.h" -#include "ioctl.h" #include "utils.h" #include "volumes.h" #include "commands.h" #include "cmds-fi-usage.h" #include "list_sort.h" #include "disk-io.h" -#include "cmds-fi-du.h" +#include "help.h" /* * for btrfs fi show, we maintain a hash of fsids we've already printed. * This way we don't print dups if a given FS is mounted more than once. */ -#define SEEN_FSID_HASH_SIZE 256 - -struct seen_fsid { - u8 fsid[BTRFS_FSID_SIZE]; - struct seen_fsid *next; -}; - static struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = {NULL,}; -static int is_seen_fsid(u8 *fsid) -{ - 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; -} - -static int add_seen_fsid(u8 *fsid) -{ - 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); - - if (seen) - seen->next = alloc; - else - seen_fsid_hash[slot] = alloc; - - return 0; -} - -static void free_seen_fsid(void) -{ - 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; - free(seen); - seen = next; - } - seen_fsid_hash[slot] = NULL; - } -} - static const char * const filesystem_cmd_group_usage[] = { "btrfs filesystem [] []", NULL @@ -228,7 +150,7 @@ static int cmd_filesystem_df(int argc, char **argv) return !!ret; } -static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label, +static int match_search_item_kernel(u8 *fsid, char *mnt, char *label, char *search) { char uuidbuf[BTRFS_UUID_UNPARSED_SIZE]; @@ -251,7 +173,6 @@ static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label, static int uuid_search(struct btrfs_fs_devices *fs_devices, const char *search) { char uuidbuf[BTRFS_UUID_UNPARSED_SIZE]; - struct list_head *cur; struct btrfs_device *device; int search_len = strlen(search); @@ -260,8 +181,7 @@ static int uuid_search(struct btrfs_fs_devices *fs_devices, const char *search) if (!strncmp(uuidbuf, search, search_len)) return 1; - list_for_each(cur, &fs_devices->devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, &fs_devices->devices, dev_list) { if ((device->label && strcmp(device->label, search) == 0) || strcmp(device->name, search) == 0) return 1; @@ -355,7 +275,7 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices, u64 devs_found = 0; u64 total; - if (add_seen_fsid(fs_devices->fsid)) + if (add_seen_fsid(fs_devices->fsid, seen_fsid_hash, -1, NULL)) return; uuid_unparse(fs_devices->fsid, uuidbuf); @@ -402,7 +322,7 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info, struct btrfs_ioctl_dev_info_args *tmp_dev_info; int ret; - ret = add_seen_fsid(fs_info->fsid); + ret = add_seen_fsid(fs_info->fsid, seen_fsid_hash, -1, NULL); if (ret == -EEXIST) return 0; else if (ret) @@ -474,7 +394,7 @@ static int btrfs_scan_kernel(void *search, unsigned unit_mode) goto out; /* skip all fs already shown as mounted fs */ - if (is_seen_fsid(fs_info_arg.fsid)) + if (is_seen_fsid(fs_info_arg.fsid, seen_fsid_hash)) continue; ret = get_label_mounted(mnt->mnt_dir, label); @@ -509,33 +429,6 @@ out: return !found; } -static int dev_to_fsid(const char *dev, __u8 *fsid) -{ - struct btrfs_super_block *disk_super; - char buf[BTRFS_SUPER_INFO_SIZE]; - int ret; - int fd; - - fd = open(dev, O_RDONLY); - if (fd < 0) { - ret = -errno; - return ret; - } - - disk_super = (struct btrfs_super_block *)buf; - ret = btrfs_read_dev_super(fd, disk_super, - BTRFS_SUPER_INFO_OFFSET, SBREAD_DEFAULT); - if (ret) - goto out; - - memcpy(fsid, disk_super->fsid, BTRFS_FSID_SIZE); - ret = 0; - -out: - close(fd); - return ret; -} - static void free_fs_devices(struct btrfs_fs_devices *fs_devices) { struct btrfs_fs_devices *cur_seed, *next_seed; @@ -676,7 +569,7 @@ static int search_umounted_fs_uuids(struct list_head *all_uuids, } /* skip all fs already shown as mounted fs */ - if (is_seen_fsid(cur_fs->fsid)) + if (is_seen_fsid(cur_fs->fsid, seen_fsid_hash)) continue; fs_copy = calloc(1, sizeof(*fs_copy)); @@ -783,7 +676,7 @@ static int cmd_filesystem_show(int argc, char **argv) int type = 0; char mp[PATH_MAX]; char path[PATH_MAX]; - __u8 fsid[BTRFS_FSID_SIZE]; + u8 fsid[BTRFS_FSID_SIZE]; char uuid_buf[BTRFS_UUID_UNPARSED_SIZE]; unsigned unit_mode; int found = 0; @@ -908,7 +801,7 @@ devs_only: free_fs_devices(fs_devices); } out: - free_seen_fsid(); + free_seen_fsid(seen_fsid_hash); return ret; } @@ -952,6 +845,8 @@ static int parse_compress_type(char *s) return BTRFS_COMPRESS_ZLIB; else if (strcmp(optarg, "lzo") == 0) return BTRFS_COMPRESS_LZO; + else if (strcmp(optarg, "zstd") == 0) + return BTRFS_COMPRESS_ZSTD; else { error("unknown compression type %s", s); exit(1); @@ -962,30 +857,21 @@ static const char * const cmd_filesystem_defrag_usage[] = { "btrfs filesystem defragment [options] | [|...]", "Defragment a file or a directory", "", - "-v be verbose", - "-r defragment files recursively", - "-c[zlib,lzo] compress the file while defragmenting", - "-f flush data to disk immediately after defragmenting", - "-s start defragment only from byte onward", - "-l len defragment only up to len bytes", - "-t size target extent size hint (default: 32M)", + "-v be verbose", + "-r defragment files recursively", + "-c[zlib,lzo,zstd] compress the file while defragmenting", + "-f flush data to disk immediately after defragmenting", + "-s start defragment only from byte onward", + "-l len defragment only up to len bytes", + "-t size target extent size hint (default: 32M)", + "", + "Warning: most Linux kernels will break up the ref-links of COW data", + "(e.g., files copied with 'cp --reflink', snapshots) which may cause", + "considerable increase of space usage. See btrfs-filesystem(8) for", + "more information.", NULL }; -static int do_defrag(int fd, int fancy_ioctl, - struct btrfs_ioctl_defrag_range_args *range) -{ - int ret; - - if (!fancy_ioctl) - ret = ioctl(fd, BTRFS_IOC_DEFRAG, NULL); - else - ret = ioctl(fd, BTRFS_IOC_DEFRAG_RANGE, range); - - return ret; -} - -static int defrag_global_fancy_ioctl; static struct btrfs_ioctl_defrag_range_args defrag_global_range; static int defrag_global_verbose; static int defrag_global_errors; @@ -1004,12 +890,11 @@ static int defrag_callback(const char *fpath, const struct stat *sb, err = errno; goto error; } - ret = do_defrag(fd, defrag_global_fancy_ioctl, &defrag_global_range); + ret = ioctl(fd, BTRFS_IOC_DEFRAG_RANGE, &defrag_global_range); close(fd); - if (ret && errno == ENOTTY && defrag_global_fancy_ioctl) { - error("defrag range ioctl not " - "supported in this kernel, please try " - "without any options."); + if (ret && errno == ENOTTY) { + error( +"defrag range ioctl not supported in this kernel version, 2.6.33 and newer is required"); defrag_global_errors++; return ENOTTY; } @@ -1042,14 +927,14 @@ static int cmd_filesystem_defrag(int argc, char **argv) /* * Kernel has a different default (256K) that is supposed to be safe, * but it does not defragment very well. The 32M will likely lead to - * better results and is independent of the kernel default. + * better results and is independent of the kernel default. We have to + * use the v2 defrag ioctl. */ - thresh = 32 * 1024 * 1024; + thresh = SZ_32M; defrag_global_errors = 0; defrag_global_verbose = 0; defrag_global_errors = 0; - defrag_global_fancy_ioctl = 0; while(1) { int c = getopt(argc, argv, "vrc::fs:l:t:"); if (c < 0) @@ -1060,22 +945,18 @@ static int cmd_filesystem_defrag(int argc, char **argv) compress_type = BTRFS_COMPRESS_ZLIB; if (optarg) compress_type = parse_compress_type(optarg); - defrag_global_fancy_ioctl = 1; break; case 'f': flush = 1; - defrag_global_fancy_ioctl = 1; break; case 'v': defrag_global_verbose = 1; break; case 's': start = parse_size(optarg); - defrag_global_fancy_ioctl = 1; break; case 'l': len = parse_size(optarg); - defrag_global_fancy_ioctl = 1; break; case 't': thresh = parse_size(optarg); @@ -1085,7 +966,6 @@ static int cmd_filesystem_defrag(int argc, char **argv) thresh, (u32)-1); thresh = (u32)-1; } - defrag_global_fancy_ioctl = 1; break; case 'r': recursive = 1; @@ -1147,23 +1027,22 @@ static int cmd_filesystem_defrag(int argc, char **argv) if (fd < 0) { error("cannot open %s: %s", argv[i], strerror(errno)); - defrag_global_errors++; - close_file_or_dir(fd, dirstream); - continue; + ret = -errno; + goto next; } - if (fstat(fd, &st)) { + + ret = fstat(fd, &st); + if (ret) { error("failed to stat %s: %s", argv[i], strerror(errno)); - defrag_global_errors++; - close_file_or_dir(fd, dirstream); - continue; + ret = -errno; + goto next; } if (!(S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))) { error("%s is not a directory or a regular file", argv[i]); - defrag_global_errors++; - close_file_or_dir(fd, dirstream); - continue; + ret = -EINVAL; + goto next; } if (recursive && S_ISDIR(st.st_mode)) { ret = nftw(argv[i], defrag_callback, 10, @@ -1175,24 +1054,28 @@ static int cmd_filesystem_defrag(int argc, char **argv) } else { if (defrag_global_verbose) printf("%s\n", argv[i]); - ret = do_defrag(fd, defrag_global_fancy_ioctl, + ret = ioctl(fd, BTRFS_IOC_DEFRAG_RANGE, &defrag_global_range); defrag_err = errno; + if (ret && defrag_err == ENOTTY) { + error( +"defrag range ioctl not supported in this kernel version, 2.6.33 and newer is required"); + defrag_global_errors++; + close_file_or_dir(fd, dirstream); + break; + } + if (ret) { + error("defrag failed on %s: %s", argv[i], + strerror(defrag_err)); + goto next; + } } - close_file_or_dir(fd, dirstream); - if (ret && defrag_err == ENOTTY && defrag_global_fancy_ioctl) { - error("defrag range ioctl not " - "supported in this kernel, please try " - "without any options."); - defrag_global_errors++; - break; - } - if (ret) { - error("defrag failed on %s: %s", argv[i], - strerror(defrag_err)); +next: + if (ret) defrag_global_errors++; - } + close_file_or_dir(fd, dirstream); } + if (defrag_global_errors) fprintf(stderr, "total %d failures\n", defrag_global_errors);