]> err.no Git - util-linux/commitdiff
libblkid: add microsecond resolution for cache entries
authorKarel Zak <kzak@redhat.com>
Wed, 17 Mar 2010 13:49:14 +0000 (14:49 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 17 Mar 2010 13:49:14 +0000 (14:49 +0100)
The libblkid library uses stat.st_mtine to detect changes on the
device. The last update time of of the device in the cache is stored
as TIME= tag in the /etc/blkid.tab file.

Linux since 2.5.48 supports nanosecond resolution and more precise
time is available in the stat.st_mtim timespec struct.

This patch add microsecond precision to TIME= tag in the cache file,
old format:

TIME="<sec>"

the new format:

TIME="<sec>.<usec>"

This change is backwardly compatible.

Now, the blkid_verify() function checks stat.st_mtime and
stat.st_mtim.tv_nsec/1000.

Test:

 # e2label /dev/sdb1 AAAA

old version:

 # blkid -s LABEL /dev/sdb1; e2label /dev/sdb1 BBBB; blkid -s LABEL /dev/sdb1
 /dev/sdb1: LABEL="AAAA"
 /dev/sdb1: LABEL="AAAA"

new version:

 # blkid -s LABEL /dev/sdb1; e2label /dev/sdb1 BBBB; blkid -s LABEL /dev/sdb1
 /dev/sdb1: LABEL="AAAA"
 /dev/sdb1: LABEL="BBBB"

Signed-off-by: Karel Zak <kzak@redhat.com>
configure.ac
shlibs/blkid/src/blkidP.h
shlibs/blkid/src/dev.c
shlibs/blkid/src/read.c
shlibs/blkid/src/save.c
shlibs/blkid/src/verify.c

index 9cc20b7acf28136ab5c85b5238d4a4a929b9be9b..96d7219f995876fccc07e1c16304f38175dd48a8 100644 (file)
@@ -601,6 +601,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 AC_CHECK_MEMBERS([struct termios.c_line],,,
     [[#include <termios.h>]])
 
+AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec],,,
+       [#include <sys/stat.h>])
+
 AC_CHECK_DECLS([
  ADDR_NO_RANDOMIZE,
  FDPIC_FUNCPTRS,
index 1de6dd064396a039356af5002b88510320f2a7d9..db5da5e80d853875a21926e3db043b9e3671aae2 100644 (file)
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdint.h>
@@ -45,6 +46,7 @@ struct blkid_struct_dev
        int                     bid_pri;        /* Device priority */
        dev_t                   bid_devno;      /* Device major/minor number */
        time_t                  bid_time;       /* Last update time of device */
+       suseconds_t             bid_utime;      /* Last update time (microseconds) */
        unsigned int            bid_flags;      /* Device status bitflags */
        char                    *bid_label;     /* Shortcut to device LABEL */
        char                    *bid_uuid;      /* Shortcut to binary UUID */
index e02f170c77c6e170bd46e2806d3be82d0c12d40c..24d989ddc938ee8f3dd1fe22dbfbad87d6a8f4fa 100644 (file)
@@ -84,7 +84,7 @@ void blkid_debug_dump_dev(blkid_dev dev)
 
        printf("  dev: name = %s\n", dev->bid_name);
        printf("  dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
-       printf("  dev: TIME=\"%ld\"\n", (long)dev->bid_time);
+       printf("  dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
        printf("  dev: PRI=\"%d\"\n", dev->bid_pri);
        printf("  dev: flags = 0x%08X\n", dev->bid_flags);
 
index b5e9cd02435af915af5e774ab8a0fa8083faa7e8..e6aa083682dbffab18e80ce840e9bc2e1d81b3dd 100644 (file)
@@ -49,7 +49,8 @@ static void debug_dump_dev(blkid_dev dev);
  *
  *     The following tags are required for each entry:
  *     <ID="id">       unique (within this file) ID number of this device
- *     <TIME="time">   (ascii time_t) time this entry was last read from disk
+ *     <TIME="sec.usec"> (time_t and suseconds_t) time this entry was last
+ *                      read from disk
  *     <TYPE="type">   (detected) type of filesystem/data for this partition
  *
  *     The following tags may be present, depending on the device contents
@@ -318,9 +319,12 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
                dev->bid_devno = STRTOULL(value, 0, 0);
        else if (!strcmp(name, "PRI"))
                dev->bid_pri = strtol(value, 0, 0);
-       else if (!strcmp(name, "TIME"))
-               dev->bid_time = STRTOULL(value, 0, 0);
-       else
+       else if (!strcmp(name, "TIME")) {
+               char *end = NULL;
+               dev->bid_time = STRTOULL(value, &end, 0);
+               if (end && *end == '.')
+                       dev->bid_utime = STRTOULL(end + 1, 0, 0);
+       } else
                ret = blkid_set_tag(dev, name, value, strlen(value));
 
        DBG(DEBUG_READ, printf("    tag: %s=\"%s\"\n", name, value));
@@ -455,7 +459,7 @@ static void debug_dump_dev(blkid_dev dev)
 
        printf("  dev: name = %s\n", dev->bid_name);
        printf("  dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
-       printf("  dev: TIME=\"%lld\"\n", (long long)dev->bid_time);
+       printf("  dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
        printf("  dev: PRI=\"%d\"\n", dev->bid_pri);
        printf("  dev: flags = 0x%08X\n", dev->bid_flags);
 
index a1583ecca095542b39024dc127738547d677498b..c04c2242743950826b9a769a8b801fa125758efb 100644 (file)
@@ -37,9 +37,11 @@ static int save_dev(blkid_dev dev, FILE *file)
            printf("device %s, type %s\n", dev->bid_name, dev->bid_type ?
                   dev->bid_type : "(null)"));
 
-       fprintf(file,
-               "<device DEVNO=\"0x%04lx\" TIME=\"%ld\"",
-               (unsigned long) dev->bid_devno, (long) dev->bid_time);
+       fprintf(file, "<device DEVNO=\"0x%04lx\" TIME=\"%ld.%ld\"",
+                       (unsigned long) dev->bid_devno,
+                       (long) dev->bid_time,
+                       (long) dev->bid_utime);
+
        if (dev->bid_pri)
                fprintf(file, " PRI=\"%d\"", dev->bid_pri);
        list_for_each(p, &dev->bid_tags) {
index 27360260094e606525907791b87177af876345d8..a0cb3fea2f2ddaefac000b2d13f26b34b3120247 100644 (file)
@@ -11,6 +11,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -73,19 +74,34 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
                return NULL;
        }
 
-       if ((now >= dev->bid_time) &&
-           (st.st_mtime <= dev->bid_time) &&
-           ((diff < BLKID_PROBE_MIN) ||
-            (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
-             diff < BLKID_PROBE_INTERVAL)))
+       if (now >= dev->bid_time &&
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+           (st.st_mtime < dev->bid_time ||
+               (st.st_mtime == dev->bid_time &&
+                st.st_mtim.tv_nsec / 1000 <= dev->bid_utime)) &&
+#else
+           st.st_mtime <= dev->bid_time &&
+#endif
+           (diff < BLKID_PROBE_MIN ||
+               (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
+                diff < BLKID_PROBE_INTERVAL)))
                return dev;
 
+#ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
        DBG(DEBUG_PROBE,
            printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
                   "time since last check %lu)\n",
                   dev->bid_name, (unsigned long)dev->bid_time,
                   (unsigned long)st.st_mtime, (unsigned long)diff));
-
+#else
+       DBG(DEBUG_PROBE,
+           printf("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\n\t"
+                  "time since last check %lu)\n",
+                  dev->bid_name,
+                  (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime,
+                  (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000,
+                  (unsigned long)diff));
+#endif
 
        if (!cache->probe) {
                cache->probe = blkid_new_probe();
@@ -156,8 +172,16 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
 
 found_type:
        if (dev) {
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+               struct timeval tv;
+               if (!gettimeofday(&tv, NULL)) {
+                       dev->bid_time = tv.tv_sec;
+                       dev->bid_utime = tv.tv_usec;
+               } else
+#endif
+                       dev->bid_time = time(0);
+
                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;