X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-fi-du.c;h=8a44665cee3b515dc92d881746ca665d7dea95ee;hb=4a5b95abb620175ca6eb356ff8a7d698891fa8ab;hp=09d4a656e422c7346e01dc1a1e61a0a811c3601f;hpb=d66d44eacb68112a2b935eb2d4e79edbbad8d5f0;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-fi-du.c b/cmds-fi-du.c index 09d4a65..8a44665 100644 --- a/cmds-fi-du.c +++ b/cmds-fi-du.c @@ -27,14 +27,21 @@ #include #include +#include #include +#if !defined(FIEMAP_EXTENT_SHARED) && (HAVE_OWN_FIEMAP_EXTENT_SHARED_DEFINE == 1) +#define FIEMAP_EXTENT_SHARED 0x00002000 +#endif + #include "utils.h" #include "commands.h" #include "kerncompat.h" #include "rbtree.h" #include "interval_tree_generic.h" +#include "help.h" +#include "fsfeatures.h" static int summarize = 0; static unsigned unit_mode = UNITS_RAW; @@ -79,11 +86,11 @@ static int add_shared_extent(u64 start, u64 len, struct rb_root *root) { struct shared_extent *sh; - BUG_ON(len == 0); + ASSERT(len != 0); sh = calloc(1, sizeof(*sh)); if (!sh) - return ENOMEM; + return -ENOMEM; sh->start = start; sh->last = (start + len - 1); @@ -111,7 +118,7 @@ static void cleanup_shared_extents(struct rb_root *root) } } -#define dprintf(...) +#define dbgprintf(...) /* * Find all extents which overlap 'n', calculate the space @@ -123,7 +130,7 @@ static u64 count_unique_bytes(struct rb_root *root, struct shared_extent *n) u64 wstart = n->start; u64 wlast = n->last; - dprintf("Count overlaps:"); + dbgprintf("Count overlaps:"); do { /* @@ -136,7 +143,7 @@ static u64 count_unique_bytes(struct rb_root *root, struct shared_extent *n) if (wlast < n->last) wlast = n->last; - dprintf(" (%llu, %llu)", n->start, n->last); + dbgprintf(" (%llu, %llu)", n->start, n->last); tmp = n; n = extent_tree_iter_next(n, wstart, wlast); @@ -145,7 +152,7 @@ static u64 count_unique_bytes(struct rb_root *root, struct shared_extent *n) free(tmp); } while (n); - dprintf("; wstart: %llu wlast: %llu total: %llu\n", wstart, + dbgprintf("; wstart: %llu wlast: %llu total: %llu\n", wstart, wlast, wlast - wstart + 1); return wlast - wstart + 1; @@ -153,7 +160,7 @@ static u64 count_unique_bytes(struct rb_root *root, struct shared_extent *n) /* * What we want to do here is get a count of shared bytes within the - * set of extents we have collected. Specifcally, we don't want to + * set of extents we have collected. Specifically, we don't want to * count any byte more than once, so just adding them up doesn't * work. * @@ -228,12 +235,12 @@ static int mark_inode_seen(u64 ino, u64 subvol) else if (cmp > 0) p = &(*p)->rb_right; else - BUG(); + return -EEXIST; } si = calloc(1, sizeof(*si)); if (!si) - return ENOMEM; + return -ENOMEM; si->i_ino = ino; si->i_subvol = subvol; @@ -259,7 +266,7 @@ static int inode_seen(u64 ino, u64 subvol) else if (cmp > 0) n = n->rb_right; else - return EEXIST; + return -EEXIST; } return 0; } @@ -308,7 +315,7 @@ static int du_calc_file_space(int fd, struct rb_root *shared_extents, fiemap->fm_extent_count = count; rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap); if (rc < 0) { - ret = errno; + ret = -errno; goto out; } @@ -326,6 +333,12 @@ static int du_calc_file_space(int fd, struct rb_root *shared_extents, if (flags & SKIP_FLAGS) continue; + if (ext_len == 0) { + warning("extent %llu has length 0, skipping", + (unsigned long long)fm_ext[i].fe_physical); + continue; + } + file_total += ext_len; if (flags & FIEMAP_EXTENT_SHARED) { file_shared += ext_len; @@ -389,8 +402,15 @@ static int du_walk_dir(struct du_dir_ctxt *ctxt, struct rb_root *shared_extents) dirfd(dirstream), shared_extents, &tot, &shr, 0); - if (ret) + if (ret == -ENOTTY) { + ret = 0; + continue; + } else if (ret) { + fprintf(stderr, + "failed to walk dir/file: %s :%s\n", + entry->d_name, strerror(-ret)); break; + } ctxt->bytes_total += tot; ctxt->bytes_shared += shr; @@ -413,22 +433,19 @@ static int du_add_file(const char *filename, int dirfd, u64 file_total = 0; u64 file_shared = 0; u64 dir_set_shared = 0; - u64 subvol; int fd; DIR *dirstream = NULL; ret = fstatat(dirfd, filename, &st, 0); - if (ret) { - ret = errno; - return ret; - } + if (ret) + return -errno; if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) return 0; if (len > (path_max - pathp)) { error("path too long: %s %s", path, filename); - return ENAMETOOLONG; + return -ENAMETOOLONG; } pathtmp = pathp; @@ -438,22 +455,30 @@ static int du_add_file(const char *filename, int dirfd, ret = sprintf(pathp, "/%s", filename); pathp += ret; - fd = open_file_or_dir(path, &dirstream); + fd = open_file_or_dir3(path, &dirstream, O_RDONLY); if (fd < 0) { - ret = fd; + ret = -errno; goto out; } - ret = lookup_ino_rootid(fd, &subvol); - if (ret) - goto out_close; + /* + * If st.st_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID ==2, there is no any + * related tree + */ + if (st.st_ino != BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) { + u64 subvol; + + ret = lookup_path_rootid(fd, &subvol); + if (ret) + goto out_close; - if (inode_seen(st.st_ino, subvol)) - goto out_close; + if (inode_seen(st.st_ino, subvol)) + goto out_close; - ret = mark_inode_seen(st.st_ino, subvol); - if (ret) - goto out_close; + ret = mark_inode_seen(st.st_ino, subvol); + if (ret) + goto out_close; + } if (S_ISREG(st.st_mode)) { ret = du_calc_file_space(fd, shared_extents, &file_total, @@ -497,15 +522,16 @@ static int du_add_file(const char *filename, int dirfd, if (is_dir) set_shared = dir_set_shared; - printf("%s\t%s\t%s\t%s\n", + printf("%10s %10s %10s %s\n", pretty_size_mode(file_total, unit_mode), pretty_size_mode(excl, unit_mode), pretty_size_mode(set_shared, unit_mode), path); } else { - printf("%s\t%s\t\t\t%s\n", + printf("%10s %10s %10s %s\n", pretty_size_mode(file_total, unit_mode), - pretty_size_mode(excl, unit_mode), path); + pretty_size_mode(excl, unit_mode), + "-", path); } } @@ -526,8 +552,8 @@ out: const char * const cmd_filesystem_du_usage[] = { "btrfs filesystem du [options] [..]", "Summarize disk usage of each file.", + "-s|--summarize display only a total for each argument", HELPINFO_UNITS_LONG, - "-s display only a total for each argument", NULL }; @@ -535,10 +561,10 @@ int cmd_filesystem_du(int argc, char **argv) { int ret = 0, err = 0; int i; + u32 kernel_version; unit_mode = get_unit_mode_from_arg(&argc, argv, 1); - optind = 1; while (1) { static const struct option long_options[] = { { "summarize", no_argument, NULL, 's'}, @@ -560,13 +586,22 @@ int cmd_filesystem_du(int argc, char **argv) if (check_argc_min(argc - optind, 1)) usage(cmd_filesystem_du_usage); - printf("total\texclusive\tset shared\tfilename\n"); + kernel_version = get_running_kernel_version(); + + if (kernel_version < KERNEL_VERSION(2,6,33)) { + warning( +"old kernel version detected, shared space will be reported as exclusive\n" +"due to missing support for FIEMAP_EXTENT_SHARED flag"); + } + + printf("%10s %10s %10s %s\n", "Total", "Exclusive", "Set shared", + "Filename"); for (i = optind; i < argc; i++) { ret = du_add_file(argv[i], AT_FDCWD, NULL, NULL, NULL, 1); if (ret) { error("cannot check space of '%s': %s", argv[i], - strerror(ret)); + strerror(-ret)); err = 1; }