c401cc
From 71beabf07ea569c41b4b2ce9a8d91e82a85b29c3 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <71beabf07ea569c41b4b2ce9a8d91e82a85b29c3@dist-git>
c401cc
From: Eric Blake <eblake@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:54:32 +0100
c401cc
Subject: [PATCH] storage: reduce number of stat calls
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
We are calling fstat() at least twice per storage volume in
c401cc
a directory storage pool; this is rather wasteful.  Refactoring
c401cc
this is also a step towards making code reusable for gluster,
c401cc
where gluster can provide struct stat but cannot use fstat().
c401cc
c401cc
* src/storage/storage_backend.h
c401cc
(virStorageBackendVolOpenCheckMode)
c401cc
(virStorageBackendUpdateVolTargetInfoFD): Update signature.
c401cc
* src/storage/storage_backend.c
c401cc
(virStorageBackendVolOpenCheckMode): Pass stat results back.
c401cc
(virStorageBackendUpdateVolTargetInfoFD): Use existing stats.
c401cc
(virStorageBackendVolOpen, virStorageBackendUpdateVolTargetInfo):
c401cc
Update callers.
c401cc
* src/storage/storage_backend_fs.c (virStorageBackendProbeTarget):
c401cc
Likewise.
c401cc
* src/storage/storage_backend_scsi.c
c401cc
(virStorageBackendSCSIUpdateVolTargetInfo): Likewise.
c401cc
* src/storage/storage_backend_mpath.c
c401cc
(virStorageBackendMpathUpdateVolTargetInfo): Likewise.
c401cc
c401cc
Signed-off-by: Eric Blake <eblake@redhat.com>
c401cc
(cherry picked from commit 9cac863965aa318667619727c387ec8ee3965557)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/storage/storage_backend.c       | 62 +++++++++++++++++--------------------
c401cc
 src/storage/storage_backend.h       | 10 ++++--
c401cc
 src/storage/storage_backend_fs.c    |  5 +--
c401cc
 src/storage/storage_backend_mpath.c |  7 +++--
c401cc
 src/storage/storage_backend_scsi.c  |  7 +++--
c401cc
 5 files changed, 49 insertions(+), 42 deletions(-)
c401cc
c401cc
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
c401cc
index 086642c..f8c0004 100644
c401cc
--- a/src/storage/storage_backend.c
c401cc
+++ b/src/storage/storage_backend.c
c401cc
@@ -1129,30 +1129,30 @@ virStorageBackendForType(int type)
c401cc
  * volume is a dangling symbolic link.
c401cc
  */
c401cc
 int
