From ed6acfa337ca74912079b85196cf1263f6daf1a2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 7 May 2005 17:06:27 -0400 Subject: [PATCH] Add a new option to the blkid program, -l, which will more efficiently search for a single device. Add a new function to the blkid library, blkid_probe_all_new(). Optimize blkid_find_dev_with_tag() so that extraneous device validation are skipped. (Makes a difference for system with a large number of disks). --- lib/blkid/ChangeLog | 9 +++++++++ lib/blkid/blkid.h | 1 + lib/blkid/devname.c | 52 +++++++++++++++++++++++++++++++++++++++------------- lib/blkid/tag.c | 11 ++++++++--- misc/ChangeLog | 4 ++++ misc/blkid.8.in | 30 ++++++++++++++++++++++++++++-- misc/blkid.c | 28 +++++++++++++++++++++++++--- 7 files changed, 114 insertions(+), 21 deletions(-) diff --git a/lib/blkid/ChangeLog b/lib/blkid/ChangeLog index 40c7d12..d84c903 100644 --- a/lib/blkid/ChangeLog +++ b/lib/blkid/ChangeLog @@ -1,5 +1,14 @@ 2005-05-07 Theodore Ts'o + * tag.c (blkid_find_dev_with_tag): If a device can't be found with + the specified search arguments, probe all new devices + before trying to verify existing devices, as a speed + optimization. + + * devname.c (blkid_probe_all_new): New function which only probes + devices are not known in the blkid cache. This takes + much less time than a full probe of all devices. + * cache.c, dev.c, devno.c, probe.c, probe.h: Fix gcc -Wall nits. * blkidP.h, cache.c, dev.c, read.c, tag.c: Clean up the debugging diff --git a/lib/blkid/blkid.h b/lib/blkid/blkid.h index 84be589..892b798 100644 --- a/lib/blkid/blkid.h +++ b/lib/blkid/blkid.h @@ -65,6 +65,7 @@ extern char *blkid_devno_to_devname(dev_t devno); /* devname.c */ extern int blkid_probe_all(blkid_cache cache); +extern int blkid_probe_all_new(blkid_cache cache); extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags); diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c index 87d5cbe..3b1ad89 100644 --- a/lib/blkid/devname.c +++ b/lib/blkid/devname.c @@ -79,7 +79,7 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) * Probe a single block device to add to the device cache. */ static void probe_one(blkid_cache cache, const char *ptname, - dev_t devno, int pri) + dev_t devno, int pri, int only_if_new) { blkid_dev dev = NULL; struct list_head *p; @@ -91,6 +91,8 @@ static void probe_one(blkid_cache cache, const char *ptname, blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs); if (tmp->bid_devno == devno) { + if (only_if_new) + return; dev = blkid_verify(cache, tmp); break; } @@ -171,7 +173,7 @@ static dev_t lvm_get_devno(const char *lvm_device) return ret; } -static void lvm_probe_all(blkid_cache cache) +static void lvm_probe_all(blkid_cache cache, int only_if_new) { DIR *vg_list; struct dirent *vg_iter; @@ -222,7 +224,8 @@ static void lvm_probe_all(blkid_cache cache) DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", lvm_device, (unsigned int) dev)); - probe_one(cache, lvm_device, dev, BLKID_PRI_LVM); + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, + only_if_new); free(lvm_device); } closedir(lv_list); @@ -235,7 +238,7 @@ exit: #define PROC_EVMS_VOLUMES "/proc/evms/volumes" static int -evms_probe_all(blkid_cache cache) +evms_probe_all(blkid_cache cache, int only_if_new) { char line[100]; int ma, mi, sz, num = 0; @@ -253,7 +256,8 @@ evms_probe_all(blkid_cache cache) DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", device, ma, mi)); - probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS); + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, + only_if_new); num++; } fclose(procpt); @@ -263,7 +267,7 @@ evms_probe_all(blkid_cache cache) /* * Read the device data for all available block devices in the system. */ -int blkid_probe_all(blkid_cache cache) +static int probe_all(blkid_cache cache, int only_if_new) { FILE *proc; char line[1024]; @@ -286,9 +290,9 @@ int blkid_probe_all(blkid_cache cache) return 0; blkid_read_cache(cache); - evms_probe_all(cache); + evms_probe_all(cache, only_if_new); #ifdef VG_DIR - lvm_probe_all(cache); + lvm_probe_all(cache, only_if_new); #endif proc = fopen(PROC_PARTITIONS, "r"); @@ -325,7 +329,8 @@ int blkid_probe_all(blkid_cache cache) ptname, (unsigned int) devs[which])); if (sz > 1) - probe_one(cache, ptname, devs[which], 0); + probe_one(cache, ptname, devs[which], 0, + only_if_new); lens[which] = 0; lens[last] = 0; } else if (lens[last] && strncmp(ptnames[last], ptname, @@ -333,23 +338,44 @@ int blkid_probe_all(blkid_cache cache) DBG(DEBUG_DEVNAME, printf("whole dev %s, devno 0x%04X\n", ptnames[last], (unsigned int) devs[last])); - probe_one(cache, ptnames[last], devs[last], 0); + probe_one(cache, ptnames[last], devs[last], 0, + only_if_new); lens[last] = 0; } } /* Handle the last device if it wasn't partitioned */ if (lens[which]) - probe_one(cache, ptname, devs[which], 0); + probe_one(cache, ptname, devs[which], 0, only_if_new); fclose(proc); + blkid_flush_cache(cache); + return 0; +} +int blkid_probe_all(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n")); + ret = probe_all(cache, 0); cache->bic_time = time(0); cache->bic_flags |= BLKID_BIC_FL_PROBED; - blkid_flush_cache(cache); - return 0; + DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n")); + return ret; } +int blkid_probe_all_new(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n")); + ret = probe_all(cache, 1); + DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n")); + return ret; +} + + #ifdef TEST_PROGRAM int main(int argc, char **argv) { diff --git a/lib/blkid/tag.c b/lib/blkid/tag.c index 9470ac0..9bca2c6 100644 --- a/lib/blkid/tag.c +++ b/lib/blkid/tag.c @@ -316,9 +316,6 @@ extern void blkid_tag_iterate_end(blkid_tag_iterate iter) * type/value pair. If there is more than one device that matches the * search specification, it returns the one with the highest priority * value. This allows us to give preference to EVMS or LVM devices. - * - * XXX there should also be an interface which uses an iterator so we - * can get all of the devices which match a type/value search parameter. */ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, const char *type, @@ -328,6 +325,7 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, blkid_dev dev; int pri; struct list_head *p; + int probe_new = 0; if (!cache || !type || !value) return NULL; @@ -359,6 +357,13 @@ try_again: goto try_again; } + if (!dev && !probe_new) { + if (blkid_probe_all_new(cache) < 0) + return NULL; + probe_new++; + goto try_again; + } + if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { if (blkid_probe_all(cache) < 0) return NULL; diff --git a/misc/ChangeLog b/misc/ChangeLog index b0b87f6..67dec48 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -4,6 +4,10 @@ blkid_dev_has_tag(). Remove compare_search_type() since it has been obseleted by blkid_dev_has_tag(). + * blkid.c (main): Add a new flag, -l, which will use a more + efficient method to find the device that matches a + particular tag specifier. + 2005-05-06 Theodore Ts'o * blkid.c (main): Use an int instead of an char to store the diff --git a/misc/blkid.8.in b/misc/blkid.8.in index 0f6f7c8..f1effe1 100644 --- a/misc/blkid.8.in +++ b/misc/blkid.8.in @@ -11,7 +11,7 @@ blkid \- command\-line utility to locate/print block device attributes .SH SYNOPSIS .B blkid [ -.B \-hv +.B \-hlv ] [ [ @@ -63,6 +63,32 @@ scanned but not necessarily available at this time), specify .B \-h Display a usage message and exit. .TP +.B \-l +Lookup the device that matches the search parameter specified using +the +.B \-t +option, assuming that there is only one matching the search parameter. +For a system with a large number of disks, this will be more +efficient by avoiding the need to revalidate devices unless absolutely +necessary. If this option is not specified, +.B blkid +will use a less efficient approach, which allows +.B blkid +to print all of the devices that match the search parameter. +.IP +This option is best used for tag searches such as +.I LABEL=data_vol +or +.IR UUID=e280469a-d06f-4c0b-b068-44f3b576029e . +If you want +.B blkid +to print all of the ext3 filesystems using a search parameter +such as +.IR TYPE=ext3 , +then this option should +.I not +be used. +.TP .B \-o Display .BR blkid 's @@ -117,7 +143,7 @@ instead of writing it to the default cache file If you don't want to save the cache to the default file, specify .IR /dev/null. If not specified it will be the same file as that given by the -.B -c +.B \-c option. .TP .I diff --git a/misc/blkid.c b/misc/blkid.c index 44dd7d6..256f4f1 100644 --- a/misc/blkid.c +++ b/misc/blkid.c @@ -37,12 +37,13 @@ static void usage(int error) print_version(out); fprintf(out, - "usage:\t%s [-c ] [-h] [-o format] " + "usage:\t%s [-c ] [-hl] [-o format] " "[-s ] [-t ]\n [-v] [-w ] [dev ...]\n" "\t-c\tcache file (default: /etc/blkid.tab, /dev/null = none)\n" "\t-h\tprint this usage message and exit\n" "\t-s\tshow specified tag(s) (default show all tags)\n" "\t-t\tfind device with a specific token (NAME=value pair)\n" + "\t-l\tlookup the the first device with arguments specified by -t\n" "\t-v\tprint version and exit\n" "\t-w\twrite cache to different file (/dev/null = no write)\n" "\tdev\tspecify device(s) to probe (default: all devices)\n", @@ -101,9 +102,10 @@ int main(int argc, char **argv) int err = 4; unsigned int i; int output_format = 0; + int lookup = 0; int c; - while ((c = getopt (argc, argv, "c:f:ho:s:t:w:v")) != EOF) + while ((c = getopt (argc, argv, "c:f:hlo:s:t:w:v")) != EOF) switch (c) { case 'c': if (optarg && !*optarg) @@ -113,6 +115,9 @@ int main(int argc, char **argv) if (!write) write = read; break; + case 'l': + lookup++; + break; case 'o': if (!strcmp(optarg, "value")) output_format = OUTPUT_VALUE_ONLY; @@ -172,8 +177,25 @@ int main(int argc, char **argv) goto exit; err = 2; + if (lookup) { + blkid_dev dev; + + if (!search_type) { + fprintf(stderr, "The lookup option requires a " + "search type specified using -t\n"); + exit(1); + } + /* Load any additional devices not in the cache */ + for (i = 0; i < numdev; i++) + blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL); + + if ((dev = blkid_find_dev_with_tag(cache, search_type, + search_value))) { + print_tags(dev, show, numtag, output_format); + err = 0; + } /* If we didn't specify a single device, show all available devices */ - if (!numdev) { + } else if (!numdev) { blkid_dev_iterate iter; blkid_dev dev; -- 1.8.3.1