Skip to content

Commit 9005b60

Browse files
osandovkdave
authored andcommitted
btrfs-progs: use libbtrfsutil for subvol show
Now implemented with btrfs_util_subvolume_path(), btrfs_util_subvolume_info(), and subvolume iterators. Signed-off-by: Omar Sandoval <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent afb0426 commit 9005b60

File tree

3 files changed

+98
-174
lines changed

3 files changed

+98
-174
lines changed

cmds-subvolume.c

Lines changed: 98 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -954,19 +954,20 @@ static const char * const cmd_subvol_show_usage[] = {
954954

955955
static int cmd_subvol_show(int argc, char **argv)
956956
{
957-
struct root_info get_ri;
958-
struct btrfs_list_filter_set *filter_set = NULL;
959957
char tstr[256];
960958
char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
961959
char *fullpath = NULL;
962-
char raw_prefix[] = "\t\t\t\t";
963960
int fd = -1;
964961
int ret = 1;
965962
DIR *dirstream1 = NULL;
966963
int by_rootid = 0;
967964
int by_uuid = 0;
968-
u64 rootid_arg;
965+
u64 rootid_arg = 0;
969966
u8 uuid_arg[BTRFS_UUID_SIZE];
967+
struct btrfs_util_subvolume_iterator *iter;
968+
struct btrfs_util_subvolume_info subvol;
969+
char *subvol_path = NULL;
970+
enum btrfs_util_error err;
970971

971972
while (1) {
972973
int c;
@@ -1003,96 +1004,142 @@ static int cmd_subvol_show(int argc, char **argv)
10031004
usage(cmd_subvol_show_usage);
10041005
}
10051006

1006-
memset(&get_ri, 0, sizeof(get_ri));
10071007
fullpath = realpath(argv[optind], NULL);
10081008
if (!fullpath) {
10091009
error("cannot find real path for '%s': %m", argv[optind]);
10101010
goto out;
10111011
}
10121012

1013-
if (by_rootid) {
1014-
ret = get_subvol_info_by_rootid(fullpath, &get_ri, rootid_arg);
1015-
} else if (by_uuid) {
1016-
ret = get_subvol_info_by_uuid(fullpath, &get_ri, uuid_arg);
1017-
} else {
1018-
ret = get_subvol_info(fullpath, &get_ri);
1013+
fd = open_file_or_dir(fullpath, &dirstream1);
1014+
if (fd < 0) {
1015+
error("can't access '%s'", fullpath);
1016+
goto out;
10191017
}
10201018

1021-
if (ret) {
1022-
if (ret < 0) {
1023-
error("Failed to get subvol info %s: %s",
1024-
fullpath, strerror(-ret));
1025-
} else {
1026-
error("Failed to get subvol info %s: %d",
1027-
fullpath, ret);
1019+
if (by_uuid) {
1020+
err = btrfs_util_create_subvolume_iterator_fd(fd,
1021+
BTRFS_FS_TREE_OBJECTID,
1022+
0, &iter);
1023+
if (err) {
1024+
error_btrfs_util(err);
1025+
goto out;
1026+
}
1027+
1028+
for (;;) {
1029+
err = btrfs_util_subvolume_iterator_next_info(iter,
1030+
&subvol_path,
1031+
&subvol);
1032+
if (err == BTRFS_UTIL_ERROR_STOP_ITERATION) {
1033+
uuid_unparse(uuid_arg, uuidparse);
1034+
error("can't find uuid '%s' on '%s'", uuidparse,
1035+
fullpath);
1036+
btrfs_util_destroy_subvolume_iterator(iter);
1037+
goto out;
1038+
} else if (err) {
1039+
error_btrfs_util(err);
1040+
btrfs_util_destroy_subvolume_iterator(iter);
1041+
goto out;
1042+
}
1043+
1044+
if (uuid_compare(subvol.uuid, uuid_arg) == 0)
1045+
break;
1046+
1047+
free(subvol_path);
1048+
}
1049+
btrfs_util_destroy_subvolume_iterator(iter);
1050+
} else {
1051+
/*
1052+
* If !by_rootid, rootid_arg = 0, which means find the
1053+
* subvolume ID of the fd and use that.
1054+
*/
1055+
err = btrfs_util_subvolume_info_fd(fd, rootid_arg, &subvol);
1056+
if (err) {
1057+
error_btrfs_util(err);
1058+
goto out;
10281059
}
1029-
return ret;
1060+
1061+
err = btrfs_util_subvolume_path_fd(fd, subvol.id, &subvol_path);
1062+
if (err) {
1063+
error_btrfs_util(err);
1064+
goto out;
1065+
}
1066+
10301067
}
10311068

10321069
/* print the info */
1033-
printf("%s\n", get_ri.full_path);
1034-
printf("\tName: \t\t\t%s\n", get_ri.name);
1070+
printf("%s\n", subvol.id == BTRFS_FS_TREE_OBJECTID ? "/" : subvol_path);
1071+
printf("\tName: \t\t\t%s\n",
1072+
(subvol.id == BTRFS_FS_TREE_OBJECTID ? "<FS_TREE>" :
1073+
basename(subvol_path)));
10351074

1036-
if (uuid_is_null(get_ri.uuid))
1075+
if (uuid_is_null(subvol.uuid))
10371076
strcpy(uuidparse, "-");
10381077
else
1039-
uuid_unparse(get_ri.uuid, uuidparse);
1078+
uuid_unparse(subvol.uuid, uuidparse);
10401079
printf("\tUUID: \t\t\t%s\n", uuidparse);
10411080

1042-
if (uuid_is_null(get_ri.puuid))
1081+
if (uuid_is_null(subvol.parent_uuid))
10431082
strcpy(uuidparse, "-");
10441083
else
1045-
uuid_unparse(get_ri.puuid, uuidparse);
1084+
uuid_unparse(subvol.parent_uuid, uuidparse);
10461085
printf("\tParent UUID: \t\t%s\n", uuidparse);
10471086

1048-
if (uuid_is_null(get_ri.ruuid))
1087+
if (uuid_is_null(subvol.received_uuid))
10491088
strcpy(uuidparse, "-");
10501089
else
1051-
uuid_unparse(get_ri.ruuid, uuidparse);
1090+
uuid_unparse(subvol.received_uuid, uuidparse);
10521091
printf("\tReceived UUID: \t\t%s\n", uuidparse);
10531092

1054-
if (get_ri.otime) {
1093+
if (subvol.otime.tv_sec) {
10551094
struct tm tm;
10561095

1057-
localtime_r(&get_ri.otime, &tm);
1096+
localtime_r(&subvol.otime.tv_sec, &tm);
10581097
strftime(tstr, 256, "%Y-%m-%d %X %z", &tm);
10591098
} else
10601099
strcpy(tstr, "-");
10611100
printf("\tCreation time: \t\t%s\n", tstr);
10621101

1063-
printf("\tSubvolume ID: \t\t%llu\n", get_ri.root_id);
1064-
printf("\tGeneration: \t\t%llu\n", get_ri.gen);
1065-
printf("\tGen at creation: \t%llu\n", get_ri.ogen);
1066-
printf("\tParent ID: \t\t%llu\n", get_ri.ref_tree);
1067-
printf("\tTop level ID: \t\t%llu\n", get_ri.top_id);
1102+
printf("\tSubvolume ID: \t\t%" PRIu64 "\n", subvol.id);
1103+
printf("\tGeneration: \t\t%" PRIu64 "\n", subvol.generation);
1104+
printf("\tGen at creation: \t%" PRIu64 "\n", subvol.otransid);
1105+
printf("\tParent ID: \t\t%" PRIu64 "\n", subvol.parent_id);
1106+
printf("\tTop level ID: \t\t%" PRIu64 "\n", subvol.parent_id);
10681107

1069-
if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY)
1108+
if (subvol.flags & BTRFS_ROOT_SUBVOL_RDONLY)
10701109
printf("\tFlags: \t\t\treadonly\n");
10711110
else
10721111
printf("\tFlags: \t\t\t-\n");
10731112

10741113
/* print the snapshots of the given subvol if any*/
10751114
printf("\tSnapshot(s):\n");
1076-
filter_set = btrfs_list_alloc_filter_set();
1077-
btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT,
1078-
(u64)(unsigned long)get_ri.uuid);
1079-
btrfs_list_setup_print_column(BTRFS_LIST_PATH);
10801115

1081-
fd = open_file_or_dir(fullpath, &dirstream1);
1082-
if (fd < 0) {
1083-
fprintf(stderr, "ERROR: can't access '%s'\n", fullpath);
1084-
goto out;
1116+
err = btrfs_util_create_subvolume_iterator_fd(fd,
1117+
BTRFS_FS_TREE_OBJECTID, 0,
1118+
&iter);
1119+
1120+
for (;;) {
1121+
struct btrfs_util_subvolume_info subvol2;
1122+
char *path;
1123+
1124+
err = btrfs_util_subvolume_iterator_next_info(iter, &path, &subvol2);
1125+
if (err == BTRFS_UTIL_ERROR_STOP_ITERATION) {
1126+
break;
1127+
} else if (err) {
1128+
error_btrfs_util(err);
1129+
btrfs_util_destroy_subvolume_iterator(iter);
1130+
goto out;
1131+
}
1132+
1133+
if (uuid_compare(subvol2.parent_uuid, subvol.uuid) == 0)
1134+
printf("\t\t\t\t%s\n", path);
1135+
1136+
free(path);
10851137
}
1086-
btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
1087-
1, raw_prefix);
1138+
btrfs_util_destroy_subvolume_iterator(iter);
10881139

1140+
ret = 0;
10891141
out:
1090-
/* clean up */
1091-
free(get_ri.path);
1092-
free(get_ri.name);
1093-
free(get_ri.full_path);
1094-
free(filter_set);
1095-
1142+
free(subvol_path);
10961143
close_file_or_dir(fd, dirstream1);
10971144
free(fullpath);
10981145
return !!ret;

utils.c

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,124 +2495,6 @@ const char *subvol_strip_mountpoint(const char *mnt, const char *full_path)
24952495
return full_path + len;
24962496
}
24972497

2498-
/*
2499-
* Returns
2500-
* <0: Std error
2501-
* 0: All fine
2502-
* 1: Error; and error info printed to the terminal. Fixme.
2503-
* 2: If the fullpath is root tree instead of subvol tree
2504-
*/
2505-
int get_subvol_info(const char *fullpath, struct root_info *get_ri)
2506-
{
2507-
u64 sv_id;
2508-
int ret = 1;
2509-
int fd = -1;
2510-
int mntfd = -1;
2511-
char *mnt = NULL;
2512-
const char *svpath = NULL;
2513-
DIR *dirstream1 = NULL;
2514-
DIR *dirstream2 = NULL;
2515-
2516-
ret = test_issubvolume(fullpath);
2517-
if (ret < 0)
2518-
return ret;
2519-
if (!ret) {
2520-
error("not a subvolume: %s", fullpath);
2521-
return 1;
2522-
}
2523-
2524-
ret = find_mount_root(fullpath, &mnt);
2525-
if (ret < 0)
2526-
return ret;
2527-
if (ret > 0) {
2528-
error("%s doesn't belong to btrfs mount point", fullpath);
2529-
return 1;
2530-
}
2531-
ret = 1;
2532-
svpath = subvol_strip_mountpoint(mnt, fullpath);
2533-
2534-
fd = btrfs_open_dir(fullpath, &dirstream1, 1);
2535-
if (fd < 0)
2536-
goto out;
2537-
2538-
ret = btrfs_list_get_path_rootid(fd, &sv_id);
2539-
if (ret)
2540-
goto out;
2541-
2542-
mntfd = btrfs_open_dir(mnt, &dirstream2, 1);
2543-
if (mntfd < 0)
2544-
goto out;
2545-
2546-
memset(get_ri, 0, sizeof(*get_ri));
2547-
get_ri->root_id = sv_id;
2548-
2549-
if (sv_id == BTRFS_FS_TREE_OBJECTID)
2550-
ret = btrfs_get_toplevel_subvol(mntfd, get_ri);
2551-
else
2552-
ret = btrfs_get_subvol(mntfd, get_ri);
2553-
if (ret)
2554-
error("can't find '%s': %d", svpath, ret);
2555-
2556-
out:
2557-
close_file_or_dir(mntfd, dirstream2);
2558-
close_file_or_dir(fd, dirstream1);
2559-
free(mnt);
2560-
2561-
return ret;
2562-
}
2563-
2564-
int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_id)
2565-
{
2566-
int fd;
2567-
int ret;
2568-
DIR *dirstream = NULL;
2569-
2570-
fd = btrfs_open_dir(mnt, &dirstream, 1);
2571-
if (fd < 0)
2572-
return -EINVAL;
2573-
2574-
memset(get_ri, 0, sizeof(*get_ri));
2575-
get_ri->root_id = r_id;
2576-
2577-
if (r_id == BTRFS_FS_TREE_OBJECTID)
2578-
ret = btrfs_get_toplevel_subvol(fd, get_ri);
2579-
else
2580-
ret = btrfs_get_subvol(fd, get_ri);
2581-
2582-
if (ret)
2583-
error("can't find rootid '%llu' on '%s': %d", r_id, mnt, ret);
2584-
2585-
close_file_or_dir(fd, dirstream);
2586-
2587-
return ret;
2588-
}
2589-
2590-
int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri, u8 *uuid_arg)
2591-
{
2592-
int fd;
2593-
int ret;
2594-
DIR *dirstream = NULL;
2595-
2596-
fd = btrfs_open_dir(mnt, &dirstream, 1);
2597-
if (fd < 0)
2598-
return -EINVAL;
2599-
2600-
memset(get_ri, 0, sizeof(*get_ri));
2601-
uuid_copy(get_ri->uuid, uuid_arg);
2602-
2603-
ret = btrfs_get_subvol(fd, get_ri);
2604-
if (ret) {
2605-
char uuid_parsed[BTRFS_UUID_UNPARSED_SIZE];
2606-
uuid_unparse(uuid_arg, uuid_parsed);
2607-
error("can't find uuid '%s' on '%s': %d",
2608-
uuid_parsed, mnt, ret);
2609-
}
2610-
2611-
close_file_or_dir(fd, dirstream);
2612-
2613-
return ret;
2614-
}
2615-
26162498
/* Set the seed manually */
26172499
void init_rand_seed(u64 seed)
26182500
{

utils.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,6 @@ int test_issubvolume(const char *path);
153153
int test_isdir(const char *path);
154154

155155
const char *subvol_strip_mountpoint(const char *mnt, const char *full_path);
156-
int get_subvol_info(const char *fullpath, struct root_info *get_ri);
157-
int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
158-
u64 rootid_arg);
159-
int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri,
160-
u8 *uuid_arg);
161156
int find_next_key(struct btrfs_path *path, struct btrfs_key *key);
162157
const char* btrfs_group_type_str(u64 flag);
163158
const char* btrfs_group_profile_str(u64 flag);

0 commit comments

Comments
 (0)