c401cc
-virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
c401cc
+virStorageBackendVolOpenCheckMode(const char *path, struct stat *sb,
c401cc
+                                  unsigned int flags)
c401cc
 {
c401cc
     int fd, mode = 0;
c401cc
-    struct stat sb;
c401cc
     char *base = last_component(path);
c401cc
 
c401cc
-    if (lstat(path, &sb) < 0) {
c401cc
+    if (lstat(path, sb) < 0) {
c401cc
         virReportSystemError(errno,
c401cc
                              _("cannot stat file '%s'"),
c401cc
                              path);
c401cc
         return -1;
c401cc
     }
c401cc
 
c401cc
-    if (S_ISFIFO(sb.st_mode)) {
c401cc
+    if (S_ISFIFO(sb->st_mode)) {
c401cc
         VIR_WARN("ignoring FIFO '%s'", path);
c401cc
         return -2;
c401cc
-    } else if (S_ISSOCK(sb.st_mode)) {
c401cc
+    } else if (S_ISSOCK(sb->st_mode)) {
c401cc
         VIR_WARN("ignoring socket '%s'", path);
c401cc
         return -2;
c401cc
     }
c401cc
 
c401cc
     if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
c401cc
         if ((errno == ENOENT || errno == ELOOP) &&
c401cc
-            S_ISLNK(sb.st_mode)) {
c401cc
+            S_ISLNK(sb->st_mode)) {
c401cc
             VIR_WARN("ignoring dangling symlink '%s'", path);
c401cc
             return -2;
c401cc
         }
c401cc
@@ -1163,7 +1163,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
c401cc
         return -1;
c401cc
     }
c401cc
 
c401cc
-    if (fstat(fd, &sb) < 0) {
c401cc
+    if (fstat(fd, sb) < 0) {
c401cc
         virReportSystemError(errno,
c401cc
                              _("cannot stat file '%s'"),
c401cc
                              path);
c401cc
@@ -1171,13 +1171,13 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
c401cc
         return -1;
c401cc
     }
c401cc
 
c401cc
-    if (S_ISREG(sb.st_mode))
c401cc
+    if (S_ISREG(sb->st_mode))
c401cc
         mode = VIR_STORAGE_VOL_OPEN_REG;
c401cc
-    else if (S_ISCHR(sb.st_mode))
c401cc
+    else if (S_ISCHR(sb->st_mode))
c401cc
         mode = VIR_STORAGE_VOL_OPEN_CHAR;
c401cc
-    else if (S_ISBLK(sb.st_mode))
c401cc
+    else if (S_ISBLK(sb->st_mode))
c401cc
         mode = VIR_STORAGE_VOL_OPEN_BLOCK;
c401cc
-    else if (S_ISDIR(sb.st_mode)) {
c401cc
+    else if (S_ISDIR(sb->st_mode)) {
c401cc
         mode = VIR_STORAGE_VOL_OPEN_DIR;
c401cc
 
c401cc
         if (STREQ(base, ".") ||
c401cc
@@ -1206,7 +1206,8 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
c401cc
 
c401cc
 int virStorageBackendVolOpen(const char *path)
c401cc
 {
c401cc
-    return virStorageBackendVolOpenCheckMode(path,
c401cc
+    struct stat sb;
c401cc
+    return virStorageBackendVolOpenCheckMode(path, &sb,
c401cc
                                              VIR_STORAGE_VOL_OPEN_DEFAULT);
c401cc
 }
c401cc
 
c401cc
@@ -1217,14 +1218,16 @@ virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
c401cc
                                      unsigned int openflags)
c401cc
 {
c401cc
     int ret, fd;
c401cc
+    struct stat sb;
c401cc
 
c401cc
-    if ((ret = virStorageBackendVolOpenCheckMode(target->path,
c401cc
+    if ((ret = virStorageBackendVolOpenCheckMode(target->path, &sb,
c401cc
                                                  openflags)) < 0)
c401cc
         return ret;
c401cc
 
c401cc
     fd = ret;
c401cc
     ret = virStorageBackendUpdateVolTargetInfoFD(target,
c401cc
                                                  fd,
c401cc
+                                                 &sb,
c401cc
                                                  allocation,
c401cc
                                                  capacity);
c401cc
 
c401cc
@@ -1275,35 +1278,28 @@ int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
c401cc
 int
c401cc
 virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
c401cc
                                        int fd,
c401cc
+                                       struct stat *sb,
c401cc
                                        unsigned long long *allocation,
c401cc
                                        unsigned long long *capacity)
c401cc
 {
c401cc
-    struct stat sb;
c401cc
 #if WITH_SELINUX
c401cc
     security_context_t filecon = NULL;
c401cc
 #endif
c401cc
 
c401cc
-    if (fstat(fd, &sb) < 0) {
c401cc
-        virReportSystemError(errno,
c401cc
-                             _("cannot stat file '%s'"),
c401cc
-                             target->path);
c401cc
-        return -1;
c401cc
-    }
c401cc
-
c401cc
     if (allocation) {
c401cc
-        if (S_ISREG(sb.st_mode)) {
c401cc
+        if (S_ISREG(sb->st_mode)) {
c401cc
 #ifndef WIN32
c401cc
-            *allocation = (unsigned long long)sb.st_blocks *
c401cc
+            *allocation = (unsigned long long)sb->st_blocks *
c401cc
                           (unsigned long long)DEV_BSIZE;
c401cc
 #else
c401cc
-            *allocation = sb.st_size;
c401cc
+            *allocation = sb->st_size;
c401cc
 #endif
c401cc
             /* Regular files may be sparse, so logical size (capacity) is not same
c401cc
              * as actual allocation above
c401cc
              */
c401cc
             if (capacity)
c401cc
-                *capacity = sb.st_size;
c401cc
-        } else if (S_ISDIR(sb.st_mode)) {
c401cc
+                *capacity = sb->st_size;
c401cc
+        } else if (S_ISDIR(sb->st_mode)) {
c401cc
             *allocation = 0;
c401cc
             if (capacity)
c401cc
                 *capacity = 0;
c401cc
@@ -1328,16 +1324,16 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
c401cc
         }
c401cc
     }
c401cc
 
c401cc
-    target->perms.mode = sb.st_mode & S_IRWXUGO;
c401cc
-    target->perms.uid = sb.st_uid;
c401cc
-    target->perms.gid = sb.st_gid;
c401cc
+    target->perms.mode = sb->st_mode & S_IRWXUGO;
c401cc
+    target->perms.uid = sb->st_uid;
c401cc
+    target->perms.gid = sb->st_gid;
c401cc
 
c401cc
     if (!target->timestamps && VIR_ALLOC(target->timestamps) < 0)
c401cc
         return -1;
c401cc
-    target->timestamps->atime = get_stat_atime(&sb);
c401cc
-    target->timestamps->btime = get_stat_birthtime(&sb);
c401cc
-    target->timestamps->ctime = get_stat_ctime(&sb);
c401cc
-    target->timestamps->mtime = get_stat_mtime(&sb);
c401cc
+    target->timestamps->atime = get_stat_atime(sb);
c401cc
+    target->timestamps->btime = get_stat_birthtime(sb);
c401cc
+    target->timestamps->ctime = get_stat_ctime(sb);
c401cc
+    target->timestamps->mtime = get_stat_mtime(sb);
c401cc
 
c401cc
     VIR_FREE(target->perms.label);
c401cc
 
c401cc
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
c401cc
index 55e0fee..9e07dd8 100644
c401cc
--- a/src/storage/storage_backend.h
c401cc
+++ b/src/storage/storage_backend.h
c401cc
@@ -24,6 +24,8 @@
c401cc
 #ifndef __VIR_STORAGE_BACKEND_H__
c401cc
 # define __VIR_STORAGE_BACKEND_H__
c401cc
 
c401cc
+# include <sys/stat.h>
c401cc
+
c401cc
 # include "internal.h"
c401cc
 # include "storage_conf.h"
c401cc
 # include "vircommand.h"
c401cc
@@ -110,9 +112,10 @@ enum {
c401cc
                                        VIR_STORAGE_VOL_OPEN_CHAR     |\
c401cc
                                        VIR_STORAGE_VOL_OPEN_BLOCK)
c401cc
 
c401cc
-int virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
c401cc
-ATTRIBUTE_RETURN_CHECK
c401cc
-ATTRIBUTE_NONNULL(1);
c401cc
+int virStorageBackendVolOpenCheckMode(const char *path, struct stat *sb,
c401cc
+                                      unsigned int flags)
c401cc
+    ATTRIBUTE_RETURN_CHECK
c401cc
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c401cc
 
c401cc
 int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
c401cc
                                    int withCapacity);
c401cc
@@ -126,6 +129,7 @@ int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
c401cc
                                          unsigned int openflags);
c401cc
 int virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
c401cc
                                            int fd,
c401cc
+                                           struct stat *sb,
c401cc
                                            unsigned long long *allocation,
c401cc
                                            unsigned long long *capacity);
c401cc
 int
c401cc
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
c401cc
index 0374ea1..5d68232 100644
c401cc
--- a/src/storage/storage_backend_fs.c
c401cc
+++ b/src/storage/storage_backend_fs.c
c401cc
@@ -70,18 +70,19 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
c401cc
     int fd = -1;
c401cc
     int ret = -1;
c401cc
     virStorageFileMetadata *meta = NULL;
c401cc
+    struct stat sb;
c401cc
 
c401cc
     *backingStore = NULL;
c401cc
     *backingStoreFormat = VIR_STORAGE_FILE_AUTO;
c401cc
     if (encryption)
c401cc
         *encryption = NULL;
c401cc
 
c401cc
-    if ((ret = virStorageBackendVolOpenCheckMode(target->path,
c401cc
+    if ((ret = virStorageBackendVolOpenCheckMode(target->path, &sb,
c401cc
                                         VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0)
c401cc
         goto error; /* Take care to propagate ret, it is not always -1 */
c401cc
     fd = ret;
c401cc
 
c401cc
-    if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd,
c401cc
+    if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb,
c401cc
                                                       allocation,
c401cc
                                                       capacity)) < 0) {
c401cc
         goto error;
c401cc
diff --git a/src/storage/storage_backend_mpath.c b/src/storage/storage_backend_mpath.c
c401cc
index 8333f18..4191b7b 100644
c401cc
--- a/src/storage/storage_backend_mpath.c
c401cc
+++ b/src/storage/storage_backend_mpath.c
c401cc
@@ -1,7 +1,7 @@
c401cc
 /*
c401cc
  * storage_backend_mpath.c: storage backend for multipath handling
c401cc
  *
c401cc
- * Copyright (C) 2009-2011 Red Hat, Inc.
c401cc
+ * Copyright (C) 2009-2011, 2013 Red Hat, Inc.
c401cc
  * Copyright (C) 2009-2008 Dave Allan
c401cc
  *
c401cc
  * This library is free software; you can redistribute it and/or
c401cc
@@ -46,13 +46,16 @@ virStorageBackendMpathUpdateVolTargetInfo(virStorageVolTargetPtr target,
c401cc
 {
c401cc
     int ret = -1;
c401cc
     int fdret, fd = -1;
c401cc
+    struct stat sb;
c401cc
 
c401cc
-    if ((fdret = virStorageBackendVolOpen(target->path)) < 0)
c401cc
+    if ((fdret = virStorageBackendVolOpenCheckMode(target->path, &sb,
c401cc
+                                                   VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
c401cc
         goto out;
c401cc
     fd = fdret;
c401cc
 
c401cc
     if (virStorageBackendUpdateVolTargetInfoFD(target,
c401cc
                                                fd,
c401cc
+                                               &sb,
c401cc
                                                allocation,
c401cc
                                                capacity) < 0)
c401cc
         goto out;
c401cc
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
c401cc
index 26baf4a..9a2b423 100644
c401cc
--- a/src/storage/storage_backend_scsi.c
c401cc
+++ b/src/storage/storage_backend_scsi.c
c401cc
@@ -1,7 +1,7 @@
c401cc
 /*
c401cc
  * storage_backend_scsi.c: storage backend for SCSI handling
c401cc
  *
c401cc
- * Copyright (C) 2007-2008 Red Hat, Inc.
c401cc
+ * Copyright (C) 2007-2008, 2013 Red Hat, Inc.
c401cc
  * Copyright (C) 2007-2008 Daniel P. Berrange
c401cc
  *
c401cc
  * This library is free software; you can redistribute it and/or
c401cc
@@ -138,13 +138,16 @@ virStorageBackendSCSIUpdateVolTargetInfo(virStorageVolTargetPtr target,
c401cc
 {
c401cc
     int fdret, fd = -1;
c401cc
     int ret = -1;
c401cc
+    struct stat sb;
c401cc
 
c401cc
-    if ((fdret = virStorageBackendVolOpen(target->path)) < 0)
c401cc
+    if ((fdret = virStorageBackendVolOpenCheckMode(target->path, &sb,
c401cc
+                                                   VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
c401cc
         goto cleanup;
c401cc
     fd = fdret;
c401cc
 
c401cc
     if (virStorageBackendUpdateVolTargetInfoFD(target,
c401cc
                                                fd,
c401cc
+                                               &sb,
c401cc
                                                allocation,
c401cc
                                                capacity) < 0)
c401cc
         goto cleanup;
c401cc
-- 
c401cc
1.9.0
c401cc