The access, birth, modification and change times are added to
storage volumes and corresponding xml representations.
---
docs/formatstorage.html.in | 27 +++++++++++++++++++++++++++
docs/schemas/storagevol.rng | 39 +++++++++++++++++++++++++++++++++++++++
src/conf/storage_conf.c | 21 +++++++++++++++++++++
src/conf/storage_conf.h | 13 +++++++++++++
src/storage/storage_backend.c | 21 +++++++++++++++++++++
5 files changed, 121 insertions(+)
diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index d0e4319..d8ffbea 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -141,6 +141,20 @@
<mode>0744</mode>
<label>virt_image_t</label>
</permissions>
+ <timestamps>
+ <atime>
+ <sec>1341933637</sec>
+ <nsec>27319099</nsec>
+ </atime>
+ <ctime>
+ <sec>1341930622</sec>
+ <nsec>47245868</nsec>
+ </ctime>
+ <mtime>
+ <sec>1341930622</sec>
+ <nsec>47245868</nsec>
+ </mtime>
+ </timestamps>
<encryption type='...'>
...
</encryption>
@@ -172,6 +186,19 @@
contains the MAC (eg SELinux) label string.
<span class="since">Since 0.4.1</span>
</dd>
+ <dt><code>timestamps</code></dt>
+ <dd>Provides timing information about the volume. Up to four sub-elements
are
+ present, where <code>atime</code>, <code>btime</code>,
<code>ctime</code>
+ and <code>mtime</code> hold the access, birth, change and
modification time
+ of the volume, where known. Each timestamp is represented by an attribute
+ <code>sec</code> and and optional attribute
<code>nsec</code>. The first
+ attribute holds the seconds since the beginning of the epoch and the second
+ attribute the additional nanoseconds. If nanosecond resolution isn't
supported
+ by the host OS or filesystem then the <code>nsec</code> attribute is
omitted.
+ For technical reasons the attribute is also omitted when zero. All timestamps
+ are readonly attributes and are ignored when creating a volume.
+ <span class="since">Since 0.10.0</span>
+ </dd>
<dt><code>encryption</code></dt>
<dd>If present, specifies how the volume is encrypted. See
the <a href="formatstorageencryption.html">Storage
Encryption</a> page
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 7a74331..af48bd2 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -63,6 +63,44 @@
</optional>
</define>
+ <define name='timestamps'>
+ <optional>
+ <element name='timestamps'>
+ <optional>
+ <element name='atime'>
+ <ref name='timestamp'/>
+ </element>
+ </optional>
+ <optional>
+ <element name='btime'>
+ <ref name='timestamp'/>
+ </element>
+ </optional>
+ <optional>
+ <element name='ctime'>
+ <ref name='timestamp'/>
+ </element>
+ </optional>
+ <optional>
+ <element name='mtime'>
+ <ref name='timestamp'/>
+ </element>
+ </optional>
+ </element>
+ </optional>
+ </define>
+
+ <define name='timestamp'>
+ <element name='sec'>
+ <ref name='unsignedLong'/>
+ </element>
+ <optional>
+ <element name='nsec'>
+ <ref name='unsignedLong'/>
+ </element>
+ </optional>
+ </define>
+
<define name='target'>
<element name='target'>
<optional>
@@ -72,6 +110,7 @@
</optional>
<ref name='format'/>
<ref name='permissions'/>
+ <ref name='timestamps'/>
<optional>
<ref name='encryption'/>
</optional>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 36a3bb9..5651b76 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1241,6 +1241,20 @@ virStorageVolDefParseFile(virStoragePoolDefPtr pool,
return virStorageVolDefParse(pool, NULL, filename);
}
+static void
+virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
+ struct timespec *ts)
+{
+ if (ts->tv_nsec < 0)
+ return;
+ virBufferAsprintf(buf, " <%s>\n", name);
+ virBufferAsprintf(buf, " <sec>%llu</sec>\n",
+ (unsigned long long) ts->tv_sec);
+ if (ts->tv_nsec)
+ virBufferAsprintf(buf, " <nsec>%ld</nsec>\n",
ts->tv_nsec);
+ virBufferAsprintf(buf, " </%s>\n", name);
+}
+
static int
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
virBufferPtr buf,
@@ -1277,6 +1291,13 @@ virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
virBufferAddLit(buf," </permissions>\n");
+ virBufferAddLit(buf, " <timestamps>\n");
+ virStorageVolTimestampFormat(buf, "atime", &def->timestamps.atime);
+ virStorageVolTimestampFormat(buf, "btime", &def->timestamps.btime);
+ virStorageVolTimestampFormat(buf, "ctime", &def->timestamps.ctime);
+ virStorageVolTimestampFormat(buf, "mtime", &def->timestamps.mtime);
+ virBufferAddLit(buf, " </timestamps>\n");
+
if (def->encryption) {
virBufferAdjustIndent(buf, 4);
if (virStorageEncryptionFormat(buf, def->encryption) < 0)
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 5733b57..b67ef64 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -46,6 +46,18 @@ struct _virStoragePerms {
/* Storage volumes */
+typedef struct _virStorageTimestamps virStorageTimestamps;
+typedef virStorageTimestamps *virStorageTimestampsPtr;
+struct _virStorageTimestamps {
+ struct timespec atime;
+ /* if btime.tv_nsec == -1 then
+ * birth time is unknown
+ */
+ struct timespec btime;
+ struct timespec ctime;
+ struct timespec mtime;
+};
+
/*
* How the volume's data is stored on underlying
@@ -77,6 +89,7 @@ struct _virStorageVolTarget {
char *path;
int format;
virStoragePerms perms;
+ virStorageTimestamps timestamps;
int type; /* only used by disk backend for partition type */
/* Currently used only in virStorageVolDef.target, not in .backingstore. */
virStorageEncryptionPtr encryption;
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 6ea0881..1ef6df9 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1155,6 +1155,11 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr
target,
unsigned long long *capacity)
{
struct stat sb;
+ struct timespec *const atime = &target->timestamps.atime,
+ *const btime = &target->timestamps.btime,
+ *const catime = &target->timestamps.ctime,
+ *const mtime = &target->timestamps.mtime;
+
#if HAVE_SELINUX
security_context_t filecon = NULL;
#endif
@@ -1208,6 +1213,22 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr
target,
target->perms.uid = sb.st_uid;
target->perms.gid = sb.st_gid;
+ atime->tv_sec = sb.st_atime;
+ mtime->tv_sec = sb.st_mtime;
+ catime->tv_sec = sb.st_ctime;
+#if _BSD_SOURCE || _SVID_SOURCE || \
+ _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
+ atime->tv_nsec = sb.st_atim.tv_nsec;
+ mtime->tv_nsec = sb.st_mtim.tv_nsec;
+ catime->tv_nsec = sb.st_ctim.tv_nsec;
+#else
+ atime->tv_nsec = sb.st_atimensec;
+ mtime->tv_nsec = sb.st_mtimensec;
+ catime->tv_nsec = sb.st_ctimensec;
+#endif
+ btime->tv_sec = -1;
+ btime->tv_nsec = -1;
+
VIR_FREE(target->perms.label);
#if HAVE_SELINUX
--
1.7.9.5