+2003-02-14 Theodore Ts'o <tytso@mit.edu>
+
+ * Makefile.in (blkid): When building the blkid, don't link against
+ the shared blkid library; link only against the static
+ blkid library.
+
+ * blkidP.h (struct blkid_struct_dev): Remove bid_size and
+ bid_devsize (since they aren't used any more) and add
+ bid_pri to the device structure.
+
+ * devname.c (probe_one, lvm_probe_all, evms_probe_all,
+ blkid_probe_all): Set the bid_pri filed in the device
+ structure depending on type of device so that EVMS, LVM,
+ and MD devices get priority over normal devices.
+
+ * tag.c (blkid_find_dev_with_tag): When looking for a device that
+ matches the search criteria, return the one with the
+ largest priority (bid_pri).
+
+ * save.c (save_dev): Write out the PRI tag from bid_pri.
+
+ * read.c (parse_tag): Parse the PRI tag and store its value in
+ bid_pri.
+
+ * probe.c (blkid_verify_devname): If the device does not exist
+ (open returns ENOENT), treat this as a fatal error and
+ release the device. After verifying the device, set the
+ cache as being modified so the changes are written out.
+
+ * resolve.c (main): Change the test driver to get a blkid cache
+ and pass it to blkid_get_tagname_devname and
+ blkid_get_token, as the cache is no longer optional.
+
2003-02-12 Theodore Ts'o <tytso@mit.edu>
* blkid.h, blkidP.h, cache.c, dev.c, devname.c, devno.c, probe.c,
$(CC) -Wall $(ALL_CFLAGS) -c $(top_srcdir)/misc/blkid.c \
-o ../../misc/blkid.o
-blkid: ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID)
- $(CC) -Wall -o blkid ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID)
+blkid: ../../misc/blkid.o libblkid.a $(LIBUUID)
+ $(CC) -Wall -o blkid ../../misc/blkid.o libblkid.a $(LIBUUID)
check:: tst_cache tst_devname tst_devno tst_getsize tst_probe \
tst_read tst_resolve tst_save
blkid_cache bid_cache; /* Dev belongs to this cache */
char *bid_name; /* Device inode pathname */
char *bid_type; /* Preferred device TYPE */
- blkid_loff_t bid_size; /* Filesystem size in bytes */
- blkid_loff_t bid_devsize; /* Device size in bytes */
+ int bid_pri; /* Device priority */
dev_t bid_devno; /* Device major/minor number */
time_t bid_time; /* Last update time of device */
unsigned int bid_id; /* Unique cache id for device */
struct list_head bic_devs; /* List head of all devices */
struct list_head bic_tags; /* List head of all tag types */
time_t bic_time; /* Last probe time */
- unsigned int bic_idmax; /* Highest ID assigned */
+p unsigned int bic_idmax; /* Highest ID assigned */
unsigned int bic_flags; /* Status flags of the cache */
char *bic_filename; /* filename of cache */
};
#define BLKID_ERR_PARAM 22
#define BLKID_ERR_BIG 27
+/*
+ * Priority settings for different types of devices
+ */
+#define BLKID_PRI_EVMS 30
+#define BLKID_PRI_LVM 20
+#define BLKID_PRI_MD 10
+
#if defined(TEST_PROGRAM)
#define DEBUG
#endif
printf(" dev: DEVNO=\"0x%0Lx\"\n", dev->bid_devno);
printf(" dev: ID=\"%u\"\n", dev->bid_id);
printf(" dev: TIME=\"%lu\"\n", dev->bid_time);
- printf(" dev: size = %Lu\n", dev->bid_size);
+ printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
printf(" dev: flags = 0x%08X\n", dev->bid_flags);
list_for_each(p, &dev->bid_tags) {
/*
* Probe a single block device to add to the device cache.
*/
-static blkid_dev probe_one(blkid_cache cache, const char *ptname,
- dev_t devno)
+static void probe_one(blkid_cache cache, const char *ptname,
+ dev_t devno, int pri)
{
blkid_dev dev = NULL;
struct list_head *p;
}
}
if (dev && dev->bid_devno == devno)
- return dev;
+ goto set_pri;
/*
* Take a quick look at /dev/ptname for the device number. We check
sprintf(device, "%s/%s", *dir, ptname);
if ((dev = blkid_get_devname(cache, device, BLKID_DEV_FIND)) &&
dev->bid_devno == devno)
- return dev;
+ goto set_pri;
if (stat(device, &st) == 0 && st.st_rdev == devno) {
devname = blkid_strdup(device);
if (!devname) {
devname = blkid_devno_to_devname(devno);
if (!devname)
- return NULL;
+ return;
}
dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL);
free(devname);
- return dev;
+set_pri:
+ if (!pri && !strncmp(ptname, "md", 2))
+ pri = BLKID_PRI_MD;
+ dev->bid_pri = pri;
+ return;
}
#define PROC_PARTITIONS "/proc/partitions"
sprintf(lvm_device, "%s/%s", vg_name, lv_name);
DBG(printf("LVM dev %s: devno 0x%04X\n",
lvm_device, dev));
- probe_one(cache, lvm_device, dev);
+ probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
free(lvm_device);
}
closedir(lv_list);
DBG(printf("Checking partition %s (%d, %d)\n",
device, ma, mi));
- probe_one(cache, device, makedev(ma, mi));
+ probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
num++;
}
fclose(procpt);
int blkid_probe_all(blkid_cache cache)
{
FILE *proc;
- int firstPass;
+ char line[1024];
+ char ptname0[128], ptname1[128], *ptname = 0;
+ char *ptnames[2] = { ptname0, ptname1 };
+ dev_t devs[2];
+ int ma, mi;
+ unsigned long long sz;
+ int lens[2] = { 0, 0 };
+ int which = 0, last = 0;
if (!cache)
return -BLKID_ERR_PARAM;
time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
return 0;
- if (evms_probe_all(cache))
- goto finish;
-
+ evms_probe_all(cache);
#ifdef VG_DIR
lvm_probe_all(cache);
#endif
if (!proc)
return -BLKID_ERR_PROC;
- for (firstPass = 1; firstPass >= 0; firstPass--) {
- char line[1024];
- char ptname0[128], ptname1[128], *ptname = 0;
- char *ptnames[2] = { ptname0, ptname1 };
- dev_t devs[2];
- int ma, mi;
- unsigned long long sz;
- int lens[2] = { 0, 0 };
- int handleOnFirst;
- int which = 0, last = 0;
-
- fseek(proc, 0, SEEK_SET);
-
- while (fgets(line, sizeof(line), proc)) {
- last = which;
- which ^= 1;
- ptname = ptnames[which];
-
- if (sscanf(line, " %d %d %lld %128[^\n ]",
- &ma, &mi, &sz, ptname) != 4)
- continue;
- devs[which] = makedev(ma, mi);
-
- DBG(printf("read partition name %s\n", ptname));
-
- /* look only at md devices on first pass */
- handleOnFirst = !strncmp(ptname, "md", 2);
- if (firstPass != handleOnFirst)
- continue;
+ while (fgets(line, sizeof(line), proc)) {
+ last = which;
+ which ^= 1;
+ ptname = ptnames[which];
- /* Skip whole disk devs unless they have no partitions
- * If we don't have a partition on this dev, also
- * check previous dev to see if it didn't have a partn.
- * heuristic: partition name ends in a digit.
- *
- * Skip extended partitions.
- * heuristic: size is 1
- *
- * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
- */
-
- lens[which] = strlen(ptname);
- if (isdigit(ptname[lens[which] - 1])) {
- DBG(printf("partition dev %s, devno 0x%04X\n",
- ptname, devs[which]));
-
- if (sz > 1)
- probe_one(cache, ptname, devs[which]);
- lens[which] = 0;
- lens[last] = 0;
- } else if (lens[last] &&
- strncmp(ptnames[last], ptname,
- lens[last])) {
- DBG(printf("whole dev %s, devno 0x%04X\n",
- ptname, devs[last]));
- probe_one(cache, ptname, devs[last]);
- lens[last] = 0;
- }
+ if (sscanf(line, " %d %d %lld %128[^\n ]",
+ &ma, &mi, &sz, ptname) != 4)
+ continue;
+ devs[which] = makedev(ma, mi);
+
+ DBG(printf("read partition name %s\n", ptname));
+
+ /* Skip whole disk devs unless they have no partitions
+ * If we don't have a partition on this dev, also
+ * check previous dev to see if it didn't have a partn.
+ * heuristic: partition name ends in a digit.
+ *
+ * Skip extended partitions.
+ * heuristic: size is 1
+ *
+ * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
+ */
+
+ lens[which] = strlen(ptname);
+ if (isdigit(ptname[lens[which] - 1])) {
+ DBG(printf("partition dev %s, devno 0x%04X\n",
+ ptname, devs[which]));
+
+ if (sz > 1)
+ probe_one(cache, ptname, devs[which], 0);
+ lens[which] = 0;
+ lens[last] = 0;
+ } else if (lens[last] && strncmp(ptnames[last], ptname,
+ lens[last])) {
+ DBG(printf("whole dev %s, devno 0x%04X\n",
+ ptnames[last], devs[last]));
+ probe_one(cache, ptnames[last], devs[last], 0);
+ lens[last] = 0;
}
-
- /* Handle the last device if it wasn't partitioned */
- if (lens[which])
- probe_one(cache, ptname, devs[which]);
}
+
+ /* Handle the last device if it wasn't partitioned */
+ if (lens[which])
+ probe_one(cache, ptname, devs[which], 0);
+
fclose(proc);
-finish:
cache->bic_time = time(0);
cache->bic_flags |= BLKID_BIC_FL_PROBED;
-
return 0;
}
diff < BLKID_PROBE_INTERVAL))
return dev;
- DBG(printf("need to revalidate %s\n", dev->bid_name));
+ DBG(printf("need to revalidate %s (time since last check %lu)\n",
+ dev->bid_name, diff));
if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
(fstat(fd, &st) < 0) || !S_ISBLK(st.st_mode)) {
- if (errno == ENXIO || errno == ENODEV) {
+ if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
blkid_free_dev(dev);
return NULL;
}
dev->bid_devno = st.st_rdev;
dev->bid_time = time(0);
dev->bid_flags |= BLKID_BID_FL_VERIFIED;
+ cache->bic_flags |= BLKID_BIC_FL_CHANGED;
blkid_set_tag(dev, "TYPE", type, 0, 1);
if (sec_type)
cache->bic_idmax = dev->bid_id;
} else if (!strcmp(name, "DEVNO"))
dev->bid_devno = STRTOULL(value, 0, 0);
+ else if (!strcmp(name, "PRI"))
+ dev->bid_pri = strtol(value, 0, 0);
else if (!strcmp(name, "TIME"))
/* FIXME: need to parse a long long eventually */
dev->bid_time = strtol(value, 0, 0);
if (!devname)
return NULL;
- if (!cache)
- DBG(printf("no cache given, direct device probe\n"));
-
if ((dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL)) &&
(found = blkid_find_tag_dev(dev, tagname)))
ret = blkid_strdup(found->bit_val);
int main(int argc, char **argv)
{
char *value;
+ blkid_cache cache;
if (argc != 2 && argc != 3) {
fprintf(stderr, "Usage:\t%s tagname=value\n"
argv[0], argv[0]);
exit(1);
}
+ if (blkid_get_cache(&cache, 0) < 0) {
+ fprintf(stderr, "Couldn't get blkid cache\n");
+ exit(1);
+ }
+
if (argv[2]) {
- value = blkid_get_tagname_devname(NULL, argv[1], argv[2]);
+ value = blkid_get_tagname_devname(cache, argv[1], argv[2]);
printf("%s has tag %s=%s\n", argv[2], argv[1],
value ? value : "<missing>");
} else {
- value = blkid_get_token(NULL, argv[1], NULL);
+ value = blkid_get_token(cache, argv[1], NULL);
printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
}
+ blkid_put_cache(cache);
return value ? 0 : 1;
}
#endif
"<device TYPE=\"%s\" DEVNO=\"0x%04lx\" ID=\"%d\" TIME=\"%lu\"",
dev->bid_type, (unsigned long) dev->bid_devno,
dev->bid_id, dev->bid_time);
+ if (dev->bid_pri)
+ fprintf(file, " PRI=\"%d\"", dev->bid_pri);
list_for_each(p, &dev->bid_tags) {
blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
if (strcmp(tag->bit_name, "TYPE"))
/*
* This function returns a device which matches a particular
- * type/value pair. Its behaviour is currently undefined if there is
- * more than one device which matches the search specification.
- * In the future we may have some kind of preference scheme so that if
- * there is more than one match for a given label/uuid (for example in
- * the case of snapshots) we return the preferred device.
+ * 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.
const char *type,
const char *value)
{
- blkid_tag head = 0, found = 0;
+ blkid_tag head, found;
+ blkid_dev dev;
+ int pri;
struct list_head *p;
if (!cache || !type || !value)
DBG(printf("looking for %s=%s in cache\n", type, value));
try_again:
- if (!head)
- head = blkid_find_head_cache(cache, type);
+ pri = -1;
+ found = 0;
+ head = blkid_find_head_cache(cache, type);
if (head) {
list_for_each(p, &head->bit_names) {
blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
bit_names);
- if (!strcmp(tmp->bit_val, value)) {
+ if (!strcmp(tmp->bit_val, value) &&
+ tmp->bit_dev->bid_pri > pri) {
found = tmp;
- break;
+ dev = found->bit_dev;
+ pri = dev->bid_pri;
}
}
}
+ dev = blkid_verify_devname(cache, dev);
+ if (dev && strcmp(found->bit_val, value))
+ dev = 0;
- if ((!head || !found) && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
+ if ((!head || !dev) && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
blkid_probe_all(cache);
goto try_again;
}
- return (found ? found->bit_dev : NULL);
+ return dev;
}