diff options
author | Karel Zak | 2018-10-18 15:46:07 +0200 |
---|---|---|
committer | Karel Zak | 2018-12-07 12:33:34 +0100 |
commit | dc4662f0e755929de9cbe98b1b343b492fd620f4 (patch) | |
tree | 6947fd4b81219649cb23eff5d1eb4b12f3c86252 /misc-utils/lsblk.c | |
parent | lsblk: remember whole-disk, remove unused struct member (diff) | |
download | kernel-qcow2-util-linux-dc4662f0e755929de9cbe98b1b343b492fd620f4.tar.gz kernel-qcow2-util-linux-dc4662f0e755929de9cbe98b1b343b492fd620f4.tar.xz kernel-qcow2-util-linux-dc4662f0e755929de9cbe98b1b343b492fd620f4.zip |
lsblk: add --dedup <column>
The target use-case are systems with large number of multi-path
devices or systems with duplicate (copied) filesystems.
The feature is flexible enough to use arbitrary column (for example
WWM or UUID, ...) as de-duplication key.
For example tree with multi-path devices sd{c,d,e,f}
./lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 223.6G 0 disk
├─sda1 8:1 0 200M 0 part /boot/efi
├─sda2 8:2 0 200M 0 part /boot
├─sda3 8:3 0 130.3G 0 part
├─sda4 8:4 0 50G 0 part /
└─sda5 8:5 0 42.9G 0 part
sdb 8:16 0 74.5G 0 disk
└─sdb1 8:17 0 74.5G 0 part /home/archive
sdc 8:32 0 100M 0 disk
└─mpatha 253:0 0 100M 0 mpath
├─mpatha1 253:1 0 50M 0 part
└─mpatha2 253:2 0 49M 0 part
sdd 8:48 0 100M 0 disk
└─mpatha 253:0 0 100M 0 mpath
├─mpatha1 253:1 0 50M 0 part
└─mpatha2 253:2 0 49M 0 part
sde 8:64 0 100M 0 disk
└─mpatha 253:0 0 100M 0 mpath
├─mpatha1 253:1 0 50M 0 part
└─mpatha2 253:2 0 49M 0 part
sdf 8:80 0 100M 0 disk
└─mpatha 253:0 0 100M 0 mpath
├─mpatha1 253:1 0 50M 0 part
└─mpatha2 253:2 0 49M 0 part
De-duplicate by WWN:
./lsblk -M WWN
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 223.6G 0 disk
├─sda1 8:1 0 200M 0 part /boot/efi
├─sda2 8:2 0 200M 0 part /boot
├─sda3 8:3 0 130.3G 0 part
├─sda4 8:4 0 50G 0 part /
└─sda5 8:5 0 42.9G 0 part
sdb 8:16 0 74.5G 0 disk
└─sdb1 8:17 0 74.5G 0 part /home/archive
sdc 8:32 0 100M 0 disk
└─mpatha 253:0 0 100M 0 mpath
├─mpatha1 253:1 0 50M 0 part
└─mpatha2 253:2 0 49M 0 part
Addresses: https://github.com/karelzak/util-linux/issues/616
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/lsblk.c')
-rw-r--r-- | misc-utils/lsblk.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c index 35926a17d..95c3cdc4d 100644 --- a/misc-utils/lsblk.c +++ b/misc-utils/lsblk.c @@ -1641,6 +1641,43 @@ static int cmp_u64_cells(struct libscols_cell *a, return *adata == *bdata ? 0 : *adata >= *bdata ? 1 : -1; } +static void device_set_dedupkey( + struct lsblk_device *dev, + struct lsblk_device *parent, + int id) +{ + struct lsblk_iter itr; + struct lsblk_device *child = NULL; + + dev->dedupkey = device_get_data(dev, parent, id, NULL); + if (dev->dedupkey) + DBG(DEV, ul_debugobj(dev, "%s: de-duplication key: %s", dev->name, dev->dedupkey)); + + if (dev->npartitions == 0) + /* For partitions we often read from parental whole-disk sysfs, + * otherwise we can close */ + ul_path_close_dirfd(dev->sysfs); + + lsblk_reset_iter(&itr, LSBLK_ITER_FORWARD); + + while (lsblk_device_next_child(dev, &itr, &child) == 0) + device_set_dedupkey(child, dev, id); + + /* Let's be careful with number of open files */ + ul_path_close_dirfd(dev->sysfs); +} + +static void devtree_set_dedupkeys(struct lsblk_devtree *tr, int id) +{ + struct lsblk_iter itr; + struct lsblk_device *dev = NULL; + + lsblk_reset_iter(&itr, LSBLK_ITER_FORWARD); + + while (lsblk_devtree_next_root(tr, &itr, &dev) == 0) + device_set_dedupkey(dev, NULL, id); +} + static void __attribute__((__noreturn__)) usage(void) { FILE *out = stdout; @@ -1665,6 +1702,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -J, --json use JSON output format\n"), out); fputs(_(" -l, --list use list format output\n"), out); fputs(_(" -T, --tree use tree format output\n"), out); + fputs(_(" -M, --dedup <column> de-duplicate output by <column>\n"), out); fputs(_(" -m, --perms output info about permissions\n"), out); fputs(_(" -n, --noheadings don't print headings\n"), out); fputs(_(" -o, --output <list> output columns\n"), out); @@ -1699,7 +1737,11 @@ static void check_sysdevblock(void) int main(int argc, char *argv[]) { - struct lsblk _ls = { .sort_id = -1, .flags = LSBLK_TREE }; + struct lsblk _ls = { + .sort_id = -1, + .dedup_id = -1, + .flags = LSBLK_TREE + }; struct lsblk_devtree *tr = NULL; int c, status = EXIT_FAILURE; char *outarg = NULL; @@ -1715,6 +1757,7 @@ int main(int argc, char *argv[]) { "bytes", no_argument, NULL, 'b' }, { "nodeps", no_argument, NULL, 'd' }, { "discard", no_argument, NULL, 'D' }, + { "dedup", required_argument, NULL, 'M' }, { "zoned", no_argument, NULL, 'z' }, { "help", no_argument, NULL, 'h' }, { "json", no_argument, NULL, 'J' }, @@ -1763,7 +1806,7 @@ int main(int argc, char *argv[]) lsblk_init_debug(); while((c = getopt_long(argc, argv, - "abdDze:fhJlnmo:OpPiI:rstVSTx:", longopts, NULL)) != -1) { + "abdDze:fhJlnmM:o:OpPiI:rstVSTx:", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); @@ -1880,6 +1923,12 @@ int main(int argc, char *argv[]) case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; + case 'M': + lsblk->dedup_id = column_name_to_id(optarg, strlen(optarg)); + if (lsblk->dedup_id >= 0) + break; + errtryhelp(EXIT_FAILURE); + break; case 'x': lsblk->flags &= ~LSBLK_TREE; /* disable the default */ lsblk->sort_id = column_name_to_id(optarg, strlen(optarg)); @@ -1928,6 +1977,12 @@ int main(int argc, char *argv[]) lsblk->sort_hidden = 1; } + if (lsblk->dedup_id >= 0 && column_id_to_number(lsblk->dedup_id) < 0) { + /* the deduplication column is not between output columns -- add as hidden */ + add_column(lsblk->dedup_id); + lsblk->dedup_hidden = 1; + } + lsblk_mnt_init(); scols_init_debug(0); ul_path_init_debug(); @@ -1955,6 +2010,8 @@ int main(int argc, char *argv[]) fl &= ~SCOLS_FL_TREE; if (lsblk->sort_hidden && lsblk->sort_id == id) fl |= SCOLS_FL_HIDDEN; + if (lsblk->dedup_hidden && lsblk->dedup_id == id) + fl |= SCOLS_FL_HIDDEN; cl = scols_table_new_column(lsblk->table, ci->name, ci->whint, fl); if (!cl) { @@ -2012,6 +2069,11 @@ int main(int argc, char *argv[]) EXIT_SUCCESS; /* all success */ } + if (lsblk->dedup_id > -1) { + devtree_set_dedupkeys(tr, lsblk->dedup_id); + lsblk_devtree_deduplicate_devices(tr); + } + devtree_to_scols(tr, lsblk->table); if (lsblk->sort_col) |