[PATCH v3] mountmgr.sys: Implement StorageDeviceSeekPenaltyProperty

David Koolhoven david at koolhoven-home.net
Tue Apr 27 16:31:30 CDT 2021


Allows programs to query if disk has a seek penalty.

Signed-off-by: David Koolhoven <david at koolhoven-home.net>
---
v3: Linux side/sysfs logic is contained file.
---
 dlls/mountmgr.sys/Makefile.in                |   1 +
 dlls/mountmgr.sys/device.c                   |  24 +++
 dlls/mountmgr.sys/unix/device_seek_penalty.c | 145 +++++++++++++++++++
 include/ntddstor.h                           |   9 +-
 4 files changed, 178 insertions(+), 1 deletion(-)
 create mode 100644 dlls/mountmgr.sys/unix/device_seek_penalty.c

diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in
index 83204e66504..61b462ddd7b 100644
--- a/dlls/mountmgr.sys/Makefile.in
+++ b/dlls/mountmgr.sys/Makefile.in
@@ -7,6 +7,7 @@ EXTRALIBS = $(DISKARBITRATION_LIBS) $(SYSTEMCONFIGURATION_LIBS) $(CORESERVICES_L
 
 C_SRCS = \
 	dbus.c \
+	unix/device_seek_penalty.c \
 	device.c \
 	diskarb.c \
 	mountmgr.c
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c
index 04e8fe3c0f5..90c73b13139 100644
--- a/dlls/mountmgr.sys/device.c
+++ b/dlls/mountmgr.sys/device.c
@@ -1894,6 +1894,30 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp )
 
         break;
     }
+    case StorageDeviceSeekPenaltyProperty:
+    {
+        DEVICE_SEEK_PENALTY_DESCRIPTOR *descriptor;
+	int ret;
+
+        memset( irp->AssociatedIrp.SystemBuffer, 0, irpsp->Parameters.DeviceIoControl.OutputBufferLength );
+        descriptor = irp->AssociatedIrp.SystemBuffer;
+        descriptor->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
+        descriptor->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
+        irp->IoStatus.Information = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR);
+
+        ret = device_seek_penalty(device->unix_mount);
+        if (ret < 0) {
+                FIXME( "Unsupported property StorageDeviceSeekPenalty\n" );
+                status = STATUS_NOT_SUPPORTED;
+        } else if (ret == 0) {
+		descriptor->IncursSeekPenalty = FALSE;
+		status = STATUS_SUCCESS;
+        } else if (ret == 1) {
+		descriptor->IncursSeekPenalty = TRUE;
+		status = STATUS_SUCCESS;
+	}
+        break;
+    }
     default:
         FIXME( "Unsupported property %#x\n", query->PropertyId );
         status = STATUS_NOT_SUPPORTED;
diff --git a/dlls/mountmgr.sys/unix/device_seek_penalty.c b/dlls/mountmgr.sys/unix/device_seek_penalty.c
new file mode 100644
index 00000000000..eefb4d67e65
--- /dev/null
+++ b/dlls/mountmgr.sys/unix/device_seek_penalty.c
@@ -0,0 +1,145 @@
+/*
+ * System information APIs
+ *
+ * Copyright 1996-1998 Marcus Meissner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#ifdef linux
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#define NONAMELESSUNION
+#include "ntstatus.h"
+#include "mountmgr.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#endif
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
+
+int device_seek_penalty (char *unix_mount)
+{
+#ifdef linux
+    FILE *fp;
+    char isrotapathstr[260];
+    char evpath[260];
+    char ueventbufstr[260];
+    char isrotastrbuf[2];
+    char *fgetsret = NULL;
+    int  ret = 0;
+    char *rptr = NULL;
+    char *sptr = NULL;
+    char *devstr_edited = NULL;
+    char  mountpath[260];
+    char *part_dev = NULL;
+    int c = 0;
+    struct stat statbuf;
+    int seekpen;
+
+    const char *home = getenv( "HOME" );
+    const char *prefix = getenv( "WINEPREFIX" );
+    size_t len = (prefix ? strlen(prefix) : strlen(home) + strlen("/.wine")) + sizeof("/dosdevices/com256");
+    char *path = HeapAlloc( GetProcessHeap(), 0, len );
+
+    if (path)
+    {
+        if (prefix) strcpy( path, prefix );
+        else
+        {
+            strcpy( path, home );
+            strcat( path, "/.wine" );
+        }
+        strcat( path, "/dosdevices/" );
+    }
+
+    if (!unix_mount) {
+        return -1;
+    }
+
+    snprintf (mountpath, 260, "%s%s", path, unix_mount);
+    ret = stat (mountpath, &statbuf);
+    if (ret == -1) {
+        return -1;
+    }
+    HeapFree( GetProcessHeap(), 0, path );
+    sprintf (evpath, "/sys/dev/block/%d:%d/uevent", major(statbuf.st_dev), minor(statbuf.st_dev));
+    fp = fopen(evpath, "r");
+    if (!fp) {
+        return -1;
+    }
+    while ((rptr = fgets (ueventbufstr, 260, fp))) {
+        sptr = strstr (rptr, "DEVNAME=");
+        if (sptr) {
+            sptr += strlen ("DEVNAME=");
+            break;
+        }
+    }
+    fclose (fp);
+    devstr_edited = sptr;
+    if (!devstr_edited) {
+        return -1;
+    }
+    /* Find first character after forwardslash '/' */
+    part_dev = strrchr (devstr_edited, '/');
+    if (!part_dev || (part_dev == devstr_edited)) part_dev = devstr_edited;
+    else part_dev++;
+    /* Trim off trailing digits and whitespace */
+    c = strlen (devstr_edited);
+    c--;
+    while ((devstr_edited[c] >= '0' && devstr_edited[c] <= '9')
+        || (devstr_edited[c] == '\n' || devstr_edited[c] == '\r'))
+        devstr_edited[c--] = '\0';
+
+    ret = snprintf (isrotapathstr, 260, "/sys/block/%s/queue/rotational", part_dev);
+    if (ret < 1 || ret == 260) {
+        return -1;
+    }
+
+    fp = fopen(isrotapathstr, "r");
+    if (!fp) {
+        return -1;
+    }
+
+    fgetsret = fgets(isrotastrbuf, 2, fp);
+    if (!fgetsret) {
+        return -1;
+    }
+
+    fclose (fp);
+
+    if (isrotastrbuf[0] == '1') {
+        seekpen = 1;
+    } else if (isrotastrbuf[0] == '0') {
+        seekpen = 0;
+    } else {
+        return -1;
+    }
+
+    return seekpen;
+#else
+    return -1;
+#endif
+}
diff --git a/include/ntddstor.h b/include/ntddstor.h
index b8c4bb73b0d..836def413fe 100644
--- a/include/ntddstor.h
+++ b/include/ntddstor.h
@@ -214,7 +214,8 @@ typedef enum _STORAGE_QUERY_TYPE {
 
 typedef enum _STORAGE_PROPERTY_ID {
     StorageDeviceProperty = 0,
-    StorageAdapterProperty
+    StorageAdapterProperty = 1,
+    StorageDeviceSeekPenaltyProperty = 7,
 } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
 
 typedef struct _STORAGE_PROPERTY_QUERY {
@@ -272,6 +273,12 @@ typedef struct _STORAGE_ADAPTER_DESCRIPTOR {
     USHORT                      BusMinorVersion;
 } STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR;
 
+typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR {
+    ULONG                       Version;
+    ULONG                       Size;
+    BOOLEAN                     IncursSeekPenalty;
+} DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR;
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.19.1




More information about the wine-devel mailing list