Quantcast
Channel: Jose Barreto's Blog
Viewing all 143 articles
Browse latest View live

Updated Links on Windows Server 2012 File Server and SMB 3.0

$
0
0

In this post, I'm providing a reference to the most relevant content related to Windows Server 2012 that is related to the File Server, the SMB 3.0 features and its associated scenarios like Hyper-V over SMB and SQL Server over SMB. It's obviously not a complete reference (there are new blog posts every day), but hopefully this is a useful collection of links for Windows Server 2012 users.

Summaries of SMB 3.0 features in Windows Server 2012:

Step-by-step instructions:

Articles on File Storage for Application Servers (Hyper-V over SMB, SQL Server over SMB):

Articles on SMB Transparent Failover and SMB Scale-Out:

Articles on SMB Direct (SMB over RDMA) and SMB Multichannel:

Articles on Failover Clustering related to File Server Clusters:

Articles on other SMB 3.0 features and capabilities:

Windows Server File Server Tips and Questions:

Private Cloud Solution Architecture:

TechNet Radio (includes Video) with Bob Hunt and Jose Barreto:

Case Studies

Knowledge Base articles (Support KBs) related to Windows Server 2012 SMB 3.0:

Protocol Documentation:

Older posts and videos:

-------

Change tracking:

  • 04/24/2012: Original post
  • 05/01/2012: Update: Added links to two SNW Spring 2012 presentation
  • 05/03/2012: Update: Added links to protocol documentation, blog post on SMB Encryption and private could blog post 
  • 05/18/2012: Update: Added links to SDC presentations, plus blogs on basics of SMB PowerShell and SMB PowerShell
  • 06/13/2012: Update: Added 3 new blog post, one new KB article, one new video link
  • 08/02/2012: Update: Additional blog posts and links to TechEd recordings
  • 08/26/2012: Update: Two additional blog posts
  • 11/27/2012: Update: Added 10 file server tips, SNW Fall 2012 presentations, TechNet Radio links. Moved older posts down.
  • 01/03/2013: Update: Added 1 TechNet Radio link, 1 white paper, 1 KB article. Added numbers of KB articles next to links.
  • 02/02/2013: Update: Added links to a few new blog posts and white papers
  • 03/11/2013: Update: Added links to 2 new TechNet Radio shows, 5 new blog posts, separate group for step-by-steps
  • 04/11/2013: Update: Added 1 link to TechNet Radio show, 5 new blog posts, 3 new KB articles
  • 05/05/2013: Update: Added 1 MMS link, 1 new TechNet article, 1 new tip, new section on case studies with 3 entries

SNIA’s Storage Developer Conference 2013 is just a few weeks away

$
0
0

The Storage Networking Industry Association (SNIA) is hosting the 10th Storage Developer Conference (SDC) in the Hyatt Regency in beautiful Santa Clara, CA (Silicon Valley) on the week of September 16th. As usual, Microsoft is one of the underwriters of the SNIA SMB2/SMB3 PlugFest, which is co-located with the SDC event.

For developers working with storage-related technologies, this event gathers a unique crowd and includes a rich agenda that you can find at http://www.storagedeveloper.org. Many of the key industry players are represented and this year’s agenda lists presentations from EMC, Fujitsu, Google, Hortonworks, HP, Go Daddy, Huawei, IBM, Intel, Microsoft, NEC, NetApp, Netflix, Oracle, Red Hat, Samba Team, Samsung, Spectra Logic, SwitfTest, Tata and many others.

It’s always worth reminding you that the SDC presentations are usually delivered to developers by the actual product development teams and frequently the actual developer of the technology is either delivering the presentation or is in the room to take questions. That kind of deep insight is not common in every conference out there.

Presentations by Microsoft this year include:

TitlePresenters
Advancements in Windows File SystemsNeal Christiansen, Principal Development Lead, Microsoft
LRC Erasure Coding in Windows Storage SpacesCheng Huang, Researcher, Microsoft Research
SMB3 UpdateDavid Kruse, Development Lead, Microsoft
Cluster Shared VolumesVladimir Petter, Principal Software Design Engineer, Microsoft
Tunneling SCSI over SMB: Shared VHDX files for Guest Clustering in Windows Server 2012 R2Jose Barreto, Principal Program Manager, Microsoft
Matt Kurjanowicz, Software Development Engineer, Microsoft
Windows Azure Storage - Speed and Scale in the CloudJoe Giardino, Senior Development Lead, Microsoft
SMB Direct updateGreg Kramer, Sr. Software Engineer, Microsoft
Scaled RDMA Performance & Storage Design with Windows Server SMB 3.0Dan Lovinger, Principal Software Design Engineer, Microsoft
SPEC SFS Benchmark - The Next GenerationSpencer Shepler, Architect, Microsoft
Data Deduplication as a Platform for Virtualization and High Scale StorageAdi Oltean, Principal Software Design Engineer, Microsoft
Sudipta Sengupta, Sr. Researcher, Microsoft

For a taste of what SDC presentations look like, make sure to visit the site for last year’s event, where you can find the downloadable PDF files for most and video recordings for some. You can find them at http://www.snia.org/events/storage-developer2012/presentations12.

Registration for SDC 2013 is open at http://www.storagedeveloper.org and you should definitely plan to attend. If you are registered, leave a comment and let’s plan to meet when we get there!

What’s new in SMB PowerShell in Windows Server 2012 R2

$
0
0

Windows Server 2012 R2 introduced a new version of SMB. Technically it’s SMB 3.02, but we continue to call it just SMB3. The main changes are described at http://technet.microsoft.com/en-us/library/hh831474.aspx. With this new release, we made a few changes in SMB PowerShell to support the new scenarios and features. This includes a few new cmdlets and some changes to existing cmdlets, with extra care not break any of your existing scripts. This blog post outlines 7 set of changes related to SMB PowerShell in Windows Server 2012 R2.

 

1) Simpler setting of ACL for the folder behind a share

 

In Windows Server 2012, the SMB share has a property that facilitates applying the share ACL to the file system folder used by the share. Here’s the syntax for a share named Share1:

  • (Get-SmbShare –Name Share1 ).PresetPathACL | Set-Acl

 

In Windows Server 2012 R2, we have improved this scenario by providing a proper cmdlet to apply the share ACL to the file system used by the share. Here’s the new syntax for the same share:

  • Set-SmbPathAcl –ShareName Share1

 

Note1 : The Windows Server 2012 syntax continues to work with Windows Server 2012 R2, but the new syntax is much simpler and therefore recommended.

 

Note 2: There is known issue with Windows Server 2012 R2 Preview that causes this new cmdlet to fail when using non-Unicode languages. As a workaround, you can use the old syntax.

 

2) Scale-Out Rebalancing (per-share redirection)

 

Per-share redirection is the new default behavior for the new SMB Clients (Windows 8.1 or Windows Server 2012 R2), when connecting to a Scale-Out clusters that use a storage system that does not support Direct I/O from all nodes, if running Windows Server 2012 R2. The common scenario here is a Scale-Out File Server backed by Mirrored Storage Spaces.

 

Here are the changes in SMB PowerShell to support SMB Scale-Out per-share redirection:

  • New “Redirected” Boolean property to Get-SmbConnection to indicate that per-share redirection is being used.
  • Get-SmbWitnessClient now includes a “ShareName” property, since witness can track connections per share, not only per server. 
  • Get-SmbWitnessClient now includes a “Flags” property, which will show “Share” when doing per-share redirection

 

3) Other SMB Witness Changes

 

While the overall functionality of the SMB Witness is largely unchanged in Windows Server 2012 R2 (aside from per-share redirection), we have put some effort in improving the SMB PowerShell cmdlets associated with it. Here are the changes:

  • The Move-SmbWitnessClient cmdlet can be referred to now simply as Move-SmbClient, This is simply a new alias that better describes what the cmdlet actually does.
  • The default view for Get-SmbWitnessClient was improved. Here’s the new list of items shown: 


Client Computer   Witness Node  File Server   Network Name  Share Name  Client State    
Name              Name             Node Name
----------------- ------------- ------------- ------------  ----------  ------------    
JOSE-V            JOSE-A1       JOSE-A2       JOSE-F        VMS4        RequestedNoti...
JOSE-V            JOSE-A1       JOSE-A2       JOSE-F        VMS3        RequestedNoti...
JOSE-V            JOSE-A1       JOSE-A3       JOSE-F        VMS1        RequestedNoti...
JOSE-V            JOSE-A1       JOSE-A3       JOSE-F        VMS2        RequestedNoti...
JOSE-V            JOSE-A2       JOSE-A1       JOSE-F        VMS6        RequestedNoti...
JOSE-V            JOSE-A2       JOSE-A1       JOSE-F        VMS5        RequestedNoti...

 

  • There is a new “NetworkName” parameter in Move-SmbClient.  If a NetworkName is specified, then only those will be moved. 

Windows Server 2012 syntax for Move-SmbWitnessClient:

    • Move-SmbWitnessClient -ClientName X -DestinationNode Y

Windows Server 2012 R2 syntax:

    • Move-SmbClient -ClientName X -DestinationNode Y [ -NetworkName Z ]

 

Note 1: If the –NetworkName is omitted in the Move-SmbClient cmdlet, all client connections will be moved to the destination.

 

Note 2: When using per-share redirection, the SMB client will always move to the file server node that owns the volume behind the file share. Using Move-SmbClient (or Move-SmbWitnessClient) in that situation has no effect.

 

4) SMB Bandwidth Limits

 

Starting with Windows Server 2012 R2, administrators can set a bandwidth limit for one or more categories by using simple PowerShell cmdlets. They can also query the limit for each category.  

 

There are 3 categories of traffic that can be limited:

  • VirtualMachine: Hyper-V over SMB traffic. This limit can only be applied on Hyper-V hosts. 
  • LiveMigration: Hyper-V Live Migration over SMB traffic. This limit can only be applied on Hyper-V hosts. 
  • Default: All other types of SMB traffic. This limit can be applied on any SMB client.

 

A category limit is an absolute value expressed in bytes per second.  For example, a category limit of 500MB means the total throughput for this category should not exceed 500 megabytes per second.

 

The PowerShell cmdlets used to manage SMB Bandwidth Limits are:

  • Get-SmbBandwidthLimit [ –Category {Default/VirtualMachine/LiveMigration} ]
  • Set-SmbBandwidthLimit –Category {Default/VirtualMachine/LiveMigration} –BytesPerSecond x 
  • Remove-SmbBandwidthLimit –Category {Default/ VirtualMachine/LiveMigration}

 

Note 1: Before you can use Bandwidth Limits, the feature needs to be enabled. For that, you should use:

  • Add-WindowsFeature FS-SMBBW

 

Note 2: A new SMB Performance counter set with an instance per category becomes available after you install the feature.  The performance counters in for this set will use the same counters used today for the SMB Client Shares counter.

 

Note 3: PowerShell allows us to specify units like KB, MB, GB after the number of bytes when specifying the BytesPerSecond parameter.

 

Note 4: The Set-SmbBandwidthLimit cmdlet won’t accept a BytesPerSecond parameter smaller than 1MB (1048576).

 

5) SMB Multi-instance

 

SMB Multi-instance is a new feature in Windows Server 2012 R2 that separates regular SMB traffic from CSV-related inter-node SMB traffic in distinct  SMB instances. This is designed to improve isolation between the two types of traffic in improve the reliability of the SMB servers. Information related to this new CSV-only instance in Windows Server 2012 R2 is hidden in all PowerShell cmdlets.

 

However, there are the changes in SMB PowerShell so an Administrator can view information related to the hidden CSV instance:

  • The –IncludeHidden option in Get-SmbConnection and Get-SmbMultichannelConnection will show the connections associated with the hidden CSV instance. 
  • There is now an InstanceName property in the full output of Get-SmbConnection, Get-SmbMultichannelConnection, Get-SmbSession and Get-SmbOpenFile. It shows either “Default” or “CSV” (only shows if using the –IncludeHidden option).

 

Note: There is really little use in inspecting the information on the hidden CSV instance, except if you’re troubleshooting CSV inter-node communications.

 

6) SMB Delegation

 

When you configure Hyper-V over SMB and you manage your Hyper-V hosts remotely using Hyper-V Manager, you will might run into access denied messages. This is because you’re using your credentials from the remote machine running Hyper-V Manager in the Hyper-V host to access a third machine (the file server). This is what we call a “double-hop”, and it’s not allowed by default for security reasons.The main problem with the scenario is that an intruder that compromises one computer in your environment could then connect to other systems in your environments without the need to provide a username and password. One way to work around this issue is to connect directly to the Hyper-V host and providing your credentials at that time, avoiding the double-hop.

 

You can also address this by configuring Constrained Delegation for SMB shares, which is a process that involves changing properties in Active Directory. The security risk is reduced here because a potential intruder double-hop would be limited to that specific use case (using SMB shares on the specified servers). The constrained delegation process was greatly simplified in Windows Server 2012 when the the Active Directory team introduced resource-based Kerberos constrained delegation, as explained at http://technet.microsoft.com/library/hh831747.aspx. However, even with  this new resource-based constrained delegation, there are still quite a few steps to enable it.

 

For Hyper-V over SMB in Windows Server 2012, we provided TechNet and blog-based guidance on how to automate constrained delegation. In Windows Server 2012 R2, SMB has a new set of cmdlets to simplify the configuration of resource-based constrained Delegation in SMB scenarios. Here are the new cmdlets introduced:

  • Get-SmbDelegation –SmbServer X
  • Enable-SmbDelegation –SmbServer X –SmbClient Y 
  • Disable-SmbDelegation –SmbServer X [–SmbClient Y] [-Force]

 

Note 1: For the Disable-SmbDelegation cmdlet, if no client is specified, delegation will be removed for all clients.

 

Note 2: These 3 new SMB cmdlets do rely on Active Directory PowerShell to perform their actions. For this reason, you need to install the Active Directory cmdlets before using the SMB delegation cmdlets. To install the Active Directory cmdlets, use:

  • Install-WindowsFeature RSAT-AD-PowerShell

 

Note 3: Because these cmdlets only work with the new resource-based delegation, the Active Directory forest must be in “Windows Server 2012” functional level. To check the Active Directory Forest Functional level, use:

  • Get-ADForest

 

Note 4: Virtual Machine Manager uses a different method to remote into the Hyper-V host. For VMM, constrained delegation is not required for management of Hyper-V of SMB.

 

7) Disable SMB1

 

SMB1 now can be completely disabled, so that the components are not even loaded. For scenarios where SMB1 is not required, this means less resource utilization, less need for patching and improved security.

 

To disable SMB1 completely, use the following PowerShell cmdlet:

  • Remove-WindowsFeature FS-SMB1

 

You can re-enable it by using:

  • Add-WindowsFeature FS-SMB1

 

Note 1: A reboot is required after this feature is enabled or disabled.

 

Note 2: For information worker scenarios, if you have Windows XP clients, you absolutely still need SMB1, since that is the only SMB version supported by Windows XP. Windows Vista and Windows 7 do not need SMB1 since they support SMB2. Windows 8 and Windows 8.1 do not need SMB1, since they support both SMB2 and SMB3.

 

Note 3: For classic server scenarios, if you have Windows Server 2003 or Windows Server 2003 R2 servers, you absolutely still need SMB1, since that is the only SMB version supported by them. Windows Server 2008 and Windows Server 2008 R2 do not need SMB1 since they support SMB2. Windows Server 2012 and Windows Server 2012 R2 do not need SMB1, since they support both SMB2 and SMB3.

 

Windows Server 2012 R2: Which version of the SMB protocol (SMB 1.0, SMB 2.0, SMB 2.1, SMB 3.0 or SMB 3.02) are you using?

$
0
0

Note: This blog post is a Windows Server 2012 R2 update on a previous version focused on Windows Server 2012.

 

1. Introduction

With the release of Windows 8.1 and Windows Server 2012 R2, I am frequently asked about how older versions of Windows will behave when connecting to or from these new versions. Upgrading to a new version of SMB is something that happened a few times over the years and we established a process in the protocol itself by which clients and servers negotiate the highest version that both support.

 

2. Versions

There are several different versions of SMB used by Windows operating systems:

  • CIFS – The ancient version of SMB that was part of Microsoft Windows NT 4.0 in 1996. SMB1 supersedes this version.
  • SMB 1.0 (or SMB1) – The version used in Windows 2000, Windows XP, Windows Server 2003 and Windows Server 2003 R2
  • SMB 2.0 (or SMB2) – The version used in Windows Vista (SP1 or later) and Windows Server 2008
  • SMB 2.1 (or SMB2.1) – The version used in Windows 7 and Windows Server 2008 R2
  • SMB 3.0 (or SMB3) – The version used in Windows 8 and Windows Server 2012
  • SMB 3.02 (or SMB3) – The version used in Windows 8.1 and Windows Server 2012 R2

Windows NT is no longer supported, so CIFS is definitely out. Windows Server 2003 R2 with a current service pack is under Extended Support, so SMB1 is still around for a little while. SMB 2.x in Windows Server 2008 and Windows Server 2008 R2 are under Mainstream Support until 2015. You can find the most current information on the support lifecycle page for Windows Server. The information is subject to the Microsoft Policy Disclaimer and Change Notice.  You can use the support pages to also find support policy information for Windows XP, Windows Vista, Windows 7 and Windows 8.

In Windows 8.1 and Windows Server 2012 R2, we introduced the option to completely disable CIFS/SMB1 support, including the actual removal of the related binaries. While this is not the default configuration, we recommend disabling this older version of the protocol in scenarios where it’s not useful, like Hyper-V over SMB. You can find details about this new option in item 7 of this blog post: What’s new in SMB PowerShell in Windows Server 2012 R2.

 

3. Negotiated Versions

Here’s a table to help you understand what version you will end up using, depending on what Windows version is running as the SMB client and what version of Windows is running as the SMB server:

OSWindows 8.1 
WS 2012 R2
Windows 8 
WS 2012
Windows 7 
WS 2008 R2
Windows Vista 
WS 2008
Previous
versions
Windows 8.1
WS 2012 R2
SMB 3.02SMB 3.0SMB 2.1SMB 2.0SMB 1.0
Windows 8
WS 2012
SMB 3.0SMB 3.0SMB 2.1SMB 2.0SMB 1.0
Windows 7
WS 2008 R2
SMB 2.1SMB 2.1SMB 2.1SMB 2.0SMB 1.0
Windows Vista
WS 2008
SMB 2.0SMB 2.0SMB 2.0SMB 2.0SMB 1.0
Previous
versions
SMB 1.0SMB 1.0SMB 1.0SMB 1.0SMB 1.0

* WS = Windows Server

  

4. Using PowerShell to check the SMB version

In Windows 8 or Windows Server 2012, there is a new PowerShell cmdlet that can easily tell you what version of SMB the client has negotiated with the File Server. You simply access a remote file server (or create a new mapping to it) and use Get-SmbConnection. Here’s an example:

PS C:\> Get-SmbConnection
 

ServerName   ShareName  UserName            Credential          Dialect   NumOpens
----------   ---------  --------            ----------          -------   --------
FileServer1  IPC$       DomainName\UserN... DomainName.Testi... 3.00      0
FileServer1  FileShare  DomainName\UserN... DomainName.Testi... 3.00      14
FileServ2    FS2        DomainName\UserN... DomainName.Testi... 3.02      3 
VNX3         Share1     DomainName\UserN... DomainName.Testi... 3.00      6
Filer2       Library    DomainName\UserN... DomainName.Testi... 3.00      8

DomainCtrl1  netlogon   DomainName\Compu... DomainName.Testi... 2.10      1

In the example above, a server called “FileServer1” was able to negotiate up to version 3.0. FileServ2 can use version 3.02. That means that both the client and the server support the latest version of the SMB protocol. You can also see that another server called “DomainCtrl1” was only able to negotiate up to version 2.1. You can probably guess that it’s a domain controller running Windows Server 2008 R2. Some of the servers on the list are not running Windows, showing the dialect that these non-Windows SMB implementations negotiated with this specific Windows client.

If you just want to find the version of SMB running on your own computer, you can use a loopback share combined with the Get-SmbConnection cmdlet. Here’s an example:

PS C:\> dir \\localhost\c$
 
Directory: \\localhost\c$

 
Mode                LastWriteTime     Length Name

----                -------------     ------ ----
d----         5/19/2012   1:54 AM            PerfLogs
d-r--          6/1/2012  11:58 PM            Program Files
d-r--          6/1/2012  11:58 PM            Program Files (x86)
d-r--         5/24/2012   3:56 PM            Users
d----          6/5/2012   3:00 PM            Windows
 
PS C:\> Get-SmbConnection -ServerName localhost
 
ServerName  ShareName  UserName            Credential          Dialect  NumOpens
----------  ---------  --------            ----------          -------  --------
localhost   c$         DomainName\UserN... DomainName.Testi... 3.02     0

 

You have about 10 seconds after you issue the “dir” command to run the “Get-SmbConnection” cmdlet. The SMB client will tear down the connections if there is no activity between the client and the server. It might help to know that you can use the alias “gsmbc” instead of the full cmdlet name.

 

5. Features and Capabilities

Here’s a very short summary of what changed with each version of SMB:

  • From SMB 1.0 to SMB 2.0 - The first major redesign of SMB
    • Increased file sharing scalability
    • Improved performance
      • Request compounding
      • Asynchronous operations
      • Larger reads/writes
    • More secure and robust
      • Small command set
      • Signing now uses HMAC SHA-256 instead of MD5
      • SMB2 durability
  • From SMB 2.0 to SMB 2.1
    • File leasing improvements
    • Large MTU support
    • BranchCache
  • From SMB 2.1 to SMB 3.0
    • Availability
      • SMB Transparent Failover
      • SMB Witness
      • SMB Multichannel
    • Performance
      • SMB Scale-Out
      • SMB Direct (SMB 3.0 over RDMA)
      • SMB Multichannel
      • Directory Leasing
      • BranchCache V2
    • Backup
      • VSS for Remote File Shares
    • Security
      • SMB Encryption using AES-CCM (Optional)
      • Signing now uses AES-CMAC
    • Management
      • SMB PowerShell
      • Improved Performance Counters
      • Improved Eventing
  • From SMB 3.0 to SMB 3.02
    • Automatic rebalancing of Scale-Out File Server clients
    • Improved performance of SMB Direct (SMB over RDMA)
    • Support for multiple SMB instances on a Scale-Out File Server

You can get additional details on the SMB 2.0 improvements listed above at
http://blogs.technet.com/b/josebda/archive/2008/12/09/smb2-a-complete-redesign-of-the-main-remote-file-protocol-for-windows.aspx

You can get additional details on the SMB 3.0 improvements listed above at
http://blogs.technet.com/b/josebda/archive/2012/05/03/updated-links-on-windows-server-2012-file-server-and-smb-3-0.aspx

You can get additional details on the SMB 3.02 improvements in Windows Server 2012 R2 at
http://technet.microsoft.com/en-us/library/hh831474.aspx

 

6. Recommendation

We strongly encourage you to update to the latest version of SMB, which will give you the most scalability, the best performance, the highest availability and the most secure SMB implementation.

Keep in mind that Windows Server 2012 Hyper-V and Windows Server 2012 R2 Hyper-V only support SMB 3.0 for remote file storage. This is due mainly to the availability features (SMB Transparent Failover, SMB Witness and SMB Multichannel), which did not exist in previous versions of SMB. The additional scalability and performance is also very welcome in this virtualization scenario. The Hyper-V Best Practices Analyzer (BPA) will warn you if an older version is detected.

 

7. Conclusion

We’re excited about SMB3, but we are also always concerned about keeping as much backwards compatibility as possible. Both SMB 3.0 and SMB 3.02 bring several key new capabilities and we encourage you to learn more about them. We hope you will be convinced to start planning your upgrades as early as possible.

 


Note 1: Protocol Documentation

If you consider yourself an SMB geek and you actually want to understand the SMB NEGOTIATE command in greater detail, you can read the [MS-SMB2-Preview] protocol documentation (which covers SMB 2.0, 2.1, 3.0 and 3.02), currently available from http://msdn.microsoft.com/en-us/library/ee941641.aspx. In regards to protocol version negotiation, you should pay attention to the following sections of the document:

  • 1.7: Versioning and Capability Negotiation
  • 2.2.3: SMB2 Negotiate Request
  • 2.2.4: SMB2 Negotiate Response

Section 1.7 includes this nice state diagram describing the inner workings of protocol negotiation:

clip_image001

 

Note 2: Third-party implementations

There are several implementations of the SMB protocol from someone other than Microsoft. If you use one of those implementations of SMB, you should ask whoever is providing the implementation which version of SMB they implement for each version of their product. Here are a few of these implementations of SMB:

Please note that is not a complete list of implementations and the list is bound to become obsolete the minute I post it. Please refer to the specific implementers for up-to-date information on their specific implementations and which version and optional portions of the protocol they offer.

Networking configurations for Hyper-V over SMB in Windows Server 2012 and Windows Server 2012 R2

$
0
0

One of the questions regarding Hyper-V over SMB that I get the most relates to how the network should be configured. Networking is key to several aspects of the scenario, including performance, availability and scalability.

The main challenge is to provide a fault-tolerant and high-performance network for the two clusters typically involved: the Hyper-V cluster (also referred to as the Compute Cluster) and the Scale-out File Server Cluster (also referred to as the Storage Cluster).

Not too long ago, the typical configuration for virtualization deployments would call for up to 6 distinct networks for these two clusters:

  • Client (traffic between the outside and VMs running in the Compute Cluster)
  • Storage (main communications between the Compute and Storage clusters)
  • Cluster (communication between nodes in both clusters, including heartbeat)
  • Migration (used for moving VMs between nodes in the Compute Cluster)
  • Replication (used by Hyper-V replica to send changes to another site)
  • Management (used to configuring and monitoring the systems, typically also including DC and DNS traffic)

These days, it’s common to consolidate these different types of traffic, with the proper fault tolerance and Quality of Service (QoS) guarantees.

There are certainly many different ways to configure the network for your Hyper-V over SMB, but this blog post will focus on two of them:

  • A basic fault-tolerant solution using just two physical network ports per node
  • A high-end solution using RDMA networking for the highest throughput, highest density, lowest latency and low CPU utilization.

Both configurations presented here work with Windows Server 2012 and Windows Server 2012 R2, the two versions of Windows Server that support the Hyper-V over SMB scenario.

 

Configuration 1 – Basic fault-tolerant Hyper-V over SMB configuration with two non-RDMA port

 

The solution below using two network ports for each node of both the Compute Cluster and the Storage Cluster. NIC teaming is the main technology used for fault tolerance and load balancing.

image

Configuration 1: click on diagram to see a larger picture

Notes:

  • A single dual-port network adapter per host can be used. Network failures are usually related to cables and switches, not the NIC itself. It the NIC does fail, failover clustering on the Hyper-V or Storage side would kick in. Two network adapters each with one port is also an option.
  • The 2 VNICs on the Hyper-V host are used to provide additional throughput for the SMB client via SMB Multichannel, since the VNIC does not support RSS (Receive Side Scaling, which helps spread the CPU load of networking activity across multiple cores). Depending on configuration, increasing it up to 4 VNICs per Hyper-V host might be beneficial to increase throughput.
  • You can use additional VNICs that are dedicated for other kinds of traffic like migration, replication, cluster and management. In that case, you can optionally configure SMB Multichannel constraints to limit the SMB client to a specific subset of the VNICs. More details can be found in item 7 of the following article: The basics of SMB Multichannel, a feature of Windows Server 2012 and SMB 3.0
  • If RDMA NICs are used in this configuration, their RDMA capability will not be leveraged, since the physical port capabilities are hidden behind NIC teaming and the virtual switch.
  • Network QoS should be used to tame each individual type of traffic on the Hyper-V host. In this configuration, it’s recommended to implement the network QoS at the virtual switch level. See http://technet.microsoft.com/en-us/library/jj735302.aspx for details (the above configuration matches the second one described in the linked article).

 

Configuration 2 - High-performance fault-tolerant Hyper-V over SMB configuration with two RDMA ports and two non-RDMA ports

 

The solution below requires four network ports for each node of both the Compute Cluster and the Storage Cluster, two of them being RDMA-capable. NIC teaming is the main technology used for fault tolerance and load balancing on the two non-RDMA ports, but SMB Multichannel covers those capabilities for the two RDMA ports.

image

Configuration 2: click on diagram to see a larger picture

Notes:

  • Two dual-port network adapter per host can be used, one RDMA and one non-RDMA.
  • In this configuration, Storage, Migration and Clustering traffic should leverage the RDMA path. The client, replication and management traffic should use the teamed NIC path.
  • In this configuration, if using Windows Server 2012 R2, Hyper-V should be configured to use SMB for Live Migration. This is not the default setting.
  • The SMB client will naturally prefer the RDMA paths, so there is no need to specifically configure that preference via SMB Multichannel constraints.
  • There are three different types of RDMA NICs that can be used: iWARP, RoCE and InifiniBand. Below are links to step-by-step configuration instructions for each one:
  • Network QoS should be used to tame traffic flowing through the virtual switch on the Hyper-V host. If your NIC and switch support Data Center Bridging (DCB) and Priority Flow Control (PFC), there are additional options available as well. See http://technet.microsoft.com/en-us/library/jj735302.aspx for details (the above configuration matches the fourth one described in the linked article).
  • In most environments, RDMA provides enough bandwidth without the need of any traffic shaping. If using Windows Server 2012 R2, SMB Bandwidth Limits can optionally be used to shape the Storage and Live Migration traffic. More details can be found in item 4 of the following article: What’s new in SMB PowerShell in Windows Server 2012 R2. SMB Bandwidth Limits can also be used for configuration 1, but it's more common here.

 

I hope this blog posts helps with the network planning for your Private Cloud deployment. Feel free to ask questions via the comments below.

 

 

Automatic SMB Scale-Out Rebalancing in Windows Server 2012 R2

$
0
0

Introduction

 

This blog post focus on the new SMB Scale-Out Rebalancing introduced in Windows Server 2012 R2. If you haven’t seen it yet, it delivers a new way of balancing file clients accessing a Scale-Out File Server.

In Windows Server 2012, each client would be randomly directed via DNS Round Robin to a node of the cluster and stick with that one for all shares, all traffic going to that Scale-Out File Server. If necessary, some server-side redirection of individual IO requests could happen in order to fulfill the client request.

In Windows Server 2012 R2, a single client might be directed to a different node for each file share. The idea here is that the client will connect to the best node for each individual file share in the Scale-Out File Server Cluster, avoiding any kind of server-side redirection.

Now there are some details about when redirection can happen and when the new behavior will apply. Let’s look into the 3 types of scenarios you might encounter.

 

Hyper-V over SMB with Windows Server 2012 and a SAN back-end (symmetric)

 

When we first introduced the SMB Scale-Out File Server in Windows Server 2012, as mentioned in the introduction, the client would be randomly directed to one and only one node for all shares in that cluster.

If the storage is equally accessible from every node (what we call symmetric cluster storage), then you can do reads and writes from every file server cluster node, even if it’s not the owner node for that Cluster Shared Volume (CSV). We refer to this as Direct IO.

However, metadata operations (like creating a new file, renaming a file or locking byte range on a file) must be done orchestrated cross the cluster and will be executed on a single node called the coordinator node or the owner node. Any other node will simply redirect these metadata operations to the coordinator node.

The diagram below illustrates these behaviors:

 

image

Figure 1: Windows Server 2012 Scale-Out File Server on symmetric storage

 

The most common example of symmetric storage is when the Scale-Out File Server is put in front of a SAN. The common setup is to have every file server node connected to the SAN.

Another common example is when the Scale-Out File Server is using a clustered Storage Spaces solution with a shared SAS JBOD using Simple Spaces (no resiliency).

 

Hyper-V over SMB with Windows Server 2012 and Mirrored Storage Spaces (asymmetric)

 

When using a Mirrored Storage Spaces, the CSV operates in a block level redirected IO mode. This means that every read and write to the volume must be performed through the coordinator node of that CSV.

This configuration, where not every node has the ability to read/write to the storage, is generically called asymmetric storage. In those cases, every data and metadata request must be redirected to the coordinator node.

In Windows Server 2012, the SMB client chooses one of the nodes of the Scale-Out File Server cluster using DNS Round Robin and that may not necessarily be the coordinator node that owns the CSV that contains the file share it wants to access.

In fact, if using multiple file shares in a well-balanced cluster, it’s likely that the node will own some but not all of the CSVs required.

That means some SMB requests (for data or metadata) are handled by the node and some are redirected via the cluster back-end network to the right owner node. This redirection, commonly referred to as “double-hop”, is a very common occurrence in Windows Server 2012 when using the Scale-Out File Server combined with Mirrored Storage Spaces.

It’s important to mention that this cluster-side redirection is something that is implemented by CSV and it can be very efficient, especially if your cluster network uses RDMA-capable interfaces.

The diagram below illustrates these behaviors:

 

image

Figure 2: Windows Server 2012 Scale-Out File Server on asymmetric storage

 

The most common example of asymmetric storage is when the Scale-Out File Server is using a Clustered Storage Spaces solution with a Shared SAS JBOD using Mirrored Spaces.

Another common example is when only a subset of the file server nodes is directly connected to a portion backend storage, be it Storage Spaces or a SAN.

A possible asymmetric setup would be a 4-node cluster where 2 nodes are connected to one SAN and the other 2 nodes are connected to a different SAN.

 

Hyper-V over SMB with Windows Server 2012 R2 and Mirrored Storage Spaces (asymmetric)

 

If you’re following my train of thought here, you probably noticed that the previous configuration has a potential for further optimization and that’s exactly what we did in Windows Server 2012 R2.

In this new release, the SMB client gained the flexibility to connect to different Scale-Out File Server cluster nodes for each independent share that it needs to access.

The SMB server also gained the ability to tell its clients (using the existing Witness protocol) what is the ideal node to access the storage, in case it happens to be asymmetric.

With the combination of these two behavior changes, a Windows Server 2012 R2 SMB client and server are capable to optimize the traffic, so that no redirection is required even for asymmetric configurations.

The diagram below illustrates these behaviors:

 

image

Figure 3: Windows Server 2012 R2 Scale-Out File Server on asymmetric storage

 

Note that the SMB client now always talks to the Scale-Out File Server node that is the coordinator of the CSV where the share is.

Note also that the CSV ownership is shared across nodes in the example. That is not a coincidence. CSV now includes the ability to spread its CSVs across the nodes uniformly.

If you add or remove nodes or CSVs in the Scale-Out File Server cluster, the CSVs will be rebalanced. The SMB clients will then also be rebalanced to follow the CSV owner nodes for their shares.

 

Key configuration requirements for asymmetric storage in Windows Server 2012 R2

 

Because of this new automatic rebalancing, there are key new considerations when designing asymmetric (Mirrored or Parity Storage Spaces) storage when using Windows Server 2012 R2.

First of all, you should have at least as many CSVs as you have file server cluster nodes. For instance, for a 3-node Scale-Out File Server, you should have at least 3 CSVs. Having 6 CSVs is also a valid configuration, which will help with rebalancing when one of the nodes is down for maintenance.

To be clear, if you have a single CSV in such asymmetric configuration in Windows Server 2012 R2 Scale-Out File Server cluster, only one node will be actively accessed by SMB clients.

You should also try, as much as possible, to have your file shares and workloads evenly spread across the multiple CSVs. This way you won’t have some nodes working much harder than others.

 

Forcing per-share redirection for symmetric storage in Windows Server 2012 R2

 

The new per-share redirection does not happen by default in the Scale-Out File Server if the back-end storage is found to be symmetric.

For instance, if every node of your file server is connected to a SAN back-end, you will continue to have the behavior described on Figure 1 (Direct IO from every node plus metadata redirection).

The CSVs will automatically be balanced across file server cluster nodes even in symmetric storage configurations. You can turn that behavior off using the cmdlet below, although I'm hard pressed to find any good reason to do it.

(Get-Cluster). CSVBalancer = 0

However, when using symmetric storage, the SMB clients will continue to each connect a single file server cluster node for all shares. We opted for this behavior by default because Direct IO tends to be efficient in these configurations and the amount of metadata redirection should be fairly small.

You can override this setting and make the symmetric cluster use the same rebalancing behavior as an asymmetric cluster by using the following PowerShell cmdlet:

Set-ItemProperty HKLM:\System\CurrentControlSet\Services\LanmanServer\Parameters -Name AsymmetryMode -Type DWord -Value 2 -Force

You must apply the setting above to every file server cluster node. The new behavior won’t apply to existing client sessions.

If you switch to this configuration, you must apply the same planning rules outlined previously (at least one CSV per file server node, ideally two).

 

Conclusion

 

I hope this clarifies the behavior changes introduced with SMB Scale-Out Automatic Rebalancing in Windows Server 2012 R2.

While most of it is designed to just work, I do get some questions about it from those interested in understanding what happens behind the scenes.

Let me know if you find those useful or if you have any additional questions.

Updated Links on Windows Server 2012 R2 File Server and SMB 3.02

$
0
0

In this post, I'm providing a reference to the most relevant content related to Windows Server 2012 R2 that is related to the File Server, the SMB 3.02 features and its associated scenarios like Hyper-V over SMB and SQL Server over SMB. It's obviously not a complete reference (there are always new blogs and articles being posted), but hopefully this is a useful collection of links for Windows Server 2012 R2 users.

This post covers only articles that are specific to Windows Server 2012 R2. However, note that there’s also a Windows Server 2012 version of this post. Most concepts, step-by-steps and tools listed there also apply to Windows Server 2012 R2.

 

Overview articles on Windows Server 2012 R2 File Server and SMB 3.02 (and related topics)

 

Step-by-step instructions for Windows Server 2012 R2 File Server and SMB 3.0 (and related topics)

 

TechEd 2013 presentations (with video recording) on Windows Server 2012 R2 File Server and SMB 3.0 (and related topics)

 

Demos, Interviews and other video recordings

 

Windows Server 2012 R2 download links

 

Blog posts by Microsoft MVPs on Windows Server 2012 R2 File Server and SMB 3.0 (and related topics)

 

Windows Server 2012 R2 File Server Tips and Q&A

  • Coming later

 

Protocol Documentation

 

Other relevant links related to Windows Server 2012 R2 SMB features

 

Knowledge Base - KB Articles

  • KB 2883200 - Windows Server 2012 R2 General Availability Update Rollup.

 

-------

 

Change tracking:

  • 06/26/2013: Original post
  • 07/11/2013: Added two demos, added Mellanox driver download, updated links
  • 07/18/2013: Added more MVP blog links
  • 07/31/2013: Additional blog links (including main In The Cloud blog, step-by-step guides)
  • 09/23/2013: Additional blog links (SMB PowerShell, Storage Spaces) and links to final protocol documents
  • 10/17/2013: Additional blog links (Networking) and GA Update Rollup link.
  • 11/04/2013: Additional blog link (Rebalancing), Storage Spaces FAQ wiki link
  • 11/10/2013: Additional blog link (Number of nodes), Performance guide link

Selecting the number of nodes for your Scale-Out File Server Cluster

$
0
0

I recently got a stream of e-mails and questions about the maximum number of cluster nodes you can have in a Scale-Out File Server cluster. For the record, we test and support up to 8 nodes per file server cluster. This is the case for both Windows Server 2012 (which introduced the Scale-Out File Server cluster feature) and Windows Server 2012 R2.

 

image

 

However, the real question is usually "How many file server nodes do I need for my Scale-Out File Server cluster?" The most common scenarios we see involve the deployment of 2 to 4 file server nodes per cluster, with just a few people considering 8 nodes. Here are some arguments for each cluster size:

  • 2 is the bare minimum for achieving continuous availability (transparent failover). We see a lot of these two-node clusters out there.
  • 3 is a good idea to allow you to still have continuous availability even when you're doing maintenance on a node.
  • 4 allows you to upgrade the cluster without extra hardware by evicting two nodes, installing the new operating system and using the Copy Cluster Roles Wizard.
  • 8 will allow you to combine the network throughput and computing power of the many nodes to create an amazing file sharing infrastructure.

On the topic of performance, keep in mind that the Scale-Out concept means that you have the ability to linearly scale the cluster by adding more nodes to achieve higher IOPS and throughput. We have proved it in our test labs. However, we have also shown that a single file server cluster node can deliver over 200,000 IOPs at 8KB each or over 2GB/sec throughput, with a fairly standard server configuration (two modern Intel CPUs with a few cores each, dual 10GbE RDMA network interfaces, two SAS port each with four lanes of 6Gbps SAS shared storage with an SSD tier). We have also shown high-end file server configurations achieving over a million IOPs and over 16.5GB/sec from a single node. So, there are only a few scenarios that would require anything close to 8 nodes solely to achieve specific performance goals.

Also, keep in mind that the reasons for adopting a Scale-Out File Server usually include a combination of availability, performance and scalability of the resulting file service. While the number of nodes is an important ingredient to achieve that, you should never overlook related configuration decisions like the number and model of CPU you're using, the number and type of network interfaces, the number and speed of the SAS ports, the proper deployment of tiered storage with the right class of SSDs and even the generation and number of lanes of the PCIe slots you use. Two well sized and properly fitted file server nodes can easily beat eight nodes that were poorly put together.

Here a few additional references for those looking to dig deeper:

I'm not sure what's driving this wave of questions about the Scale-Out File Server cluster limits, but I hope this helps clarify the topic. Have you ever encountered a scenario where you would need more than 8 nodes? We would love to hear it...


Step-by-Step for Mirrored Storage Spaces Resiliency using PowerShell

$
0
0
 
0 - Overview
 
This blog post is a walkthrough of the resiliency offered by Storage Spaces when using mirrored spaces.
For this exercise we have a single virtual machine with multiple data disks used to create the spaces.
The idea is to simulate a number of different failure and recovery scenarios, reviewing the behavior.
It includes the procedure to replace a disk and repair a degraded Space.
 
1 - Two-way mirror with 3 disks
 
Part 1 of this post focuses on testing the resiliency of a two-way mirrored virtual disk (storage space) on a storage pool with 3 physical disks.
For each section you have the steps to perform (useful if you want to cut/paste), the actual output of the cmdlets on my test system and finally some notes explaining what happened.
 
1.1 - Attach 3 disks to a VM
 
Steps to perform on the host:
 
1..3 | % { New-VHD –Path D:\demo\disk$_.VHDX –Dynamic –SizeBytes 20GB } | Out-Null
1..3 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:\demo\disk$_.VHDX -ControllerType SCSI}
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> 1..3 | % { New-VHD –Path D:\demo\disk$_.VHDX –Dynamic –SizeBytes 20GB } | Out-Null
PS C:\> 1..3 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:\demo\disk$_.VHDX -ControllerType SCSI}
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
 
Notes:
 
Nothing much. Just your regular VM with 1 IDE boot disk and 3 SCSI data disks.
 
1.2 - Create pool and mirrored space
 
Steps to perform on the guest:
 
$s = Get-StorageSubSystem -FriendlyName *Spaces*
$d = Get-PhysicalDisk -CanPool $true
New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d
$p = Get-StoragePool Pool1
Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 2
$p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize
 
$L ="X”
$N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number
Set-Disk -Number $N -IsReadOnly 0
Set-Disk -Number $N -IsOffline 0
Initialize-Disk -Number $N -PartitionStyle MBR
New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize 
Start-Sleep –Seconds 10
Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false
 
Output:
 
PS C:\> $s = Get-StorageSubSystem -FriendlyName *Spaces*
PS C:\> $d = Get-PhysicalDisk -CanPool $true
PS C:\> New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d
 
FriendlyName            OperationalStatus       HealthStatus            IsPrimordial            IsReadOnly
------------            -----------------       ------------            ------------            ----------
Pool1                   OK                      Healthy                 False                   False
 
PS C:\> $p = Get-StoragePool Pool1
PS C:\> Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 2
PS C:\> $p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize
 
FriendlyName        ResiliencySettingNa OperationalStatus   HealthStatus        IsManualAttach                     Size
                    me
------------        ------------------- -----------------   ------------        --------------                     ----
Space1              Mirror              OK                  Healthy             False                             27 GB
 
PS C:\> $L ="X”
PS C:\> $N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number
PS C:\> Set-Disk -Number $N -IsReadOnly 0
PS C:\> Set-Disk -Number $N -IsOffline 0
PS C:\> Initialize-Disk -Number $N -PartitionStyle MBR
PS C:\> New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize
 
   Disk Number: 4
 
PartitionNumber  DriveLetter Offset                                        Size Type
---------------  ----------- ------                                        ---- ----
1                X           1048576                                      27 GB Logical
 
PS C:\> Start-Sleep –Seconds 10
PS C:\> Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false
 
DriveLetter       FileSystemLabel  FileSystem       DriveType        HealthStatus        SizeRemaining             Size
-----------       ---------------  ----------       ---------        ------------        -------------             ----
X                                  NTFS             Fixed            Healthy                   26.9 GB            27 GB
 
Notes:
 
Created a Pool and Space. Resulting disk is initialized and mounted as volume X:.
 
1.3 - Verify health of the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | FT -AutoSize
 
   Disk Number: 4
 
PartitionNumber DriveLetter Offset   Size Type
--------------- ----------- ------   ---- ----
1               X           1048576 27 GB IFS
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | FT -AutoSize
 
Number Friendly Name                  OperationalStatus Total Size Partition Style
------ -------------                  ----------------- ---------- ---------------
4      Microsoft Storage Space Device Online                 27 GB MBR
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk2 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
Notes:
 
All is healthy: Volume, Space (Virtual Disk), Pool and Physical Disks.
 
1.4 - Remove 1 disk
 
Steps to perform on the host:
 
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
 
Notes:
 
Removed one of the 3 SCSI disks for the VM.
That is the equivalent, in a physical machine, to pulling a drive out while the system is running (assuming you have a drive that supports hot removal).
 
1.5 - Verify effect on the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-EventLog -LogName System -Source Disk | ? EntryType -ne "Information" | FL
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Level -lt 4 | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                Incomplete        Warning      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Degraded          Warning      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk2  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk3  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-EventLog -LogName System -Source Disk | ? EntryType -ne "Information" | FL
 
Index              : 14802
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 1 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR11, 1}
Source             : disk
TimeGenerated      : 3/29/2014 5:04:16 PM
TimeWritten        : 3/29/2014 5:04:16 PM
UserName           :
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Level -lt 4 | FL
 
TimeCreated  : 3/29/2014 5:04:16 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 4:54:00 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 103
Message      : The capacity consumption of the storage pool {1874344D-B794-11E3-80B7-00155D010205} has exceeded the
               threshold limit set on the pool. Return Code: STATUS_SUCCESS
 
Notes:
 
As expected, the mirror is now incomplete and pool is degraded, but the volume is still healthy.
Applications won’t see the event, but alarm bells are ringing in the event logs.
 
1.6 - Add back the removed disk
 
Steps to perform on the host:
 
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX

Notes:
 
Added the VHDX file back.
That is the equivalent, in a physical machine, plugging the drive back in (assuming you have a drive that supports hot plugging).
 
1.7 - Verify that the pool and space recover
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Message -like "*repair*" | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk2 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Message -like "*repair*" | FL
 
TimeCreated  : 3/29/2014 5:11:39 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874345F-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 4:54:00 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874345F-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
Notes:
 
Storage Spaces, seeing the drive coming back, attempts a repair and succeeds. Not sure why the log shows two repairs.
After that, all is well again: virtual disks, storage pools and physical disks all report as healthy.
Again, this is completely transparent to the applications.
 
1.8 - Remove 2 disks
 
Steps to perform on the host:
 
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
 
Notes:
 
Removing 2 of the 3 disks now. There is now only one surviving disk. This will be trouble...
 
1.9 - Verify effect on the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT –AutoSize
Get-VirtualDisk Space1 | FT -AutoSize
Get-VirtualDisk Space1  | Get-StoragePool | FT -AutoSize
Get-VirtualDisk Space1  | Get-PhysicalDisk | FT -AutoSize
Get-EventLog -LogName System -Source Disk -After "3/29/2014 5:10 PM” | ? EntryType -ne "Information" | FL
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 5:10 PM") } | FL
 
Output:
 
PS C:\> Get-Volume X | FT –AutoSize
Get-Volume : No MSFT_Volume objects found with property 'DriveLetter' equal to 'X'.  Verify the value of the property and retry.
At line:1 char:1
+ Get-Volume X | FT –AutoSize
+ ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (X:Char) [Get-Volume], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound_DriveLetter,Get-Volume
 
PS C:\> Get-VirtualDisk Space1 | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                Detached          Unhealthy    False          27 GB
 
PS C:\> Get-VirtualDisk Space1  | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Read-only         Unhealthy    False        False
 
PS C:\> Get-VirtualDisk Space1  | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk3  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-EventLog -LogName System -Source Disk -After "3/29/2014 5:10 PM” | ? EntryType -ne "Information" | FL
 
Index              : 14807
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 4 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR14, 4}
Source             : disk
TimeGenerated      : 3/29/2014 5:17:32 PM
TimeWritten        : 3/29/2014 5:17:32 PM
UserName           :
 
Index              : 14806
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 2 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\...\DR12, 2}
Source             : disk
TimeGenerated      : 3/29/2014 5:17:32 PM
TimeWritten        : 3/29/2014 5:17:32 PM
UserName           :
 
Index              : 14805
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 1 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR15, 1}
Source             : disk
TimeGenerated      : 3/29/2014 5:17:31 PM
TimeWritten        : 3/29/2014 5:17:31 PM
UserName           :
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 5:10 PM") } | FL
 
 
TimeCreated  : 3/29/2014 5:17:32 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 5:17:32 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 203
Message      : Physical drive {38133EAF-D68C-7229-E30B-64D68782E509} failed an IO operation. Return Code: This device
               does not exist.. Additional related events may be found in the System event log for Disk 2.
 
 
               This drive may need to be replaced. To view its reliability counters, run this command in PowerShell:
 
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{38133EAF-D68C-7229-E30B-64D68782E509}" } |
               Get-StorageReliabilityCounter
 
               This drive may be located using the following information:
 
               Drive Manufacturer: Msft
               Drive Model Number: Virtual Disk
               Drive Serial Number:
 
               More information can be obtained using this PowerShell command:
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{38133EAF-D68C-7229-E30B-64D68782E509}" }
 
               If this drive is in an enclosure, it may be located using the following information:
 
               Enclosure Manufacturer:
               Enclosure Model Number:
               Enclosure Serial Number:
               Enclosure Slot: -1
 
               It may also be located by running this command in PowerShell:
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{38133EAF-D68C-7229-E30B-64D68782E509}" } |
               Enable-PhysicalDiskIndication
 
TimeCreated  : 3/29/2014 5:17:32 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 303
Message      : Drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or are
               missing. As a result, no copy of data is available. Return Code: This device does not exist.
 
TimeCreated  : 3/29/2014 5:17:32 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 303
Message      : Drives hosting data for storage space {18743460-B794-11E3-80B7-00155D010205} have failed or are
               missing. As a result, no copy of data is available. Return Code: This device does not exist.
 
TimeCreated  : 3/29/2014 5:17:31 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 5:11:38 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
Notes:
 
As expected, things get broken. The virtual disk is detached and the volume simply disappears completely.
The storage pool is showing as unhealthy and read-only. Two physical disks are correctly reported missing.
If there is an application using this specific volume, there will be failures and down time associated with this event.
 
1.10 - Add back the removed disks
 
Steps to perform on the host:
 
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1 –Path D:\demo\disk2.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1 –Path D:\demo\disk2.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
 
Notes:
 
Putting the two drives back in. This should fix things.
 
1.11 - Verify that the pool and space recover
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Message -like "*repair*") -and ($_.TimeCreated -gt "3/29/2014 5:20 PM") } | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Message -like "*repair*") -and ($_.TimeCreated -gt "3/29/2014 5:20 PM") } | FL
 
 
TimeCreated  : 3/29/2014 6:12:50 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874345F-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 6:12:47 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874345F-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
Notes:
 
Without any need for repair commands, the physical disks are detected and go back to a healthy state.
The storage pool goes back to healthy and is no longer read-only. The virtual disk recovers and the volume shows up again.
You will have some work to do restart and recover your applications, which suffered the equivalent of a hard crash.
 
1.12- Remove 1 disk, add replacement disk
 
Steps to perform on the host:
 
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
New-VHD –Path D:\demo\disk1r.VHDX –Dynamic –SizeBytes 20GB
Add-VMHardDiskDrive –VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1r.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
PS C:\> New-VHD –Path D:\demo\disk1r.VHDX –Dynamic –SizeBytes 20GB | Out-Null
PS C:\> Add-VMHardDiskDrive –VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1r.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1r.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
 
Notes:
 
Now we’re simulating that you lost a disk and it’s really broken and never coming back.
You add a brand new disk that will be the replacement to the old disk.
 
1.13 - Verify effect on the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-PhysicalDisk –CanPool $true | FT -AutoSize
Get-EventLog -LogName System -Source Disk -After "3/29/2014 6:20 PM” | ? EntryType -ne "Information" | FL
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 6:20 PM") } | FL
 
Output:
 
PS C:\> Get-Volume X | FT –AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                Incomplete        Warning      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Degraded          Warning      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk4  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk3  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-PhysicalDisk –CanPool $true | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage        Size
------------  ------- ----------------- ------------ -----        ----
PhysicalDisk1 True    OK                Healthy      Auto-Select 20 GB
 
PS C:\> Get-EventLog -LogName System -Source Disk -After "3/29/2014 6:20 PM” | ? EntryType -ne "Information" | FL
 
 
Index              : 14813
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 1 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR16, 1}
Source             : disk
TimeGenerated      : 3/29/2014 6:24:13 PM
TimeWritten        : 3/29/2014 6:24:13 PM
UserName           :
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 6:20 PM") } | FL
 
 
TimeCreated  : 3/29/2014 6:24:13 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874345F-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
Notes:
 
As we saw previously, we survive the failure of a single disk just fine. Volume is healthy, but the virtual disk and pool are degraded.
We note that there is a brand new disk available that can be pooled, but Storage Spaces will not automatically attempt to use it.
 
1.14 - Retire old disk, add new disk, repair and verify
 
Steps to perform on the guest:
 
Get-PhysicalDisk | ? OperationalStatus –eq “Lost Communication” | Set-PhysicalDisk –Usage Retired
Add-PhysicalDisk –StoragePoolFriendlyName Pool1 -PhysicalDisks (Get-PhysicalDisk –CanPool $True)
Repair-VirtualDisk Space1
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT –AutoSize
Get-StoragePool Pool1 | Get-PhysicalDisk | FT –AutoSize
 
Remove-PhysicalDisk -StoragePoolFriendlyName Pool1 -PhysicalDisks (Get-PhysicalDisk | ? OperationalStatus -eq "Lost Communication" )
Get-StoragePool Pool1 | Get-PhysicalDisk | FT –AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
Output:
 
PS C:\> Get-PhysicalDisk | ? OperationalStatus –eq “Lost Communication” | Set-PhysicalDisk –Usage Retired
PS C:\> Add-PhysicalDisk –StoragePoolFriendlyName Pool1 -PhysicalDisks (Get-PhysicalDisk –CanPool $True)
PS C:\> Repair-VirtualDisk Space1
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            26.9 GB 27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          27 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Degraded          Warning      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT –AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-StoragePool Pool1 | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk4  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Retired     19.25 GB
PhysicalDisk1  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk3  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Remove-PhysicalDisk -StoragePoolFriendlyName Pool1 -PhysicalDisks (Get-PhysicalDisk | ? OperationalStatus -eq "Lost Communication" )
 
Confirm
Are you sure you want to perform this action?
Removing a physical disk will cause problems with the fault tolerance capabilities of the following storage pool:"Pool1".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
 
PS C:\> Get-StoragePool Pool1 | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
Notes:
 
After we add the new disk to the pool and command a repair, things go back to normal.
The old disk can either be retired (remains showing in the pool) or it can be completely removed from the pool.
 
1.15 - Add the old disk back
 
Steps to perform on the host:
 
Add-VMHardDiskDrive –VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 3 –Path D:\demo\disk1.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Add-VMHardDiskDrive –VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 3 –Path D:\demo\disk1.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1r.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
VM2    SCSI           0                3                             D:\demo\disk1.VHDX
 
Notes:
 
Simulating an odd but plausible situation. You have cleaned up the pool and repaired everything after a disk went bad, but someone put that old disk back in.
Since you’ve already removed it from the pool, what is the result?
 
1.16 - Verify effect on the pool, reset disk
 
Steps to perform on the guest:
 
Get-PhysicalDisk | FT –AutoSize
Get-StoragePool Pool1 | Get-PhysicalDisk
Get-PhysicalDisk | ? OperationalStatus -eq "Unrecognized Metadata" | Reset-PhysicalDisk
Get-PhysicalDisk | FT -AutoSize
 
Get-EventLog -LogName System -Source Disk -After "3/29/2014 6:20 PM” | ? EntryType -ne "Information" | FL
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 6:20 PM") } | FL
 
Output:
 
PS C:\> Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus     HealthStatus Usage           Size
------------  ------- -----------------     ------------ -----           ----
PhysicalDisk0 False   OK                    Healthy      Auto-Select    32 GB
PhysicalDisk4 False   OK                    Healthy      Auto-Select 19.25 GB
PhysicalDisk5 False   Unrecognized MetadataUnhealthy    Unknown        20 GB
PhysicalDisk1 False   OK                    Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                    Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-StoragePool Pool1 | Get-PhysicalDisk
 
FriendlyName        CanPool             OperationalStatus   HealthStatus        Usage                              Size
------------        -------             -----------------   ------------        -----                              ----
PhysicalDisk4       False               OK                  Healthy             Auto-Select                    19.25 GB
PhysicalDisk1       False               OK                  Healthy             Auto-Select                    19.25 GB
PhysicalDisk3       False               OK                  Healthy             Auto-Select                    19.25 GB
 
PS C:\> Get-PhysicalDisk | ? OperationalStatus -eq "Unrecognized Metadata" | Reset-PhysicalDisk
PS C:\> Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk0 False   OK                Healthy      Auto-Select    32 GB
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk5 True    OK                Healthy      Auto-Select    20 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 7:00PM") } | FL
 
TimeCreated  : 3/29/2014 7:10:53 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 201
Message      : Physical drive {5A464324-FBA5-A176-5DE8-DE8FE63E3951} has invalid meta-data. Resetting the health
               status, using command line or GUI, might bring the physical drive to the primordial pool. Return Code:
               STATUS_SUCCESS
 
Notes:
 
So you can see that the old disk comes back as unhealthy, with a status of “unrecognized metadata”.
It has already been removed from the pool and contains metadata that is inconsistent with the current state of the pools and virtual disks in the system.
There is an interesting event log in the Storage Spaces event highlighting the situation. The recommendation is to reset the health status.
We go ahead and reset it as suggested, making it healthy again and available to add back to the pool if necessary (that last portion is not shown).
 
2 - Three-way mirror with 5 disks
 
Part 2 of this post focuses on testing the resiliency of a 3-way mirrored virtual disk on a storage pool with 5 physical disks. It follows the same format as Part 1.
We are going to start fresh with a new set of disks. At this point, if you’re following along on your system, you should:
  • Inside the VM, remove all virtual disks and pools from Part 1.
  • On the host, remove the data VHDX files from the VM, then delete them.
  • Inside the VM, clear the System log and the Storage Spaces.
 
2.1 - Attach 5 disks to a VM
 
Steps to perform on the host:
 
1..5 | % { New-VHD –Path D:\demo\disk$_.VHDX –Dynamic –SizeBytes 20GB }
1..5 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:\demo\disk$_.VHDX -ControllerType SCSI}
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> 1..5 | % { New-VHD –Path D:\demo\disk$_.VHDX –Dynamic –SizeBytes 20GB } | Out-Null
PS C:\> 1..5 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:\demo\disk$_.VHDX -ControllerType SCSI}
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
VM2    SCSI           0                3                             D:\demo\disk4.VHDX
VM2    SCSI           0                4                             D:\demo\disk5.VHDX
 
Notes:
 
Nothing much. Just your regular VM with 1 IDE boot disk and 5 SCSI data disks.
 
2.2 - Create pool and 3-way mirrored space
 
Steps to perform on the guest:
 
$s = Get-StorageSubSystem -FriendlyName *Spaces*
$d = Get-PhysicalDisk -CanPool $true
New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d
$p = Get-StoragePool Pool1
Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 3
$p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize
 
$L ="X”
$N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number
Set-Disk -Number $N -IsReadOnly 0
Set-Disk -Number $N -IsOffline 0
Initialize-Disk -Number $N -PartitionStyle MBR
New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize 
Start-Sleep –Seconds 10
Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false
 
Output:
 
PS C:\> $s = Get-StorageSubSystem -FriendlyName *Spaces*
PS C:\> $d = Get-PhysicalDisk -CanPool $true
PS C:\> New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d
 
FriendlyName            OperationalStatus       HealthStatus            IsPrimordial            IsReadOnly
------------            -----------------       ------------            ------------            ----------
Pool1                   OK                      Healthy                 False                   False
 
PS C:\> $p = Get-StoragePool Pool1
PS C:\> Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 3
PS C:\> $p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize
 
FriendlyName        ResiliencySettingNa OperationalStatus   HealthStatus        IsManualAttach                     Size
                    me
------------        ------------------- -----------------   ------------        --------------                     ----
Space1              Mirror              OK                  Healthy             False                             30 GB
 
PS C:\> $L ="X”
PS C:\> $N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number
PS C:\> Set-Disk -Number $N -IsReadOnly 0
PS C:\> Set-Disk -Number $N -IsOffline 0
PS C:\> Initialize-Disk -Number $N -PartitionStyle MBR
PS C:\> New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize
 
   Disk Number: 6
 
PartitionNumber  DriveLetter Offset                                        Size Type
---------------  ----------- ------                                        ---- ----
1                X           1048576                                      30 GB Logical
 
PS C:\> Start-Sleep –Seconds 10
PS C:\> Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false
 
DriveLetter       FileSystemLabel  FileSystem       DriveType        HealthStatus        SizeRemaining             Size
-----------       ---------------  ----------       ---------        ------------        -------------             ----
X                                  NTFS             Fixed            Healthy                   29.9 GB            30 GB
 
Notes:
 
Created a storage pool and storage space. Resulting disk is initialized and mounted as volume X:.
 
2.3 - Verify health of the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            29.9 GB 30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk2 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk5 False   OK                Healthy      Auto-Select 19.25 GB
 
Notes:
 
All is healthy: volume, storage space (virtual disk), storage pool and physical disks.
 
2.4 - Remove 2 disks
 
Steps to perform on the host:
 
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
VM2    SCSI           0                3                             D:\demo\disk4.VHDX
VM2    SCSI           0                4                             D:\demo\disk5.VHDX
 
Notes:
 
Removed 2 of the 5 SCSI disks for the VM.
Since this is a 3-way mirror, we’re going to hit it right away with a double disk failure. But it should be able to survive that.
 
2.5 - Verify effect on the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-EventLog -LogName System -Source Disk | ? EntryType -ne "Information" | FL
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Level -lt 4 | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            29.9 GB 30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                Incomplete        Warning      False          30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Degraded          Warning      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk3  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk4  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk5  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-EventLog -LogName System -Source Disk | ? EntryType -ne "Information" | FL
 
Index              : 14841
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 2 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR22, 2}
Source             : disk
TimeGenerated      : 3/29/2014 8:38:11 PM
TimeWritten        : 3/29/2014 8:38:11 PM
UserName           :
 
Index              : 14840
EntryType          : Warning
InstanceId         : 2147745949
Message            : Disk 1 has been surprise removed.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {\DR21, 1}
Source             : disk
TimeGenerated      : 3/29/2014 8:38:10 PM
TimeWritten        : 3/29/2014 8:38:10 PM
UserName           :
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Level -lt 4 | FL
 
 
TimeCreated  : 3/29/2014 8:38:11 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:38:10 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:31:56 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 103
Message      : The capacity consumption of the storage pool {18743521-B794-11E3-80B7-00155D010205} has exceeded the
               threshold limit set on the pool. Return Code: STATUS_SUCCESS
 
Notes:
 
As expected, the 3-way mirrored space was able to survive the double disk failure. The storage space is now incomplete and the storage pool is degraded, but the volume is still healthy.
Applications won’t see the event, but again there are many alarm bells ringing in the event logs. You better act fast because the next failure will be fatal…
 
2.6 - Add back the removed disks
 
Steps to perform on the host:
 
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1 –Path D:\demo\disk2.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 –Path D:\demo\disk1.VHDX
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1 –Path D:\demo\disk2.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                0                             D:\demo\disk1.VHDX
VM2    SCSI           0                1                             D:\demo\disk2.VHDX
VM2    SCSI           0                2                             D:\demo\disk3.VHDX
VM2    SCSI           0                3                             D:\demo\disk4.VHDX
VM2    SCSI           0                4                             D:\demo\disk5.VHDX
 
Notes:
 
Added the two VHDX files back to restore the VM to the original state.
 
2.7 - Verify that the pool and space recover
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Message -like "*repair*" | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            29.9 GB 30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk2 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk5 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Message -like "*repair*" | FL
 
TimeCreated  : 3/29/2014 8:45:51 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:45:47 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:31:56 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
Notes:
 
Storage Spaces, seeing the drives coming back, attempts a repair and succeeds.
After that, all is well again: virtual disks, storage pools and physical disks all report as healthy.
This shows that we can survive two disk failures in a way that is completely transparent to the applications.
 
2.8 - Remove 3 disks
 
Steps to perform on the host:
 
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 2
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1
PS C:\> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 2
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                3                             D:\demo\disk4.VHDX
VM2    SCSI           0                4                             D:\demo\disk5.VHDX
 
Notes:
 
Removing 3 of the 5 disks now. There are now only two surviving disks. That should be too much to bear.
 
2.9 - Verify effect on the pool and space
 
Steps to perform on the guest:
 
Get-Volume X | FT –AutoSize
Get-VirtualDisk Space1 | FT -AutoSize
Get-VirtualDisk Space1  | Get-StoragePool | FT -AutoSize
Get-VirtualDisk Space1  | Get-PhysicalDisk | FT -AutoSize
Get-EventLog -LogName System -Source Disk -After "3/29/2014 8:40 PM” | ? EntryType -ne "Information" | FT TimeGenerated, Source, Index, EventID, EntryType, Message -AutoSize
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 8:40 PM") } | FL
 
Output:
 
PS C:\> Get-Volume X | FT –AutoSize
Get-Volume : No MSFT_Volume objects found with property 'DriveLetter' equal to 'X'.  Verify the value of the property and retry.
At line:1 char:1
+ Get-Volume X | FT –AutoSize
+ ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (X:Char) [Get-Volume], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound_DriveLetter,Get-Volume
 
PS C:\> Get-VirtualDisk Space1 | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                Detached          Unhealthy    False          30 GB
 
PS C:\> Get-VirtualDisk Space1  | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        Read-only         Unhealthy    False        False
 
PS C:\> Get-VirtualDisk Space1  | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName   CanPool OperationalStatus  HealthStatus Usage           Size
------------   ------- -----------------  ------------ -----           ----
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk4  False   OK                 Healthy      Auto-Select 19.25 GB
PhysicalDisk-1 False   Lost Communication Warning      Auto-Select 19.25 GB
PhysicalDisk5  False   OK                 Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-EventLog -LogName System -Source Disk -After "3/29/2014 8:40 PM” | ? EntryType -ne "Information" | FT TimeGenerated, Source, Index, EventID, EntryType, Message -AutoSize
 
TimeGenerated        Source Index EventID EntryType Message
-------------        ------ ----- ------- --------- -------
3/29/2014 8:50:21 PM disk   14847     157   Warning Disk 6 has been surprise removed.
3/29/2014 8:50:21 PM disk   14846     157   Warning Disk 3 has been surprise removed.
3/29/2014 8:50:20 PM disk   14845     157   Warning Disk 2 has been surprise removed.
3/29/2014 8:50:19 PM disk   14844     157   Warning Disk 1 has been surprise removed.
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Level -lt 4) -and ($_.TimeCreated -gt "3/29/2014 8:40 PM") } | FL
 
TimeCreated  : 3/29/2014 8:50:21 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:50:21 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 203
Message      : Physical drive {06724EEA-84C4-283C-1EF9-F26D195E0D7A} failed an IO operation. Return Code: This device
               does not exist.. Additional related events may be found in the System event log for Disk 3.
 
 
               This drive may need to be replaced. To view its reliability counters, run this command in PowerShell:
 
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{06724EEA-84C4-283C-1EF9-F26D195E0D7A}" } |
               Get-StorageReliabilityCounter
 
               This drive may be located using the following information:
 
               Drive Manufacturer: Msft
               Drive Model Number: Virtual Disk
               Drive Serial Number:
 
               More information can be obtained using this PowerShell command:
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{06724EEA-84C4-283C-1EF9-F26D195E0D7A}" }
 
               If this drive is in an enclosure, it may be located using the following information:
 
               Enclosure Manufacturer:
               Enclosure Model Number:
               Enclosure Serial Number:
               Enclosure Slot: -1
 
               It may also be located by running this command in PowerShell:
               Get-PhysicalDisk | ?{ $_.ObjectId -Match "{06724EEA-84C4-283C-1EF9-F26D195E0D7A}" } |
               Enable-PhysicalDiskIndication
 
TimeCreated  : 3/29/2014 8:50:21 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 303
Message      : Drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or are
               missing. As a result, no copy of data is available. Return Code: This device does not exist.
 
TimeCreated  : 3/29/2014 8:50:20 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:50:19 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:45:49 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 8:45:46 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 304
Message      : One or more drives hosting data for storage space {1874353C-B794-11E3-80B7-00155D010205} have failed or
               are missing. As a result, at least one copy of data is not available. However, at least one copy of
               data is still available. Return Code: STATUS_SUCCESS
 
Notes:
 
As expected, the volume is gone and any applications running here would have stopped.
The virtual disk is detached, the volume is dismounted, the pool is unhealthy and 3 physical disks are missing.
Again we get more disk failures and Storage Spaces failures as I would expect. Not sure why that happens.
 
2.10 - Add back the 3 removed disks
 
Steps to perform on the host:
 
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 5 –Path D:\demo\disk1.VHDX
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 6 –Path D:\demo\disk2.VHDX
Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 7 –Path D:\demo\disk3.VHDX
Get-VMHardDiskDrive -VMName VM2
 
Output:
 
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 5 –Path D:\demo\disk1.VHDX
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 6 –Path D:\demo\disk2.VHDX
PS C:\> Add-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 7 –Path D:\demo\disk3.VHDX
PS C:\> Get-VMHardDiskDrive -VMName VM2
 
VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path
------ -------------- ---------------- ------------------ ---------- ----
VM2    IDE            0                0                             c:\demo\v2.vhdx
VM2    SCSI           0                3                             D:\demo\disk4.VHDX
VM2    SCSI           0                4                             D:\demo\disk5.VHDX
VM2    SCSI           0                5                             D:\demo\disk1.VHDX
VM2    SCSI           0                6                             D:\demo\disk2.VHDX
VM2    SCSI           0                7                             D:\demo\disk3.VHDX
 
Notes:
 
Simulating putting the 3 drives back in. This should fix things.
Just for fun, adding them in different controller locations, the equivalent of putting it back in a drive bay different than where it was originally.
Storage Spaces relies on the metadata stored in the disk itself, so this should not make any difference.
 
2.11 - Verify that the pool and space recover
 
Steps to perform on the guest:
 
Get-Volume X | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Message -like "*repair*") -and ($_.TimeCreated -gt "3/29/2014 9:00 PM") } | FL
 
Output:
 
PS C:\> Get-Volume X | FT -AutoSize
 
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining  Size
----------- --------------- ---------- --------- ------------ -------------  ----
X                           NTFS       Fixed     Healthy            29.9 GB 30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize
 
FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
Space1       Mirror                OK                Healthy      False          30 GB
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize
 
FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool1        OK                Healthy      False        False
 
PS C:\> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize
 
FriendlyName  CanPool OperationalStatus HealthStatus Usage           Size
------------  ------- ----------------- ------------ -----           ----
PhysicalDisk6 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk1 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk4 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk3 False   OK                Healthy      Auto-Select 19.25 GB
PhysicalDisk5 False   OK                Healthy      Auto-Select 19.25 GB
 
PS C:\> Get-WinEvent -LogName Microsoft-Windows-Stor* | ? { ($_.Message -like "*repair*") -and ($_.TimeCreated -gt "3/29/2014 9:00 PM") } | FL
 
TimeCreated  : 3/29/2014 9:13:14 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 9:13:08 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
TimeCreated  : 3/29/2014 9:13:05 PM
ProviderName : Microsoft-Windows-StorageSpaces-Driver
Id           : 308
Message      : A repair attempt for storage space {1874353C-B794-11E3-80B7-00155D010205} was initiated by the driver.
               Return Code: STATUS_SUCCESS
 
Notes:
 
Again, without any need for repair commands, the physical disks are detected and everything goes back to a healthy state.
Keep in mind that your application probably will need to be restarted and you should follow the required recovery steps, since there was down time.
 
3 - Conclusion
 
This is it. I hope this tour of mirrored storage spaces resiliency was helpful.
The idea was to save you the trouble of finding this out for yourself, but I’m sure you’ll still be interested in experimenting with it further.
The goal was also to prepare you for an eventual disk failure. You will likely be a bit more stressed at that time, so knowing what to expect and where to look might be helpful.
I have lots of additional ideas to try like trying more columns, adding storage tiers to the mix, using parity spaces or actually using an actual bad disk to go beyond just surprise removals.
But I guess that will have to wait for another opportunity. This one is already too long as it is… :-)

For additional content related to Storage Spaces, check these:

PowerShell tips for building objects with custom properties and special formatting

$
0
0

 

I’ve been building a number of scripts that query information using PowerShell.

To create those, I used some PowerShell tricks to make the output look just like I wanted. This post is a compilation of these tricks.

The first few tricks are simple, but they grow increasingly complex towards the end.

The examples here are geared towards SMB Shares and Volumes, but you can apply these concepts in many, many other situations.

 

1) Using –AutoSize

 

I do not like the default way that PowerShell spaces out fields in a query. I prefer them packed on the left, which is what the AutoSize option of the Format-Table cmdlet (FT for short) does.

AutoSize, as the name implies, also adjusts to the size of the properties and avoids showing “…” at the end of the output.

 

PS C:\> Get-SmbShare

Name                          ScopeName                     Path                          Description
----                          ---------                     ----                          -----------
ADMIN$                        *                             C:\windows                    Remote Admin
BackupFiles                   *                             E:\Backup                     Project backup files
C$                            *                             C:\                           Default share
D$                            *                             D:\                           Default share
F$                            *                             F:\                           Default share
Images                        *                             D:\Images                     Pictures to be used in pro...
IPC$                          *                                                           Remote IPC
print$                        *                             C:\windows\system32\spool\... Printer Drivers
Projects                      *                             C:\Projects                   Recent project files

 

PS C:\> Get-SmbShare | FT -AutoSize

Name        ScopeName Path                              Description
----        --------- ----                              -----------
ADMIN$      *         C:\windows                        Remote Admin
BackupFiles *         E:\Backup                         Project backup files
C$          *         C:\                               Default share
D$          *         D:\                               Default share
F$          *         F:\                               Default share
Images      *         D:\Images                         Pictures to be used in projects
IPC$        *                                           Remote IPC
print$      *         C:\windows\system32\spool\drivers Printer Drivers
Projects    *         C:\Projects                       Recent project files

 

2) Selecting columns to show

 

Every object has a default view with a specific set of columns. If you don’t like those, you can select your own. To find out what fields you can use, you can use a “Select *” or a “Get-Member” to find out.

 

PS C:\> Get-SmbShare | Select * -First 1

PresetPathAcl         :
ShareState            : Online
AvailabilityType      : NonClustered
ShareType             : FileSystemDirectory
FolderEnumerationMode : Unrestricted
CachingMode           : Manual
SmbInstance           : Default
CATimeout             : 0
ConcurrentUserLimit   : 0
ContinuouslyAvailable : False
CurrentUsers          : 0
Description           : Remote Admin
EncryptData           : False
Name                  : ADMIN$
Path                  : C:\windows
Scoped                : False
ScopeName             : *
SecurityDescriptor    : O:SYG:SYD:(A;;GA;;;BA)(A;;GA;;;BO)(A;;GA;;;IU)
ShadowCopy            : False
Special               : True
Temporary             : False
Volume                : \\?\Volume{4304337d-6763-11e3-8255-806e6f6e6963}\
PSComputerName        :
CimClass              : ROOT/Microsoft/Windows/SMB:MSFT_SmbShare
CimInstanceProperties : {AvailabilityType, CachingMode, CATimeout, ConcurrentUserLimit...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties

PS C:\> Get-SmbShare | Get-Member

   TypeName: Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/SMB/MSFT_SmbShare

Name                      MemberType     Definition
----                      ----------     ----------
Clone                     Method         System.Object ICloneable.Clone()
Dispose                   Method         void Dispose(), void IDisposable.Dispose()
Equals                    Method         bool Equals(System.Object obj)
GetCimSessionComputerName Method         string GetCimSessionComputerName()
GetCimSessionInstanceId   Method         guid GetCimSessionInstanceId()
GetHashCode               Method         int GetHashCode()
GetObjectData             Method         void GetObjectData(System.Runtime.Serialization.SerializationInfo info, Sys...
GetType                   Method         type GetType()
ToString                  Method         string ToString()
CATimeout                 Property       uint32 CATimeout {get;set;}
ConcurrentUserLimit       Property       uint32 ConcurrentUserLimit {get;set;}
ContinuouslyAvailable     Property       bool ContinuouslyAvailable {get;set;}
CurrentUsers              Property       uint32 CurrentUsers {get;set;}
Description               Property       string Description {get;set;}
EncryptData               Property       bool EncryptData {get;set;}
Name                      Property       string Name {get;}
Path                      Property       string Path {get;}
PSComputerName            Property       string PSComputerName {get;}
Scoped                    Property       bool Scoped {get;}
ScopeName                 Property       string ScopeName {get;}
SecurityDescriptor        Property       string SecurityDescriptor {get;set;}
ShadowCopy                Property       bool ShadowCopy {get;}
Special                   Property       bool Special {get;}
Temporary                 Property       bool Temporary {get;}
Volume                    Property       string Volume {get;}
AvailabilityType          ScriptProperty System.Object AvailabilityType {get=[Microsoft.PowerShell.Cmdletization.Gen...
CachingMode               ScriptProperty System.Object CachingMode {get=[Microsoft.PowerShell.Cmdletization.Generate...
FolderEnumerationMode     ScriptProperty System.Object FolderEnumerationMode {get=[Microsoft.PowerShell.Cmdletizatio...
PresetPathAcl             ScriptProperty System.Object PresetPathAcl {get=$acl = Get-Acl ($this.PSBase.CimInstancePr...
ShareState                ScriptProperty System.Object ShareState {get=[Microsoft.PowerShell.Cmdletization.Generated...
ShareType                 ScriptProperty System.Object ShareType {get=[Microsoft.PowerShell.Cmdletization.GeneratedT...
SmbInstance               ScriptProperty System.Object SmbInstance {get=[Microsoft.PowerShell.Cmdletization.Generate...

 

PS C:\> Get-SmbShare | FT Name, Path, Special, AvailabilityType -AutoSize

Name        Path                              Special AvailabilityType
----        ----                              ------- ----------------
ADMIN$      C:\windows                           True     NonClustered
BackupFiles E:\Backup                           False     NonClustered
C$          C:\                                  True     NonClustered
D$          D:\                                  True     NonClustered
F$          F:\                                  True     NonClustered
Images      D:\Images                           False     NonClustered
IPC$                                             True     NonClustered
print$      C:\windows\system32\spool\drivers   False     NonClustered
Projects    C:\Projects                         False     NonClustered

 

3) Selecting rows to show

 

You can restrict the items to show based on any of its properties. You need to learn to use the many types of operators like equal (-eq), not equal (-ne), greater than (-gt), like (-like), not like (-not like) and many others.

The cmdlet used is Where-Object, but it can be abbreviated as Where or simply a question mark. There is a simple form for querying just one property and also a more complex form for using expressions.

For instance, to show all shares that are not special, you can one of these:
Get-SmbShare | Where-Object {$_.Special –ne $true}
Get-SmbShare | ? Special –ne $true

If you use the form with the expression in {}, you must specify $_.property, where $_ means “the current item we’re processing”. The simpler form without {} can be used with only one property.

Here’s a more complex example to show all shares that are not special and with a description starting with the letter P:
Get-SmbShare | ? { $_.Special -ne $true -and $_.Description -like "P*" }

 

PS C:\> Get-SmbShare | Where-Object {$_.Special –ne $true} | FT -AutoSize

Name        ScopeName Path                              Description
----        --------- ----                              -----------
BackupFiles *         E:\Backup                         Project backup files
Images      *         D:\Images                         Pictures to be used in projects
print$      *         C:\windows\system32\spool\drivers Printer Drivers
Projects    *         C:\Projects                       Recent project files

PS C:\> Get-SmbShare | ? Special –ne $true| FT -AutoSize

Name        ScopeName Path                              Description
----        --------- ----                              -----------
BackupFiles *         E:\Backup                         Project backup files
Images      *         D:\Images                         Pictures to be used in projects
print$      *         C:\windows\system32\spool\drivers Printer Drivers
Projects    *         C:\Projects                       Recent project files

PS C:\> Get-SmbShare | ? Special | FT -AutoSize

Name   ScopeName Path       Description
----   --------- ----       -----------
ADMIN$ *         C:\windows Remote Admin
C$     *         C:\        Default share
D$     *         D:\        Default share
F$     *         F:\        Default share
IPC$   *                    Remote IPC

PS C:\> Get-SmbShare | ? { $_.Special -ne $true -and $_.Description -like "P*" } | FT -AutoSize

Name        ScopeName Path                              Description
----        --------- ----                              -----------
BackupFiles *         E:\Backup                         Project backup files
Images      *         D:\Images                         Pictures to be used in projects
print$      *         C:\windows\system32\spool\drivers Printer Drivers

 

4) Creating custom columns

 

In addition to the ability to select which columns to show, you can also create custom tables with any expression. This is useful for creating new calculated columns based on the existing ones.

You can also use this same process to rename existing properties (if you don’t like their default names) or customize the alignment/size of the column.

As with the full form of the “Where” filters, the expressions here must be enclosed in {} and references to existing properties must be preceded with $_.

The syntax uses a hash table, which is little unusual. You should include at least a “Label” (or “Name”) and an “Expression” item in the hash table. You can also specify “Alignment” (or “Align”) and “Width”.

Here’s an example to rename the “Path” property to “Folder”:
Get-SmbShare | FT Name, @{ Label=”Folder”; Expression={$_.Path} }, Description –AutoSize

Here’s another example showing only the drive letter of the path:
Get-SmbShare | FT Name, Description, @{ Name=”Drive”; Expression={$_.Path.Substring(0,1)}; Alignment=”Center” } –AutoSize

Lastly, a more complex example showing that shares ending with $ are hidden:
Get-SmbShare | FT Name, Path, @{ Align="Center"; Expression={If ($_.Name –like “*$”) {“Yes”} else {“No”} }; Label=”Hidden” } –AutoSize

It’s a lot of curly braces, I know. Just make sure you keep good track of them.

 

PS C:\> Get-SmbShare | FT Name, @{ Label=”Folder”; Expression={$_.Path} }, Description –AutoSize

Name        Folder                            Description
----        ------                            -----------
ADMIN$      C:\windows                        Remote Admin
BackupFiles E:\Backup                         Project backup files
C$          C:\                               Default share
D$          D:\                               Default share
F$          F:\                               Default share
Images      D:\Images                         Pictures to be used in projects
IPC$                                          Remote IPC
print$      C:\windows\system32\spool\drivers Printer Drivers
Projects    C:\Projects                       Recent project files

 
PS C:\> Get-SmbShare | FT Name, Description, @{ Name=”Drive”; Expression={$_.Path.Substring(0,1)}; Alignment=”Center” } –AutoSize

Name        Description                     Drive
----        -----------                     -----
ADMIN$      Remote Admin                      C
BackupFiles Project backup files              E
C$          Default share                     C
D$          Default share                     D
F$          Default share                     F
Images      Pictures to be used in projects   D
IPC$        Remote IPC
print$      Printer Drivers                   C
Projects    Recent project files              C

 

PS C:\> Get-SmbShare | FT Name, Path, @{ Align="Center"; Expression={If ($_.Name –like “*$”) {“Yes”} else {“No”} }; Label=”Hidden” } –AutoSize

Name        Path                              Hidden
----        ----                              ------
ADMIN$      C:\windows                         Yes
BackupFiles E:\Backup                           No
C$          C:\                                Yes
D$          D:\                                Yes
F$          F:\                                Yes
Images      D:\Images                           No
IPC$                                           Yes
print$      C:\windows\system32\spool\drivers  Yes
Projects    C:\Projects                         No

 

PS C:\> Get-Volume | Sort DriveLetter | FT DriveType, DriveLetter, FileSystem, @{Expression={ [int] ($_.Size/1MB) }; Label="Total (MB)"; Align="Right" }, @{Expression={ [int] (($_.Size-$_.SizeRemaining)/1MB) }; Label="Used (MB)"; Align="Right" }, @{Expression={ [int] ($_.SizeRemaining/1MB) }; Label="Free (MB)"; Align="Right" }, @{Expression={ [int]($_.SizeRemaining/$_.Size*100) }; Label="Free %"; Align="Right" } –AutoSize

DriveType DriveLetter FileSystem Total (MB) Used (MB) Free (MB) Free %
--------- ----------- ---------- ---------- --------- --------- ------
Fixed                 NTFS              350       287        63     18
Fixed               C NTFS           243845    214308     29537     12
Fixed               D NTFS           476937     56928    420009     88
Removable           E NTFS           125903     20925    104978     83
Fixed               F NTFS           476938    137181    339757     71

 

PS C:\> dir d:\*.* -Recurse | Select @{Expression={$_.CreationTime.Year};Label="YearCreated"}, @{Expression={$_.CreationTime.Month};Label="MonthCreated"} | Group YearCreated, MonthCreated | Select @{Expression={$_.Name.Split(",")[0].Trim()};Label="Year"}, @{Expression={$_.Name.Split(",")[1].Trim()};Label="Month"}, Count | Sort Count -Descending | FT Year, Month, Count -AutoSize

Year Month Count
---- ----- -----
2013 7     10172
2013 8      9114
2013 10     9097
2013 9      4075
2014 2       483
2013 4        47
2012 2        16
2013 11       15
2013 6         5
2013 12        4
2014 4         3
2013 5         2
2012 12        2
2012 5         1

 

 

5) Formatting numeric fields

 

One interesting trick when creating expressions is to format numbers. There is a specific –f operator that you can use to format numbers with comma separators, fixed number of decimal places, currency format and also percentages.

The format string can include references to multiple numbers, so you must specify the index for the number in {}. Here’s an example using 3 numbers.

PS C:\> "Note that {1} times {0} equals {2}" -f 123, 2, 246
Note that 2 times 123 equals 246

Beside the index, you can can specify a colon plus a letter indicating the type of formatting followed by the number of decimal points to use. Types of formatting include C for currency, N for Numeric (just comma separators), P for Percentage and E for Exponential. Here are a few examples:

PS C:\> "They spent {0:C2} of the total {1:C2} they had. They spent {2:P2}." -f 12.34, 45.67, (12.34/45.67)
They spent $12.34 of the total $45.67 they had. They spent 27.02 %.

PS C:\> "The number {0:N2} in exponential notation is {0:E6}" -f 123456.789
The number 123,456.79 in exponential notation is 1.234568E+005

Now if you combine this new formatting feature with the expressions the previous items, you can get quite powerful results:

PS C:\> Get-Volume | Sort DriveLetter | FT DriveType, DriveLetter, FileSystem, @{Expression={ "{0:N0}" -f ($_.Size/1MB) }; Label="Total (MB)"; Align="Right" }, @{Expression={ "{0:N0}" -f (($_.Size-$_.SizeRemaining)/1MB) }; Label="Used (MB)"; Align="Right" }, @{Expression={ "{0:N0}" -f ($_.SizeRemaining/1MB) }; Label="Free (MB)"; Align="Right" }, @{Expression={ "{0:P2}" -f ($_.SizeRemaining/$_.Size) }; Label="Free %"; Align="Right" } -AutoSize

DriveType DriveLetter FileSystem Total (MB) Used (MB) Free (MB)  Free %
--------- ----------- ---------- ---------- --------- ---------  ------
Fixed                 NTFS              350       287        63 18.09 %
Fixed               C NTFS          243,845   213,652    30,193 12.38 %
Fixed               D NTFS          476,937    56,928   420,009 88.06 %
Removable           E NTFS          125,903    20,925   104,978 83.38 %
Fixed               F NTFS          476,938   137,181   339,757 71.24 %

 

6) Linking two tables

 

One useful trick is to find the relationship between objects and create a single query that shows information coming from both of them.

For instance, you might want to show the free space in the volume when showing information about a share. Or you might want to show all volumes with their associated shares.

This usually involves looping through the items in one table using the For-Each cmdlet, which can be abbreviated as %. This also involves using $_ to refer to the properties of the table being looped through.

In other to show the correct association, you commonly need to use matching or related properties from both tables. If you come from the relational database world, think of a foreign key.

Because you’re dealing with two tables, you might need to assign the outer $_ to a specific variable, so you can compare fields from the outer table with the inner table.

Here’s an example showing all volumes and their associated file shares:
Get-Volume | Sort DriveLetter | % { $V=$_; $V | FT -AutoSize; Get-SmbShare | ? {$V.ObjectID –eq $_.Volume} | FT Name, Path -AutoSize }

Here’s another example showing all shares and the free space on the associated volume:
Get-SmbShare | ? Special -ne $true | % { $_ | FT Name, Path -AutoSize; Get-Volume –ObjectID $_.Volume | FT DriveLetterSize, SizeRemaining}

 

PS C:\> Get-Volume | Sort DriveLetter | % { $V=$_; $V | FT -AutoSize; Get-SmbShare | ? {$V.ObjectID –eq $_.Volume} | FT Name, Path -AutoSize }

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining   Size
----------- --------------- ---------- --------- ------------ -------------   ----
            System Reserved NTFS       Fixed     Healthy            63.3 MB 350 MB

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining      Size
----------- --------------- ---------- --------- ------------ -------------      ----
C           SSD1            NTFS       Fixed     Healthy           29.49 GB 238.13 GB

Name      Path
----      ----
ADMIN$    C:\windows
C$        C:\
print$    C:\windows\system32\spool\drivers
Projects  C:\Projects

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining      Size
----------- --------------- ---------- --------- ------------ -------------      ----
D           HDD             NTFS       Fixed     Healthy          410.17 GB 465.76 GB

Name   Path
----   ----
D$     D:\
Images D:\Images

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining      Size
----------- --------------- ---------- --------- ------------ -------------      ----
E           SDCard          NTFS       Removable Healthy          102.52 GB 122.95 GB

Name        Path
----        ----
BackupFiles E:\Backup

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining      Size
----------- --------------- ---------- --------- ------------ -------------      ----
F           USB3            NTFS       Fixed     Healthy          331.79 GB 465.76 GB

Name Path
---- ----
F$   F:\

 

PS C:\> Get-SmbShare | ? Special -ne $true | % { $_ | FT Name, Path -AutoSize; Get-Volume –ObjectID $_.Volume | FT DriveLetter, Size, SizeRemaining}

Name        Path
----        ----
BackupFiles E:\Backup

DriveLetter         Size SizeRemaining
-----------         ---- -------------
          E 132018860032  110077665280

Name   Path
----   ----
Images D:\Images

DriveLetter         Size SizeRemaining
-----------         ---- -------------
          D 500104687616  440411648000

Name   Path
----   ----
print$ C:\windows\system32\spool\drivers

DriveLetter         Size SizeRemaining
-----------         ---- -------------
          C 255690010624   31659585536

Name     Path
----     ----
Projects C:\Projects

DriveLetter         Size SizeRemaining
-----------         ---- -------------
          C 255690010624   31659585536

 

7) Creating a few fake fields

 

Another useful trick is to create a temporary object with a few fake properties that you can fill in with some scripting. This requires using variables to store the temporary results and a little more understanding of programming structures like loops.

This provides a better way to combine two related tables into a single view, like we did in the previous item. But this time we get a single, combined output.

For instance, Get-SmbShare will return a volume ID that you can link to a volume, but it would be nice if we could have a single query with some properties from the share and some from the volume.

Here’s what you would do: First, create a variable with the result of Get-SmbShare, including the properties you want to fill later. These won’t exist initially, so they start empty. Then we’ll loop through the items and fill those empty properties using a query for the volume ID. After that, the results are ready to be formatted using any of our previous tricks…

 

PS C:\> $Shares = Get-SmbShare | ? { $_.Special -ne $true} | Select Name, Path, Volume, Total, Used, Free
 

PS C:\> $Shares | FT -AutoSize

Name        Path                              Volume                                            Total Used Free
----        ----                              ------                                            ----- ---- ----
BackupFiles E:\Backup                         \\?\Volume{a68e6379-6763-11e3-8256-d89d67d108b9}\
Images      D:\Images                         \\?\Volume{4304337f-6763-11e3-8255-806e6f6e6963}\
print$      C:\windows\system32\spool\drivers \\?\Volume{4304337d-6763-11e3-8255-806e6f6e6963}\
Projects    C:\Projects                       \\?\Volume{4304337d-6763-11e3-8255-806e6f6e6963}\

PS C:\> $Shares | % { $S=$_; $V=Get-Volume | ? ObjectId -eq $S.Volume; $S.Total=$V.Size/1MB; $S.Free=$V.SizeRemaining/1MB; $S.Used=($V.Size-$V.SizeRemaining)/1MB }
 

PS C:\> $Shares | Sort Name | FT Name, Path, @{Expression={ "{0:N0}" -f $_.Total }; Label="Total (MB)"; Align="Right" }, @{Expression={ "{0:N0}" -f $_.Used }; Label="Used (MB)"; Align="Right" }, @{Expression={ "{0:N0}" -f $_.Free }; Label="Free (MB)"; Align="Right" }, @{Expression={ "{0:P2}" -f ($_.Free/$_.Total) }; Label="Free %"; Align="Right" } -AutoSize

Name        Path                              Total (MB) Used (MB) Free (MB)  Free %
----        ----                              ---------- --------- ---------  ------
BackupFiles E:\Backup                            125,903    20,925   104,978 83.38 %
Images      D:\Images                            476,937    56,928   420,009 88.06 %
print$      C:\windows\system32\spool\drivers    243,845   213,652    30,193 12.38 %
Projects    C:\Projects                          243,845   213,652    30,193 12.38 %

 

8) Creating entirely fake tables

 

You can also create entirely new objects using a trick similar to the previous one. You start by creating a new item simply piping an empty variable to a Select cmdlet that specifies the columns you want to create.

PS C:\> $Alerts = "" | Select Severity, Entity, Instance, Description

Then you can use any cmdlets to populate that item’s columns and sent them out.

PS C:\> Get-Volume | ? {($_.SizeRemaining/$_.Size) -lt 0.8} | % { $Alerts.Severity="Warning"; $Alerts.Entity="Volume"; $Alerts.Instance = $_.DriveLetter+" "+$_.ObjectID; $Alerts.Description="Volume has less than 80% free space"; $Alerts} | FT -AutoSize

Severity Entity Instance                                            Description
-------- ------ --------                                            -----------
Warning  Volume   \\?\Volume{4304337c-6763-11e3-8255-806e6f6e6963}\ Volume has less than 80% free space
Warning  Volume F \\?\Volume{c9337eca-6774-11e3-825a-b8763fd91487}\ Volume has less than 80% free space
Warning  Volume C \\?\Volume{4304337d-6763-11e3-8255-806e6f6e6963}\ Volume has less than 80% free space

This gets even more useful if you pack it as a PowerShell function, which you can name just like a regular cmdlet:

Function Get-StorageAlert
{

    $A = "" | Select Severity, Entity, Instance, Description

    Get-Volume | ? DriveLetter | ? {($_.SizeRemaining/$_.Size) -lt 0.8} | % {
        $A.Severity="Warning"
        $A.Entity="Volume"
        $A.Instance = $_.DriveLetter
        $A.Description="Volume has less than 80% free space"
        $A
    }

    Get-SmbShare -ContinuouslyAvailable $false | ? {$_.Special -ne $true} | % {
        $A.Severity="Warning"
        $A.Entity="Share"
        $A.Instance = $_.Name
        $A.Description="Share is not continuously available"
        $A
    }

}

Here’s a sample output:

PS C:\> Get-StorageAlert | FT -AutoSize

Severity Entity             Instance Description
-------- ------             -------- -----------
Warning  Volume                    F Volume has less than 80% free space
Warning  Volume                    C Volume has less than 80% free space
Warning  Share           BackupFiles Share is not continuously available
Warning  Share                Images Share is not continuously available
Warning  Share                print$ Share is not continuously available
Warning  Share              Projects Share is not continuously available

Building your schedule for TechEd 2014? Here are some Storage-related sessions!

$
0
0

 

TENA2014_PMS288

TechEd NorthAmerica 2014 is just a few weeks away and it’s a sold-out event now.

If you’re attending and you haven’t yet started building your schedule, you can consider yourself officially late. :-)

If you’re focused on Private Cloud Storage and High Availability, let me suggest a few Breakout Sessions, Instructor-Led Labs (ILL) and Hands-On Labs (HOL) that you should consider:

  

TypeTitlePresenter(s)Date/Time
FoundationalFDN06 Transform the Datacenter: Making the Promise of Connected Clouds a RealityBrian Hillger,
Elden Christensen,
Jeff Woolsey,
Jeffrey Snover,
Matt McSpirit
Mon 11:00 AM
BreakoutDCIM-B349 Software-Defined Storage in Windows Server 2012 R2 and Microsoft System Center 2012 R2Elden Christensen,
Hector Linares,
Jose Barreto
Wed 8:30 AM
BreakoutDCIM-B354 Failover Clustering: What's New in Windows Server 2012 R2Elden Christensen,
John Marlin
Tue 1:30 PM
BreakoutDCIM-B337 File Server Networking for a Private Cloud Storage Infrastructure in Windows Server 2012 R2Jose BarretoTue 3:15 PM
BreakoutDCIM-B333 Distributed File System Replication (DFSR) Scalability Enhancements in Windows Server 2012 R2Ned PyleWed 5:00 PM
BreakoutDCIM-B335 Microsoft Storage Solutions in Production EnvironmentsPrabu RambadranTue 1:30 PM
BreakoutDCIM-B364 Step-by-step to Deploying Microsoft SQL Server 2014 with Cluster Shared VolumesSubhasish BhattacharyaThu 8:30 AM
BreakoutDCIM-B310 The StorSimple Approach to Solving Issues Related to Growing Data TrendsBadri Venkatachari,
Marc Farley
Mon 3:00 PM
BreakoutDCIM-B357 StorSimple: Enabling Microsoft Azure Cloud Storage for Enterprise WorkloadsJai Desai ,
Meghan Liese
Wed 1:30 PM
BreakoutDCIM-B311 Delivering Exceptional IOPS/$ with Windows Server 2012 R2Bryan Matthew,
Tobias Klima
Mon 1:15 PM
BreakoutDCIM-B346 Best Practices for Deploying Tiered Storage Spaces in Windows Server 2012 R2Bryan Matthew,
Tobias Klima
Wed 8:30 AM
BreakoutDCIM-B338 Software-Defined Storage Solutions: Storage Control Plane Functionality in Windows Server 2012 R2 and System Center 2012 R2Hector LinaresMon 1:15 PM
BreakoutDCIM-B327 Cluster-in-a-Box Using Windows Server 2012 R2: Solutions and ApplicationsJohn LoveallTue 8:30 AM
BreakoutPCIT-B214 Using Dynamic Access Control and Rights Management for Information ProtectionNir Ben Zvi,
Stan Symms
Thu 2:45 PM
BreakoutDCIM-B345 Networking Solutions in Action: How Customers Implement Software-Defined Networking Using Windows Server 2012 R2 and System Center 2012 R2Prabu RambadranTue 10:15 AM
BreakoutDCIM-B211 Service Provider Datacenter ArchitecturePhilip MossMon 3:00 PM
BreakoutDCIM-B212 The Enterprise: Be Your Own Cloud ProviderPhilip MossTue 8:30 AM
BreakoutDCIM-B378 Converged Networking for Windows Server 2012 R2 Hyper-VDon Stanwyck,
Taylor Brown
Mon 12:45 PM
BreakoutDBI-B314 CAT: Microsoft SQL Server High Availability and Disaster Recovery in Windows AzureLuis Carlos Vargas HerringThu 2:45 PM
BreakoutDBI-B332 AlwaysOn in Microsoft SQL Server 2014Luis Carlos Vargas HerringMon 1:15 PM
BreakoutDCIM-B313 Best Practices for Virtualizing and Managing Microsoft SharePoint 2013 with Microsoft System Center 2012 R2 and Windows Server 2012 R2Marcos NogueiraMon 3:00 PM
BreakoutOFC-B318 Microsoft Exchange Server 2013 SP1 High Availability and Site ResilienceScott SchnollTue 3:00 PM
BreakoutOFC-B415 Microsoft Lync Server 2013 High Availability and Disaster RecoveryBrandon Bernier,
Bryan Nyce
Tue 10:15 AM
ILLDCIM-IL200 Build Your Storage Infrastructure with Windows Server 2012 R2Prabu RambadranWed 8:30 AM
ILLDCIM-IL200-R Build Your Storage Infrastructure with Windows Server 2012 R2Prabu RambadranWed 5:00 PM
ILLDCIM-IL308 Windows Server 2012 R2: Introduction to Failover Clustering with Hyper-VSymon PerrimanMon 3:00 PM
ILLDCIM-IL308-R Windows Server 2012 R2: Introduction to Failover Clustering with Hyper-VSymon PerrimanTue 1:30 PM
ILLDCIM-IL305 Managing Your Storage with Microsoft System Center 2012 Virtual Machine ManagerPrabu RambadranWed 3:15 AM
HOLDCIM-H205 Build Your Storage Infrastructure with Windows Server 2012 R2  
HOLDCIM-H321 Windows Server 2012 R2: Introduction to Failover Clustering with Hyper-V  
HOLDCIM-H202 Introduction to Microsoft Virtualization, Part 2: Virtual Machine Management  
HOLDBI-H304 Implementing HA/DR with Microsoft SQL Server 2014 AlwaysOn Availability Groups  

 

Get that schedule going. Looking forward to meeting you in Houston…

 

Disclaimers:

  • While I tried to get all sessions related to Windows Server and Storage, I might have missed some. Post a comment if you find more.
  • Sessions could still change date and time. The best thing to do is add them to your schedule builder, which will keep track of those last-minute changes.
  • This list includes Storage sessions related to Private Cloud and Hybrid Cloud (StorSimple), but not Public Cloud (Azure Storage).

Demo details for my TechEd 2014 presentation on File Server Networking

$
0
0

During my TechEd 2014 presentation on File Server Networking for a Private Cloud Storage Infrastructure in Windows Server 2012 R2, I did a demo showing a Scale-Out File Server Cluster. The demo consisted of showing the networking details of this cluster, looking both from the cluster perspective and the client side. I was asked after the presentation to share the details of the PowerShell script that I used. So, here it goes.

 

First, here is the output of the script. It’s broken into a few parts:

  • It starts by showing the cluster configuration (cluster nodes, cluster networks, cluster resources and cluster shared volumes)
  • Note that the name of the cluster itself is JOSE-S and the name of the Scale-Out File Server is JOSE-SO.
  • Then it shows the IP addresses on each node, plus what’s registered on DNS for the scale-out file server name.
  • Next, it outputs the SMB server network information, with focus on the scopes defined on the server.
  • Then we switch to the client view of connections, after just showing the directory from the 3 shares created. This shows that multichannel won’t engage until you have a read or a write.
  • Finally, after running a quick workload on the shares, it shows the full set of 24 connections (3 shares * 2 NICs * 4 connections per NIC).
  • The 10.1.x.100 IP addresses are associated with the cluster name used for cluster management. They don't relate directly to the Scale-Out File Server.
  • The scope name starting with "FE80" is the internal cluster scope used for inter-node communication.

 

Cluster Information

PS C:\> Get-ClusterNode -Cluster JOSE-S

Name    ID State
----    -- -----
JOSE-S1 2  Up
JOSE-S2 1  Up
JOSE-S3 3  Up

PS C:\> Get-ClusterNetwork -Cluster JOSE-S

Cluster Name              State Address  Role
------- ----              ----- -------  ----
JOSE-S  Cluster Network 1    Up 10.1.2.0    3
JOSE-S  Cluster Network 2    Up 10.1.1.0    3

PS C:\> Get-ClusterResource -Cluster JOSE-S

Name                              State  OwnerGroup    ResourceType
----                              -----  ----------    ------------
Cluster Disk 1                    Online Cluster Group Physical Disk
Cluster IP Address                Online Cluster Group IP Address
Cluster IP Address 10.1.1.100     Online Cluster Group IP Address
Cluster Name                      Online Cluster Group Network Name
JOSE-SO                           Online JOSE-SO       Distributed Network Name
Scale-Out File Server (\\JOSE-SO) Online JOSE-SO       Scale Out File Server

PS C:\> Get-ClusterSharedVolume -Cluster JOSE-S

Name           State  Node
----           -----  ----
Cluster Disk 2 Online JOSE-S2
Cluster Disk 3 Online JOSE-S1
Cluster Disk 4 Online JOSE-S3

IP Addresses for each node, DNS for Scale-Out Name

PS C:\> Get-NetIPAddress -CimSession <node>

PSComputerName ifIndex IPAddress  PrefixLength
-------------- ------- ---------  ------------
JOSE-S1             12 10.1.1.100           24
JOSE-S1             12 10.1.1.2             24
JOSE-S1             14 10.1.2.100           24
JOSE-S1             14 10.1.2.2             24

PSComputerName ifIndex IPAddress PrefixLength
-------------- ------- --------- ------------
JOSE-S2             12 10.1.1.3            24
JOSE-S2             14 10.1.2.3            24

PSComputerName ifIndex IPAddress PrefixLength
-------------- ------- --------- ------------
JOSE-S3             12 10.1.1.4            24
JOSE-S3             14 10.1.2.4            24

PS C:\> Resolve-DNSName JOSE-SO

Name              Type TTL  Section IPAddress
----              ---- ---  ------- ---------
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.1.3
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.1.2
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.1.4
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.2.3
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.2.4
JOSE-SO.JOSE.TEST A    1200 Answer  10.1.2.2

IP Addresses on each node per Scope name

PS C:\> Get-SmbServerNetworkInterface -CimSession JOSE-SO

PSComputerName ScopeName                 IPAddress
-------------- ---------                 ---------
JOSE-S1        FE80::9CBF:78F5:DFA8:803B 10.1.2.2
JOSE-S1        FE80::9CBF:78F5:DFA8:803B 10.1.1.2
JOSE-S1        JOSE-S                    10.1.2.100
JOSE-S1        JOSE-S                    10.1.1.100
JOSE-S1        JOSE-SO                   10.1.2.2
JOSE-S1        JOSE-SO                   10.1.1.2

PSComputerName ScopeName                 IPAddress
-------------- ---------                 ---------
JOSE-S2        FE80::69AF:5813:D729:CEFB 10.1.1.3
JOSE-S2        FE80::69AF:5813:D729:CEFB 10.1.2.3
JOSE-S2        JOSE-SO                   10.1.2.3
JOSE-S2        JOSE-SO                   10.1.1.3

PSComputerName ScopeName                 IPAddress
-------------- ---------                 ---------
JOSE-S3        FE80::F4BE:F77B:7EAC:6CED 10.1.1.4
JOSE-S3        FE80::F4BE:F77B:7EAC:6CED 10.1.2.4
JOSE-S3        JOSE-SO                   10.1.2.4
JOSE-S3        JOSE-SO                   10.1.1.4

Simple connection just to check directory

PS C:\> Dir \\JOSE-SO\<share>

    Directory: \\JOSE-SO\Share1

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          5/4/2014   5:40 PM 1717986918 testfile.dat
                                           4

    Directory: \\JOSE-SO\Share2

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          5/4/2014   5:40 PM 1717986918 testfile.dat
                                           4

    Directory: \\JOSE-SO\Share3

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          5/4/2014   5:40 PM 1717986918 testfile.dat
                                           4

SMB Connection

PS C:\> Get-SmbConnection

ServerName ShareName Dialect Redirected Credential
---------- --------- ------- ---------- ----------
JOSE-SO    Share1    3.02          True JOSE.TEST\Administrator
JOSE-SO    Share2    3.02          True JOSE.TEST\Administrator
JOSE-SO    Share3    3.02          True JOSE.TEST\Administrator

TCP connections used by the client

PS C:\> Get-NetTCPConnection -RemotePort 445

LocalAddress RemoteAddress LocalPort RemotePort
------------ ------------- --------- ----------
10.1.1.5     10.1.1.2          49453        445
10.1.1.5     10.1.1.3          49470        445
10.1.1.5     10.1.1.4          49461        445

Putting some load on the shares

PS C:\> C:\SQLIO\SQLIO.EXE -s10 -kR -frandom -b8 -t8 -o16 -LS -BN <file>
sqlio v1.5.SG
using system counter for latency timings, 10000000 counts per second
8 threads reading for 10 secs from files \\JOSE-SO\Share1\testfile.dat, \\JOSE-SO\Share2\testfile.dat and \\JOSE-SO\Share3\testfile.dat
        using 8KB random IOs
        enabling multiple I/Os per thread with 16 outstanding
        buffering set to not use file nor disk caches (as is SQL Server)
using current size: 16384 MB for file: \\JOSE-SO\Share1\testfile.dat
using current size: 16384 MB for file: \\JOSE-SO\Share2\testfile.dat
using current size: 16384 MB for file: \\JOSE-SO\Share3\testfile.dat
initialization done
CUMULATIVE DATA:
throughput metrics:
IOs/sec: 26822.20
MBs/sec:   209.54
latency metrics:
Min_Latency(ms): 0
Avg_Latency(ms): 13
Max_Latency(ms): 171
histogram:
ms: 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24+
%:  0  0  0  0  1  2  4  6  8  8  9  8  8  7  6  5  5  4  3  3  2  2  1  1  7

SMB Connection

PS C:\> Get-SmbConnection

ServerName ShareName Dialect Redirected Credential
---------- --------- ------- ---------- ----------
JOSE-SO    Share1    3.02          True JOSE.TEST\Administrator
JOSE-SO    Share2    3.02          True JOSE.TEST\Administrator
JOSE-SO    Share3    3.02          True JOSE.TEST\Administrator

SMB Multichannel Connection

PS C:\> Get-SmbMultichannelConnection

ClientIPAddress ServerIPAddress CurrentChannels
--------------- --------------- ---------------
10.1.1.5        10.1.1.2                      4
10.1.1.5        10.1.1.3                      4
10.1.1.5        10.1.1.4                      4
10.1.2.5        10.1.2.2                      4
10.1.2.5        10.1.2.3                      4
10.1.2.5        10.1.2.4                      4

TCP connections used by the client

PS C:\> Get-NetTCPConnection -RemotePort 445

LocalAddress RemoteAddress LocalPort RemotePort
------------ ------------- --------- ----------
10.1.1.5     10.1.1.2          49511        445
10.1.1.5     10.1.1.2          49513        445
10.1.1.5     10.1.1.2          49516        445
10.1.1.5     10.1.1.2          49480        445
10.1.1.5     10.1.1.3          49518        445
10.1.1.5     10.1.1.3          49497        445
10.1.1.5     10.1.1.3          49512        445
10.1.1.5     10.1.1.3          49515        445
10.1.1.5     10.1.1.4          49514        445
10.1.1.5     10.1.1.4          49517        445
10.1.1.5     10.1.1.4          49492        445
10.1.1.5     10.1.1.4          49509        445
10.1.2.5     10.1.2.2          49498        445
10.1.2.5     10.1.2.2          49501        445
10.1.2.5     10.1.2.2          49508        445
10.1.2.5     10.1.2.2          49505        445
10.1.2.5     10.1.2.3          49500        445
10.1.2.5     10.1.2.3          49510        445
10.1.2.5     10.1.2.3          49506        445
10.1.2.5     10.1.2.3          49503        445
10.1.2.5     10.1.2.4          49507        445
10.1.2.5     10.1.2.4          49502        445
10.1.2.5     10.1.2.4          49499        445
10.1.2.5     10.1.2.4          49504        445

  

Next, here’s the PowerShell script behind what was shown above. Here are a few notes on the script:

  • It shows some text with a simplified view of the cmdlet about to be run, but the actual cmdlet is usually a bit more complex since it usually includes additional parameters and some formatting.
  • I tried to use some color and extra blank lines so things would be easier to read.
  • The “read-host” cmdlets are used to pause the script until I press enter to continue to the next phase.
  • I pipe the results to “Out-Host” to make sure everything shows in proper order on the screen (without it, some of the longer running cmdlets might show out of order).
  • The script is run from a client, so cmdlets that target the cluster use the –Cluster parameter and cmdlets that target a specific server use the –CimSession parameter.
  • SQLIO is used as a workload generator. For more details, see this other blog post on using SQLIO.
  • I make a point of using the PowerShell cmdlets for network information (Resolve-DnsName instead of NSLOOKUP.EXE, Get-NetTcpConnection instead of NETSTAT.EXE).

 

Cls

Write-Host -ForegroundColor Green "Cluster Information"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-ClusterNode -Cluster JOSE-S"
Get-ClusterNode -Cluster JOSE-S | FT -AutoSize | Out-Host

Write-Host -ForegroundColor Yellow "PS C:\> Get-ClusterNetwork -Cluster JOSE-S"
Get-ClusterNetwork -Cluster JOSE-S | FT Cluster, Name, State, Address, Role -AutoSize | Out-Host

Write-Host -ForegroundColor Yellow "PS C:\> Get-ClusterResource -Cluster JOSE-S"
Get-ClusterResource -Cluster JOSE-S  | FT -AutoSize | Out-Host

Write-Host -ForegroundColor Yellow "PS C:\> Get-ClusterSharedVolume -Cluster JOSE-S"
Get-ClusterSharedVolume -Cluster JOSE-S  | FT -AutoSize | Out-Host

Read-Host

Write-Host -ForegroundColor Green "IP Addresses for each node, DNS for Scale-Out Name"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-NetIPAddress -CimSession <node>"
"JOSE-S1", "JOSE-S2", "JOSE-S3" | % { Get-NetIPAddress -CimSession $_ -AddressFamily IPv4 -IPAddress 10.1.* | Sort IPAddress | FT PSComputerName, ifIndex, IPAddress, PrefixLength -AutoSize } | Out-Host

Write-Host -ForegroundColor Yellow "PS C:\> Resolve-DNSName JOSE-SO"
Resolve-DnsName JOSE-SO | FT -AutoSize | Out-Host

Read-Host

Write-Host -ForegroundColor Green "IP Addresses on each node per Scope name", ""
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-SmbServerNetworkInterface -CimSession JOSE-SO"
1..3 | % { Get-SmbServerNetworkInterface -CimSession JOSE-S$_ | ? ScopeName -ne "*" | Sort ScopeName | FT PSComputerName, ScopeName, IPAddress -AutoSize }  | Out-Host

Read-Host

Write-Host -ForegroundColor Green "Simple connection just to check directory", ""
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Dir \\JOSE-SO\<share>"
Dir \\JOSE-SO\Share1\testfile.dat, \\JOSE-SO\Share2\testfile.dat, \\JOSE-SO\Share3\testfile.dat  | Out-Host

Write-Host -ForegroundColor Green "SMB Connection", ""
Write-Host " "
Write-Host -ForegroundColor Yellow "PS C:\> Get-SmbConnection"
Get-SmbConnection | FT ServerName, ShareName, Dialect, Redirected, Credential -AutoSize  | Out-Host

Write-Host -ForegroundColor Green "TCP connections used by the client"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-NetTCPConnection -RemotePort 445"
Get-NetTCPConnection -RemotePort 445 | Sort LocalAddress, RemoteAddress | FT LocalAddress, RemoteAddress, LocalPort, RemotePort -AutoSize  | Out-Host
Read-Host

Write-Host -ForegroundColor Green "Putting some load on the shares", ""
Write-Host " "
Write-Host -ForegroundColor Yellow "PS C:\> C:\SQLIO\SQLIO.EXE -s10 -kR -frandom -b8 -t8 -o16 -LS -BN <file>"
C:\SQLIO\SQLIO.EXE -s10 -kR -frandom -b8 -t8 -o16 -LS -BN \\JOSE-SO\Share1\testfile.dat \\JOSE-SO\Share2\testfile.dat \\JOSE-SO\Share3\testfile.dat

Write-Host -ForegroundColor Green "SMB Connection"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-SmbConnection"
Get-SmbConnection | FT ServerName, ShareName, Dialect, Redirected, Credential -AutoSize | Out-Host

Write-Host -ForegroundColor Green "SMB Multichannel Connection"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-SmbMultichannelConnection"
Get-SmbMultichannelConnection | Sort ClientIPAddress, ServerIPAddress | FT ClientIPAddress, ServerIPAddress, CurrentChannels | Out-Host

Write-Host -ForegroundColor Green "TCP connections used by the client"
Write-Host " "

Write-Host -ForegroundColor Yellow "PS C:\> Get-NetTCPConnection -RemotePort 445"
Get-NetTCPConnection -RemotePort 445 | Sort LocalAddress, RemoteAddress | FT LocalAddress, RemoteAddress, LocalPort, RemotePort –AutoSize | Out-Host

 

You can find the slides and the recording for the presentation at http://channel9.msdn.com/Events/TechEd/NorthAmerica/2014/DCIM-B337

Sample C# code for using the latest WMI classes to manage Windows Storage

$
0
0

 

This blog post shows a bit of C# code to use the Windows Storage Management API (SM-API) classes that were introduced in Windows Server 2012 and Windows 8.

You can find a list of these classes at class described at http://msdn.microsoft.com/en-us/library/hh830612.aspx, including MSFT_PhysicalDisk, MSFT_StoragePool or MSFT_VirtualDisk.

I found a number of examples with the old interface using the old classes like Win32_Volume, but few good ones with the new classes like MSFT_Volume.

This is some simple C# code using console output. The main details to highlight here are the use of System.Management and how to specify the scope, which allows you to manage a remote computer.

Please note that you might need to enable WMI on the computer, which can be easily done with the command line “winrm quickconfig”.

 

Here is the source code, for the console application, which lists information about volumes and physical disks on the local machine.

 

using System;
using System.Text;
using System.Threading;
using System.Management;

namespace SMAPIQuery
{
    class Program
    {
        static void Main(string[] args)
        {
            // Use the Storage management scope
            ManagementScope scope = new ManagementScope("\\\\localhost\\ROOT\\Microsoft\\Windows\\Storage");
            // Define the query for volumes
            ObjectQuery query = new ObjectQuery("SELECT * FROM MSFT_Volume");

            // create the search for volumes
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
            // Get the volumes
            ManagementObjectCollection allVolumes = searcher.Get();
            // Loop through all volumes
            foreach (ManagementObject oneVolume in allVolumes)
            {
                // Show volume information
                if (oneVolume["DriveLetter"].ToString()[0] > ' '  )
                {
                    Console.WriteLine("Volume '{0}' has {1} bytes total, {2} bytes available", oneVolume["DriveLetter"], oneVolume["Size"], oneVolume["SizeRemaining"]);
                }
            }

            // Define the query for physical disks
            query = new ObjectQuery("SELECT * FROM MSFT_PhysicalDisk");

            // create the search for physical disks
            searcher = new ManagementObjectSearcher(scope, query);

            // Get the physical disks
            ManagementObjectCollection allPDisks = searcher.Get();

            // Loop through all physical disks
            foreach (ManagementObject onePDisk in allPDisks)
            {
                // Show physical disk information
                Console.WriteLine("Disk {0} is model {1}, serial number {2}", onePDisk["DeviceId"], onePDisk["Model"], onePDisk["SerialNumber"]);
            }

            Console.ReadLine();
         }
        }
    }

 

Here is some sample output from this application:

 

Volume 'D' has 500104687616 bytes total, 430712184832 bytes available
Volume 'E' has 132018860032 bytes total, 110077665280 bytes available
Volume 'F' has 500105216000 bytes total, 356260683776 bytes available
Volume 'C' has 255690010624 bytes total, 71789502464 bytes available

Disk 2 is model SD              , serial number
Disk 0 is model MTFDDAK256MAM-1K12, serial number         131109303905
Disk 3 is model 5AS             , serial number 00000000e45ca01b30c1
Disk 1 is model ST9500325AS, serial number             6VEK9B89

Using file copy to measure storage performance – Why it’s not a good idea and what you should do instead

$
0
0

1. Introduction

Every once in a while I hear from someone that they believe they have a performance problem with their Scale-Out File Server. When I dig a little further, it’s very common to find that file copies are being used as the mechanism for measuring storage performance for all kinds of scenarios.

This blog post is about why file copies are not a good metric for evaluating storage performance. It also covers what other tools you could use instead to measure things. As usual, my focus here is on copies that use SMB3 file shares or File Server Clusters.

 

2. Why people use file copies to measure storage performance

First of all, it’s important to understand why people use file copies to measure performance. There are actually quite a few reasons:

 

2.1. It’s so easy…

File copies are a simple thing to do. You can even do it from File Explorer.

 

2.2. It’s so pretty…

File Explorer now has a nice visualization of the file copy operation, including a chart showing bandwidth as the copy progresses.

clip_image002

 

2.3. I have lots of large VHDX files sitting around ready to copy

We now have many large VHDX files readily available for testing file copies, and they will take a while to transfer. When someone is looking for a simple way to generate IOs against a storage subsystem, they might be tempted to simply copy those files in or out.

 

2.4. Someone told me it was a good idea

There are a lot of blog posts and demo videos out there about how fast file copies are in this new storage system or this new protocol. I might have done that myself a few times (sorry about that).

 

3. Why using file copies to measure storage performance is not a good idea

Using file copy to measure storage performance has a number of issues. You might essentially end up reaching incorrect conclusions. Here are a few reasons for that:

 

3.1. Copy might not be optimized

In order to get the most of your storage subsystem, you need to queue up enough IO requests to keep the entire system busy end-to-end. For instance, when using hard disk drives, we like to watch the queue depth performance counters to make sure we maintain at least two IOs queued for each HDD you have in a system.

In order to take advantage of this, when you’re copying large files using the Windows copy engine, it will issue 8 asynchronous writes of 1MB each by default. However, when copying lots of small files (and using a fast storage backend), you are less likely to stand up the required IO queue depth unless you queue more IOs and use multiple threads.

To make matters worse, most file copy programs will copy only one file at a time, waiting for one file copy to finish before starting the next one. This serialization will give you a much lower storage performance than the system is actually capable of delivering when more requests are being queued in parallel.

The SMB protocol is able to queue up multiple asynchronous requests, but that does not happen unless the application (the file copy program in this case) takes advantage of it. ROBOCOPY is one of these programs that can use multiple threads to copy multiple files at once.

More importantly, the file copy behavior is not a good stand-in for all other workloads. You will find that its behavior is different from a SQL Server OLTP databases or a Hyper-V Virtual Desktop deployment, both in regards to IO sizes and the number of IOs that are queued up.

 

3.2. Every copy has two sides

People will often forget that file copies measure the performance of both source storage and the destination storage.

If you’re copying from a single slow disk at the source to 10 fast disks in a striped volume on the other end, the speed at which you can read from that source will determine the overall speed of the file copy process.

You’re basically measuring the performance of the slower of the two sides.

 

3.3. Offloads and caching

There are a number of specific technologies that can accelerate certain kinds of copies like Offloaded Data Transfers (ODX) and SMB file copy acceleration (COPYCHUNK) which will impact certain kinds of file copies and it might be hard to determine when they apply or not.

File copies will attempt to use buffered IOs, which can be accelerated by regular windows file caching. On the other hand, buffered file copies will not be accelerated by cluster CSV caching, which only accelerates unbuffered IOs.

As with item 3.1, these are examples of how file copy performance will not match the performance of other types of workload, like an OLTP database or a VDI deployment.

 

3.4. CA will not cache

Continuously Available (CA) file shares are commonly used to provide Hyper-V and SQL Server with a storage solution that will transparently failover in case of node failure.

In order to deliver on its availability promise, CA file shares will make sure that every write goes straight to disk (write-through) and no writes are cached only in RAM. That’s how SMB can recover from the failure of a file server node at any time without data loss.

While this is great for resiliency, it will slow down file copies, particularly if you are copying a single large file.

It’s important to note that most server workloads (including SQL Server and Hyper-V) will always use write-through regardless of CA, so while file copies are affected by the write-through behavior change caused by CA, most server workloads are not.

You can read more about this at http://blogs.technet.com/b/filecab/archive/2013/12/05/to-scale-out-or-not-to-scale-out-that-is-the-question.aspx.

 

4. Better ways to measure performance

 

4.1. Run the actual workload

The best way to measure performance is to run the actual workload that you are targeting.

If you’re configuring some storage that will be used for an OLTP database, install SQL Server, run an OLTP workload and see how many transactions per second you can get out of it.

If you’re creating a solution for static web sites running inside a VM, install Hyper-V, create a VM configured with IIS, set up a few static web sites and see how they handle multiple clients accessing the static web content.

 

4.2. Run a workload simulator

When it’s not possible or practical to run the actual workload, you can at least run a synthetic workload simulator.

There are many of these simulators out there that mimic the actual behavior of the application and allow you to simulate a large number of clients accessing your machine.

For instance, to simulate running SQL Server databases, you might want to try the SQLIO tool (see http://www.microsoft.com/en-us/download/details.aspx?id=20163).

SQLIO is actually fairly flexible and can go beyond simulating just SQL Server behavior. I even created a specific blog post on how to use SQLIO, which you can find at http://blogs.technet.com/b/josebda/archive/2013/03/28/sqlio-powershell-and-storage-performance-measuring-iops-throughput-and-latency-for-both-local-disks-and-smb-file-shares.aspx.

 

4.3. Keep your simulations as real as possible

While it’s more practical to use workload simulators, you should try to stay as close as possible to the actual solution you will deploy.

For instance, if you planning to deploy 4 SQL Servers in a Hyper-V-based private cloud, you should measure the storage performance by actually creating 4 VMs and running your SQLIO simulation inside each one.

That is a much better simulation than just running 4 instances of SQLIO in the host, since the IO pattern of 4 instances of SQL Server running on bare metal will be different from the IO pattern of four VMs each running one instance of SQL Server.

 

5. If your workload is actually file copies

All that aside, there’s a chance that what you are actually trying to test a file copy workload. I mean, you actually have a production scenario where you will be transferring files. In that case (and only in that case), here are a few tips to optimize that specific scenario.

 

5.1. Check both sides of the copy

Remember to optimize both the source and the destination storage subsystems. As mentioned before, you will be as fast as the weakest link in the chain. You might want to redesign your storage solution so that source and destination have better performance or are “closer” to each other.

 

5.2. Use the right copy tool

Most file copy tools like the EXPLORER.EXE GUI, the COPY command in the shell, the XCOPY.EXE tool and the PowerShell Copy-Item cmdlet not optimized for performance. They are single-threaded, one-file-at-a-time solutions that will do the job but are not designed to transfer files as fast as possible.

The best file copy tool included in Windows is actually the ROCOBOPY.EXE tool. It includes very useful options like /MT (for using multiple threads to copy multiple files at once) and /J (copy using unbuffered I/O, which is recommended for large files).

That tool got some love from the Performance Fundamentals team at Microsoft and it’s usually much faster than anything else in Windows.

It’s important to note that even ROBOCOPY with the /MT option won’t help if you’re copying a single file. Like most other file copy programs, it uses a common file copy API instead of custom code.

 

5.3. Offload with COPYCHUNK

If it’s an option for you, put source and destination of your copy on the same file server to leverage the built-in SMB COPYCHUNK. This optimization is part of the SMB protocol and basically avoids sending data over the wire if the source and destination are on the same machine.

You can read about it at http://msdn.microsoft.com/en-us/library/cc246475.aspx (yes, this has been there since SMB1 and it’s still there in SMB3).

Note that COPYCHUNK only applies if the source and destination shares are on the same file server and if the file size is at least 64KB.

 

5.3. Offload with ODX

If your file server uses a SAN back-end, consider using the Offloaded Data Transfers (ODX). This T10 standard improves performance by using a system of tokens to avoid transferring actual data over the wire.

It works only if the source and destination paths live on the same SAN (or somehow connected in the back-end). This also works with SMB file shares (SMB basically lets the request pass down to the underlying storage subsystem).

ODX support was introduced in Windows Server 2012 and requires specific support from your SAN vendor. You can read about it at http://msdn.microsoft.com/en-us/library/windows/hardware/dn265439.aspx.

 

5.4. Create a non-CA file share

If your file server is clustered, you can use SMB Continuously Available file shares that allow you to lose any node of the cluster at any time without impact to the applications. The file clients and file servers will automatically recover though a process we call SMB Transparent Failover.

However, this requires that every write be written through to the storage (instead of potentially being cached). Most server workloads (like Hyper-V and SQL Server) already have this unbuffered IO behavior, but not file copies. So, CA has the potential of slowing down file copy operations, which are normally done with buffered IOs.

If you want to trade reliability for performance during file copies, you can create a file share with the Continuous Availability property turned off (it’s on by default on all clustered file shares).

In that case, if there is a failover during a file copy, you might get an error and the copy might be aborted. But if you don’t have any failovers, the copy will go faster.

For server workloads like Hyper-V and SQL Server, turning off CA will not make things any faster, but you will lose the ability to transparently failover.

Note that you can create two shares pointing to the same folder, one without CA for file copy operations only and one with CA for regular server workloads. Having those two shares might have the side effect of confusing your management software and your file server administrators.

 

5.5. Use SMB Multichannel

If you can afford some extra hardware, consider adding a second network interface of the same type and speed to leverage SMB Multichannel (using multiple network paths simultaneously).

This was introduced in Windows Server 2012 (along with SMB3) and you must have it on both sides of the copy to be effective.

SMB Multichannel might be able to help with many scenarios, including a single large file copy when you are constrained by bandwidth or IOPS.

Also check if you have a second port on your NIC that is not wired to the switch, which might be an even easier upgrade (you will still need some extra cables and switch ports to make it happen).

You can learn more about SMB Multichannel at http://blogs.technet.com/b/josebda/archive/2012/05/13/the-basics-of-smb-multichannel-a-feature-of-windows-server-2012-and-smb-3-0.aspx.

When using SMB Multichannel in a file server cluster, be sure to use multiple subnets, as described at http://blogs.technet.com/b/josebda/archive/2012/11/12/windows-server-2012-file-server-tip-use-multiple-subnets-when-deploying-smb-multichannel-in-a-cluster.aspx.

 

5.6. Windows Server 2012 R2 Update

There are specific copy-related improvements in the Windows Server 2012 R2 Update released in April 2014. That update is especially important if you are using a Continuously Available file share as the destination of your file copy. You can find information on how to obtain the update at http://technet.microsoft.com/en-us/library/dn645472.aspx.

By the way, we are constantly evolving Windows Server and the Scale-Out File Server. We release updates regularly and keeping up with them will give you the best results.

 

5.7. File copy for Hyper-V VM provisioning

One special case of file copy is related to the provisioning of virtual machines from a template. Typically you keep a “Library Share” with your VHDX files and you copy from this library to the deployment folder, where the VHDX will be associated with a running virtual machine.

You can avoid this by using differencing VHDX files, or you can use some interesting tricks (like live VHDX file re-parenting, introduced in Windows Server 2012) to optimize your VM provisioning.

You can find more details about your options at http://blogs.technet.com/b/josebda/archive/2012/03/20/windows-server-8-beta-hyper-v-over-smb-quick-provisioning-a-vm-on-an-smb-file-share.aspx.

 

5.8. System Center Virtual Machine Manager 2012 R2

If you’re using SCVMM for provisioning your VMs from a library, it’s highly recommended that you upgrade to SCVMM 2012 R2.

Before that release, SCVMM used the slower BITS protocol to transfer files from the library to their final destination. In the 2012 R2 release, VMM uses a new way to copy files, which will leverage things like SMB Multichannel, SMB COPYCHUNK and ODX offloads to significantly improve performance.

You can find some details on how VMM deploys virtual machines at http://technet.microsoft.com/en-us/library/hh368991.aspx(that bottom of the page includes the details on Fast File Copy).

 

6. Conclusion

If you’re using copies to measure performance of anything except file copies, I hope this post made it clear that’s not a good idea and convinced you to use other methods of storage performance testing.

If you’re actually trying to optimize file copies, I hope you were able to find at least one or two useful tips here.

Feel free to share your own file copy experiences and tips using the comment section below.

Storage Spaces Survival Guide (Links to presentations, articles, blogs, tools)

$
0
0

In this post, I'm sharing my favorite links related to Storage Spaces in Windows Server 2012 R2. This includes TechEd Presentations, TechNet articles, Blogs and tools related to Storage Spaces in general and more specifically about its deployment in a Failover Cluster or Scale-Out File Server configuration. It's obviously not a complete reference (there are always new blogs and articles being posted), but hopefully this is a useful collection of links.

 

TechEd Presentations

TechNet Articles – Storage Spaces

TechNet Wiki – Storage Spaces

TechNet Articles – Cost-Effective Storage for Hyper-V

Blogs - Storage Spaces

TechNet Download - Tools

Windows Server Catalog

Updates required for deployment

Partner Articles on Storage Spaces (alphabetical order, just a sample of the many partners solutions out there)

 

Thanks for the suggestions in the comments section (some of them already added to the list). Keep them coming…


DiskSpd, PowerShell and storage performance: measuring IOPs, throughput and latency for both local disks and SMB file shares

$
0
0

 

1. Introduction

 

I have been doing storage-related demos and publishing blogs with some storage performance numbers for a while, and I commonly get questions such as “How do you run these tests?” or “What tools do you use to generate IOs for your demos?”. While it’s always best to use a real workload to test storage, sometimes that is not convenient. In the past, I frequently used and recommended a free tool from Microsoft to simulate IOs called SQLIO. However, there is a better tool that was recently released by Microsoft called DiskSpd. This is a flexible tool that can simulate many different types of workloads. And you can apply it to several configurations, from a physical host or virtual machine, using all kinds of storage, including local disks, LUNs on a SAN, Storage Spaces or SMB file shares.

 

2. Download the tool

 

To get started, you need to download and install the DiskSpd. You can get the tool from http://aka.ms/DiskSpd. It comes in the form of a ZIP file that you can open and copy local folder. There are actually 3 subfolders with different versions of the tool included in the ZIP file: amd64fre (for 64-bit systems), x86fre (for 32-bit systems) and armfre (for ARM systems). This allows you to run it in pretty much every Windows version, client or server.

In the end, you really only need one of the versions of DiskSpd.EXE files included in the ZIP (the one that best fits your platform). If you’re using a recent version of Windows Server, you probably want the version in the amd64fre folder. In this blog post, I assume that you copied the correct version of DiskSpd.EXE to the C:\DiskSpd local folder.

If you're a developer, you might also want to take a look at the source code for DiskSpd. You can find that at https://github.com/microsoft/diskspd.

 

3. Run the tool

 

When you’re ready to start running DiskSpd, you want to make sure there’s nothing else running on the computer. Other running process can interfere with your results by putting additional load on the CPU, network or storage. If the disk you are using is shared in any way (like a LUN on a SAN), you want to make sure that nothing else is competing with your testing. If you’re using any form of IP storage (iSCSI LUN, SMB file share), you want to make sure that you’re not running on a network congested with other kinds of traffic.

WARNING: You could be generating a whole lot of disk IO, network traffic and/or CPU load when you run DiskSpd. If you’re in a shared environment, you might want to talk to your administrator and ask permission. This could generate a whole lot of load and disturb anyone else using other VMs in the same host, other LUNs on the same SAN or other traffic on the same network.

WARNING: If you use DiskSpd to write data to a physical disk, you might destroy the data on that disk. DiskSpd does not ask for confirmation. It assumes you know what you are doing. Be careful when using physical disks (as opposed to files) with DiskSpd.

NOTE: You should run DiskSpd from an elevated command prompt. This will make sure file creation is fast. Otherwise, DiskSpd will fall back to a slower method of creating files. In the example below, when you're using a 1TB file, that might take a long time.

From an old command prompt or a PowerShell prompt, issue a single command line to start getting some performance results. Here is your first example using 8 threads of execution, each generating 8 outstanding random 8KB unbuffered read IOs:

PS C:\DiskSpd> C:\DiskSpd\diskspd.exe -c1000G -d10 -r -w0 -t8 -o8 -b8K -h -L X:\testfile.dat

Command Line: C:\DiskSpd\diskspd.exe -c1000G -d10 -r -w0 -t8 -o8 -b8K -h -L X:\testfile.dat

Input parameters:

        timespan:   1
        -------------
        duration: 10s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        random seed: 0
        path: 'X:\testfile.dat'
                think time: 0ms
                burst size: 0
                software and hardware cache disabled
                performing read test
                block size: 8192
                using random I/O (alignment: 8192)
                number of outstanding I/O operations: 8
                stride size: 8192
                thread stride size: 0
                threads per file: 8
                using I/O Completion Ports
                IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:       10.01s
thread count:           8
proc count:             4

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|   5.31%|   0.16%|    5.15%|  94.76%
   1|   1.87%|   0.47%|    1.40%|  98.19%
   2|   1.25%|   0.16%|    1.09%|  98.82%
   3|   2.97%|   0.47%|    2.50%|  97.10%
-------------------------------------------
avg.|   2.85%|   0.31%|    2.54%|  97.22%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |        20480000 |         2500 |       1.95 |     249.77 |   32.502 |    55.200 | X:\testfile.dat (1000GB)
     1 |        20635648 |         2519 |       1.97 |     251.67 |   32.146 |    54.405 | X:\testfile.dat (1000GB)
     2 |        21094400 |         2575 |       2.01 |     257.26 |   31.412 |    53.410 | X:\testfile.dat (1000GB)
     3 |        20553728 |         2509 |       1.96 |     250.67 |   32.343 |    56.548 | X:\testfile.dat (1000GB)
     4 |        20365312 |         2486 |       1.94 |     248.37 |   32.599 |    54.448 | X:\testfile.dat (1000GB)
     5 |        20160512 |         2461 |       1.92 |     245.87 |   32.982 |    54.838 | X:\testfile.dat (1000GB)
     6 |        19972096 |         2438 |       1.90 |     243.58 |   33.293 |    55.178 | X:\testfile.dat (1000GB)
     7 |        19578880 |         2390 |       1.87 |     238.78 |   33.848 |    58.472 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         162840576 |        19878 |      15.52 |    1985.97 |   32.626 |    55.312

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |        20480000 |         2500 |       1.95 |     249.77 |   32.502 |    55.200 | X:\testfile.dat (1000GB)
     1 |        20635648 |         2519 |       1.97 |     251.67 |   32.146 |    54.405 | X:\testfile.dat (1000GB)
     2 |        21094400 |         2575 |       2.01 |     257.26 |   31.412 |    53.410 | X:\testfile.dat (1000GB)
     3 |        20553728 |         2509 |       1.96 |     250.67 |   32.343 |    56.548 | X:\testfile.dat (1000GB)
     4 |        20365312 |         2486 |       1.94 |     248.37 |   32.599 |    54.448 | X:\testfile.dat (1000GB)
     5 |        20160512 |         2461 |       1.92 |     245.87 |   32.982 |    54.838 | X:\testfile.dat (1000GB)
     6 |        19972096 |         2438 |       1.90 |     243.58 |   33.293 |    55.178 | X:\testfile.dat (1000GB)
     7 |        19578880 |         2390 |       1.87 |     238.78 |   33.848 |    58.472 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         162840576 |        19878 |      15.52 |    1985.97 |   32.626 |    55.312

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     1 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     2 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     3 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     4 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     5 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     6 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     7 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      3.360 |        N/A |      3.360
   25th |      5.031 |        N/A |      5.031
   50th |      8.309 |        N/A |      8.309
   75th |     12.630 |        N/A |     12.630
   90th |    148.845 |        N/A |    148.845
   95th |    160.892 |        N/A |    160.892
   99th |    172.259 |        N/A |    172.259
3-nines |    254.020 |        N/A |    254.020
4-nines |    613.602 |        N/A |    613.602
5-nines |    823.760 |        N/A |    823.760
6-nines |    823.760 |        N/A |    823.760
7-nines |    823.760 |        N/A |    823.760
8-nines |    823.760 |        N/A |    823.760
    max |    823.760 |        N/A |    823.760

NOTE: The -w0 is the default, so you could skip it. I'm keeping it here to be explicit about the fact we're doing all reads.

For this specific disk, I am getting 1,985 IOPS, 15.52 MB/sec of average throughput and 32.626 milliseconds of average latency. I’m getting all that information from the blue line above.

That average latency looks high for small IOs (even though this is coming from a set of HDDs), but we’ll examine that later.

Now, let’s try now another command using sequential 512KB reads on that same file. I’ll use 2 threads with 8 outstanding IOs per thread this time:

PS C:\DiskSpd> C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t2 -o8 -b512K -h -L X:\testfile.dat

Command Line: C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t2 -o8 -b512K -h -L X:\testfile.dat

Input parameters:

        timespan:   1
        -------------
        duration: 10s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        random seed: 0
        path: 'X:\testfile.dat'
                think time: 0ms
                burst size: 0
                software and hardware cache disabled
                performing read test
                block size: 524288
                number of outstanding I/O operations: 8
                stride size: 524288
                thread stride size: 0
                threads per file: 2
                using I/O Completion Ports
                IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:       10.00s
thread count:           2
proc count:             4

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|   4.53%|   0.31%|    4.22%|  95.44%
   1|   1.25%|   0.16%|    1.09%|  98.72%
   2|   0.00%|   0.00%|    0.00%|  99.97%
   3|   0.00%|   0.00%|    0.00%|  99.97%
-------------------------------------------
avg.|   1.44%|   0.12%|    1.33%|  98.52%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       886046720 |         1690 |      84.47 |     168.95 |   46.749 |    47.545 | X:\testfile.dat (1000GB)
     1 |       851443712 |         1624 |      81.17 |     162.35 |   49.497 |    54.084 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:        1737490432 |         3314 |     165.65 |     331.29 |   48.095 |    50.873

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       886046720 |         1690 |      84.47 |     168.95 |   46.749 |    47.545 | X:\testfile.dat (1000GB)
     1 |       851443712 |         1624 |      81.17 |     162.35 |   49.497 |    54.084 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:        1737490432 |         3314 |     165.65 |     331.29 |   48.095 |    50.873

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
     1 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      9.406 |        N/A |      9.406
   25th |     31.087 |        N/A |     31.087
   50th |     38.397 |        N/A |     38.397
   75th |     47.216 |        N/A |     47.216
   90th |     64.783 |        N/A |     64.783
   95th |     90.786 |        N/A |     90.786
   99th |    356.669 |        N/A |    356.669
3-nines |    452.198 |        N/A |    452.198
4-nines |    686.307 |        N/A |    686.307
5-nines |    686.307 |        N/A |    686.307
6-nines |    686.307 |        N/A |    686.307
7-nines |    686.307 |        N/A |    686.307
8-nines |    686.307 |        N/A |    686.307
    max |    686.307 |        N/A |    686.307

With that configuration and parameters, I got about 165.65 MB/sec of throughput with an average latency of 48.095 milliseconds per IO. Again, that latency sounds high even for 512KB IOs and we’ll dive into that topic later on.

 

5. Understand the parameters used

 

Now let’s inspect the parameters on those DiskSpd command lines. I know it’s a bit overwhelming at first, but you will get used to it. And keep in mind that, for DiskSpd parameters, lowercase and uppercase mean different things, so be very careful.

Here is the explanation for the parameters used above:

PS C:\> C:\DiskSpd\diskspd.exe -c1G -d10 -r -w0 -t8 -o8 -b8K -h -L X:\testfile.dat

ParameterDescriptionNotes
-cSize of file used.Specify the number of bytes or use suffixes like K, M or G (KB, MB, or GB). You should use a large size (all of the disk) for HDDs, since small files will show unrealistically high performance (short stroking).
-dThe duration of the test, in seconds.You can use 10 seconds for a quick test. For any serious work, use at least 60 seconds.
-wPercentage of writes.0 means all reads, 100 means all writes, 30 means 30% writes and 70% reads. Be careful with using writes on SSDs for a long time, since they can wear out the drive. The default is 0.
-rRandomRandom is common for OLTP workloads. Sequential (when –r is not specified) is common for Reporting, Data Warehousing.
-bSize of the IO in KBSpecify the number of bytes or use suffixes like K, M or G (KB, MB, or GB). 8K is the typical IO for OLTP workloads. 512K is common for Reporting, Data Warehousing.
-tThreads per fileFor large IOs, just a couple is enough. Sometimes just one. For small IOs, you could need as many as the number of CPU cores.
-oOutstanding IOs or queue depth (per thread)In RAID, SAN or Storage Spaces setups, a single disk can be made up of multiple physical disks. You can start with twice the number of physical disks used by the volume where the file sits. Using a higher number will increase your latency, but can get you more IOPs and throughput.
-LCapture latency informationAlways important to know the average time to complete an IO, end-to-end.
-hDisable hardware and software cachingNo hardware or software buffering. Buffering plus a small file size will give you performance of the memory, not the disk.

 

For OLTP workloads, I commonly start with 8KB random IOs, 8 threads, 16 outstanding per thread. 8KB is the size of the page used by SQL Server for its data files. In parameter form, that would be: –r -b8K -t8 -o16. For reporting or OLAP workloads with large IO, I commonly start with 512KB IOs, 2 threads and 16 outstanding per thread. 512KB is a common IO size when SQL Server loads a batch of 64 data pages when using the read ahead technique for a table scan. In parameter form, that would be: -b512K -t2 -o16. These numbers will need to be adjusted if your machine has many cores and/or if you volume is backed up by a large number of physical disks.

If you’re curious, here are more details about parameters for DiskSpd, coming from the tool’s help itself:

PS C:\> C:\DiskSpd\diskspd.exe

Usage: C:\DiskSpd\diskspd.exe [options] target1 [ target2 [ target3 ...] ]
version 2.0.12 (2014/09/17)

Available targets:
       file_path
       #<physical drive number>
       <partition_drive_letter>:

Available options:
  -?                 display usage information
  -a#[,#[...]]       advanced CPU affinity - affinitize threads to CPUs provided after -a
                       in a round-robin manner within current KGroup (CPU count starts with 0); the same CPU
                       can be listed more than once and the number of CPUs can be different
                       than the number of files or threads (cannot be used with -n)
  -ag                group affinity - affinitize threads in a round-robin manner across KGroups
  -b<size>[K|M|G]    block size in bytes/KB/MB/GB [default=64K]
  -B<offs>[K|M|G|b]  base file offset in bytes/KB/MB/GB/blocks [default=0]
                       (offset from the beginning of the file)
  -c<size>[K|M|G|b]  create files of the given size.
                       Size can be stated in bytes/KB/MB/GB/blocks
  -C<seconds>        cool down time - duration of the test after measurements finished [default=0s].
  -D<bucketDuration> Print IOPS standard deviations. The deviations are calculated for samples of duration <bucketDuration>.
                       <bucketDuration> is given in milliseconds and the default value is 1000.
  -d<seconds>        duration (in seconds) to run test [default=10s]
  -f<size>[K|M|G|b]  file size - this parameter can be used to use only the part of the file/disk/partition
                       for example to test only the first sectors of disk
  -fr                open file with the FILE_FLAG_RANDOM_ACCESS hint
  -fs                open file with the FILE_FLAG_SEQUENTIAL_SCAN hint
  -F<count>          total number of threads (cannot be used with -t)
  -g<bytes per ms>   throughput per thread is throttled to given bytes per millisecond
                       note that this can not be specified when using completion routines
  -h                 disable both software and hardware caching
  -i<count>          number of IOs (burst size) before thinking. must be specified with -j
  -j<duration>       time to think in ms before issuing a burst of IOs (burst size). must be specified with -i
  -I<priority>       Set IO priority to <priority>. Available values are: 1-very low, 2-low, 3-normal (default)
  -l                 Use large pages for IO buffers
  -L                 measure latency statistics
  -n                 disable affinity (cannot be used with -a)
  -o<count>          number of overlapped I/O requests per file per thread
                       (1=synchronous I/O, unless more than 1 thread is specified with -F)
                       [default=2]
  -p                 start async (overlapped) I/O operations with the same offset
                       (makes sense only with -o2 or grater)
  -P<count>          enable printing a progress dot after each <count> completed I/O operations
                       (counted separately by each thread) [default count=65536]
  -r<align>[K|M|G|b] random I/O aligned to <align> bytes (doesn't make sense with -s).
                       <align> can be stated in bytes/KB/MB/GB/blocks
                       [default access=sequential, default alignment=block size]
  -R<text|xml>       output format. Default is text.
  -s<size>[K|M|G|b]  stride size (offset between starting positions of subsequent I/O operations)
  -S                 disable OS caching
  -t<count>          number of threads per file (cannot be used with -F)
  -T<offs>[K|M|G|b]  stride between I/O operations performed on the same file by different threads
                       [default=0] (starting offset = base file offset + (thread number * <offs>)
                       it makes sense only with -t or -F
  -v                 verbose mode
  -w<percentage>     percentage of write requests (-w and -w0 are equivalent).
                     absence of this switch indicates 100% reads
                       IMPORTANT: Your data will be destroyed without a warning
  -W<seconds>        warm up time - duration of the test before measurements start [default=5s].
  -x                 use completion routines instead of I/O Completion Ports
  -X<path>           use an XML file for configuring the workload. Cannot be used with other parameters.
  -z                 set random seed [default=0 if parameter not provided, GetTickCount() if value not provided]

Write buffers:
  -Z                        zero buffers used for write tests
  -Z<size>[K|M|G|b]         use a global <size> buffer filled with random data as a source for write operations.
  -Z<size>[K|M|G|b],<file>  use a global <size> buffer filled with data from <file> as a source for write operations.
                              If <file> is smaller than <size>, its content will be repeated multiple times in the buffer.

  By default, the write buffers are filled with a repeating pattern (0, 1, 2, ..., 255, 0, 1, ...)

Synchronization:
  -ys<eventname>     signals event <eventname> before starting the actual run (no warmup)
                       (creates a notification event if <eventname> does not exist)
  -yf<eventname>     signals event <eventname> after the actual run finishes (no cooldown)
                       (creates a notification event if <eventname> does not exist)
  -yr<eventname>     waits on event <eventname> before starting the run (including warmup)
                       (creates a notification event if <eventname> does not exist)
  -yp<eventname>     allows to stop the run when event <eventname> is set; it also binds CTRL+C to this event
                       (creates a notification event if <eventname> does not exist)
  -ye<eventname>     sets event <eventname> and quits

Event Tracing:
  -ep                   use paged memory for NT Kernel Logger (by default it uses non-paged memory)
  -eq                   use perf timer
  -es                   use system timer (default)
  -ec                   use cycle count
  -ePROCESS             process start & end
  -eTHREAD              thread start & end
  -eIMAGE_LOAD          image load
  -eDISK_IO             physical disk IO
  -eMEMORY_PAGE_FAULTS  all page faults
  -eMEMORY_HARD_FAULTS  hard faults only
  -eNETWORK             TCP/IP, UDP/IP send & receive
  -eREGISTRY            registry calls

Examples:

Create 8192KB file and run read test on it for 1 second:

  C:\DiskSpd\diskspd.exe -c8192K -d1 testfile.dat

Set block size to 4KB, create 2 threads per file, 32 overlapped (outstanding)
I/O operations per thread, disable all caching mechanisms and run block-aligned random
access read test lasting 10 seconds:

  C:\DiskSpd\diskspd.exe -b4K -t2 -r -o32 -d10 -h testfile.dat

Create two 1GB files, set block size to 4KB, create 2 threads per file, affinitize threads
to CPUs 0 and 1 (each file will have threads affinitized to both CPUs) and run read test
lasting 10 seconds:

  C:\DiskSpd\diskspd.exe -c1G -b4K -t2 -d10 -a0,1 testfile1.dat testfile2.dat

 

6. Tune the parameters for large sequential IO

 

Now that you have the basics down, we can spend some time looking at how you can refine your number of threads and queue depth for your specific configuration. This might help us figure out why we had those higher than expected latency numbers in the initial runs. You basically need to experiment with the -t and the -o parameters until you find the one that give you the best results. You first want to find out the latency for a given system with a queue depth of 1. Then you can increase the queue depth and check what happens in terms of IOPs, throughput and latency.

Keep in mind that many logical (and “physical”) disks may have multiple IO paths.  That’s the case in the examples mentioned here, but also true for most cloud storage systems and some physical drives (especially SSDs).  In general, increasing outstanding IOs will have minimal impact on latency until the IO paths start to saturate. Then latency will start to increase dramatically.

Here’s a sample script that measures queue depth from 1 to 16, parsing the output of DiskSpd to give us just the information we need. The results for each DiskSpd run are stored in the $result variable and parsed to show IOPs, throughput, latency and CPU usage on a single line. There is some fun string parsing going on there, first to find the line that contains the information we’re looking for, and then using the Split() function to break that line into the individual metrics we need. DiskSpd has the -Rxml option to output XML instead of text, but for me it was easier to parse the text.

1..16 | % { 
   $param = "-o $_"
   $result = C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t1 $param -b512K -h -L X:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()
   "Param $param, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
}

Here is the output:

Param -o 1, 61.01 iops, 30.50 MB/sec, 16.355 ms, 0.20% CPU
Param -o 2, 140.99 iops, 70.50 MB/sec, 14.143 ms, 0.31% CPU
Param -o 3, 189.00 iops, 94.50 MB/sec, 15.855 ms, 0.47% CPU
Param -o 4, 248.20 iops, 124.10 MB/sec, 16.095 ms, 0.47% CPU
Param -o 5, 286.45 iops, 143.23 MB/sec, 17.431 ms, 0.94% CPU
Param -o 6, 316.05 iops, 158.02 MB/sec, 19.052 ms, 0.78% CPU
Param -o 7, 332.51 iops, 166.25 MB/sec, 21.059 ms, 0.66% CPU
Param -o 8, 336.16 iops, 168.08 MB/sec, 23.875 ms, 0.82% CPU
Param -o 9, 339.95 iops, 169.97 MB/sec, 26.482 ms, 0.55% CPU
Param -o 10, 340.93 iops, 170.46 MB/sec, 29.373 ms, 0.70% CPU
Param -o 11, 338.58 iops, 169.29 MB/sec, 32.567 ms, 0.55% CPU
Param -o 12, 344.98 iops, 172.49 MB/sec, 34.675 ms, 1.09% CPU
Param -o 13, 332.09 iops, 166.05 MB/sec, 39.190 ms, 0.82% CPU
Param -o 14, 341.05 iops, 170.52 MB/sec, 41.127 ms, 1.02% CPU
Param -o 15, 339.73 iops, 169.86 MB/sec, 44.037 ms, 0.39% CPU
Param -o 16, 335.43 iops, 167.72 MB/sec, 47.594 ms, 0.86% CPU

For large sequential IOs, we typically want to watch the throughput (in MB/sec). There is a significant increase until we reach 6 outstanding IOs, which gives us around 158 MB/sec with 19 millisecond of latency per IO. You can clearly see that if you don’t queue up some IO, you’re not extracting the full throughput of this disk, since we’ll be processing the data while the disks are idle waiting for more work. If we queue more than 6 IOs, we really don’t get much more throughput, we only manage to increase the latency, as the disk subsystem is unable to give you much more throughput. You can queue up 10 IOs to reach 170 MB/sec, but we increase latency to nearly 30 milliseconds (a latency increase of 50% for a gain of only 8% in throughput).

At this point, it is clear that using multiple outstanding IOs is a great idea. However, using more outstanding IOs than what your target application can drive will be misleading as it will achieve throughput the application isn’t architected to achieve.  Using less outstanding IOs than what the application can drive may lead to an incorrect conclusion that the disk can’t achieve the necessary throughput, because the full parallelism of the disk isn’t being utilized. You should try to find what your specific application does to make sure that your DiskSpd simulation is a good approximation of your real workload.

So, looking at the data above, we can conclude that 6 outstanding IOs is a reasonable number for this storage subsystem. Now we can see if we can gain by spreading the work across multiple threads. What we want to avoid here is bottlenecking on a single CPU core, which is very common we doing lots and lots of IO. A simple experiment is to double the number of threads while reducing the queue depth by half.  Let’s now try 2 threads instead of 1.

1..8 | % {  
   $param = "-o $_"
   $result = C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t2 $param -b512K -h -L X:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim() 
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()
   "Param –t2 $param, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
}

Here is the output with 2 threads and a queue depth of 1:

Param –t2 -o 1, 162.01 iops, 81.01 MB/sec, 12.500 ms, 0.35% CPU
Param –t2 -o 2, 250.47 iops, 125.24 MB/sec, 15.956 ms, 0.82% CPU
Param –t2 -o 3, 312.52 iops, 156.26 MB/sec, 19.137 ms, 0.98% CPU
Param –t2 -o 4, 331.28 iops, 165.64 MB/sec, 24.136 ms, 0.82% CPU
Param –t2 -o 5, 342.45 iops, 171.23 MB/sec, 29.180 ms, 0.74% CPU
Param –t2 -o 6, 340.59 iops, 170.30 MB/sec, 35.391 ms, 1.17% CPU
Param –t2 -o 7, 337.75 iops, 168.87 MB/sec, 41.400 ms, 1.05% CPU
Param –t2 -o 8, 336.15 iops, 168.08 MB/sec, 47.859 ms, 0.90% CPU

Well, it seems like we were not bottlenecked on CPU after all (we sort of knew that already). So, with 2 threads and 3 outstanding IOs per thread, we effective get 6 total outstanding IOs and the performance numbers match what we got with 1 thread and queue depth of 6 in terms of throughput and latency. That pretty much proves that 1 thread was enough for this kind of configuration and workload and that increasing the number of threads yields no gain. This is not surprising for large IO. However, for smaller IO size, the CPU is more taxed and we might hit a single core bottleneck. We can look at the full DiskSpd output to confirm that no single core has pegged with 1 thread:

PS C:\DiskSpd> C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t1 -o6 -b512K -h -L X:\testfile.dat

Command Line: C:\DiskSpd\diskspd.exe -c1000G -d10 -w0 -t1 -o6 -b512K -h -L X:\testfile.dat

Input parameters:

        timespan:   1
        -------------
        duration: 10s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        random seed: 0
        path: 'X:\testfile.dat'
                think time: 0ms
                burst size: 0
                software and hardware cache disabled
                performing read test
                block size: 524288
                number of outstanding I/O operations: 6
                stride size: 524288
                thread stride size: 0
                threads per file: 1
                using I/O Completion Ports
                IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:       10.00s
thread count:           1
proc count:             4

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|   2.03%|   0.16%|    1.87%|  97.96%
   1|   0.00%|   0.00%|    0.00%|  99.84%
   2|   0.00%|   0.00%|    0.00%| 100.15%
   3|   0.00%|   0.00%|    0.00%| 100.31%
-------------------------------------------
avg.|   0.51%|   0.04%|    0.47%|  99.56%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      1664614400 |         3175 |     158.74 |     317.48 |   18.853 |    21.943 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:        1664614400 |         3175 |     158.74 |     317.48 |   18.853 |    21.943

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      1664614400 |         3175 |     158.74 |     317.48 |   18.853 |    21.943 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:        1664614400 |         3175 |     158.74 |     317.48 |   18.853 |    21.943

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      7.743 |        N/A |      7.743
   25th |     13.151 |        N/A |     13.151
   50th |     15.301 |        N/A |     15.301
   75th |     17.777 |        N/A |     17.777
   90th |     22.027 |        N/A |     22.027
   95th |     29.791 |        N/A |     29.791
   99th |    102.261 |        N/A |    102.261
3-nines |    346.305 |        N/A |    346.305
4-nines |    437.603 |        N/A |    437.603
5-nines |    437.603 |        N/A |    437.603
6-nines |    437.603 |        N/A |    437.603
7-nines |    437.603 |        N/A |    437.603
8-nines |    437.603 |        N/A |    437.603
    max |    437.603 |        N/A |    437.603

This confirms we’re not bottleneck on any of CPU cores. You can see above that the busiest CPU core is at only around 2% use.

 

7. Tune queue depth for small random IOs

 

Performing the same tuning exercise for small random IOS is typically more interesting, especially when you have fast storage. For this one, we’ll continue to use the same PowerShell script. However, for small IOs, we’ll try a larger number for queue depth. This might take a while to run, though… Here’s a script that you can run from a PowerShell prompt, trying out many different queue depths:

1..24 | % { 
   $param = "-o $_"
   $result = C:\DiskSpd\DiskSpd.exe -c1000G -d10 -w0 -r -b8k $param -t1 -h -L X:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()  
   "Param $param, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
}

As you can see, the  script runs DiskSpd 24 times, using different queue depths. Here’s the sample output:

Param -o 1, 191.06 iops, 1.49 MB/sec, 5.222 ms, 0.27% CPU
Param -o 2, 361.10 iops, 2.82 MB/sec, 5.530 ms, 0.82% CPU
Param -o 3, 627.30 iops, 4.90 MB/sec, 4.737 ms, 1.02% CPU
Param -o 4, 773.70 iops, 6.04 MB/sec, 5.164 ms, 1.02% CPU
Param -o 5, 1030.65 iops, 8.05 MB/sec, 4.840 ms, 0.86% CPU
Param -o 6, 1191.29 iops, 9.31 MB/sec, 5.030 ms, 1.33% CPU
Param -o 7, 1357.42 iops, 10.60 MB/sec, 5.152 ms, 1.13% CPU
Param -o 8, 1674.22 iops, 13.08 MB/sec, 4.778 ms, 2.07% CPU
Param -o 9, 1895.25 iops, 14.81 MB/sec, 4.745 ms, 1.60% CPU
Param -o 10, 2097.54 iops, 16.39 MB/sec, 4.768 ms, 1.95% CPU
Param -o 11, 2014.49 iops, 15.74 MB/sec, 5.467 ms, 2.03% CPU
Param -o 12, 1981.64 iops, 15.48 MB/sec, 6.055 ms, 1.84% CPU
Param -o 13, 2000.11 iops, 15.63 MB/sec, 6.517 ms, 1.72% CPU
Param -o 14, 1968.79 iops, 15.38 MB/sec, 7.113 ms, 1.79% CPU
Param -o 15, 1970.69 iops, 15.40 MB/sec, 7.646 ms, 2.34% CPU
Param -o 16, 1983.77 iops, 15.50 MB/sec, 8.069 ms, 1.80% CPU
Param -o 17, 1976.84 iops, 15.44 MB/sec, 8.599 ms, 1.56% CPU
Param -o 18, 1982.57 iops, 15.49 MB/sec, 9.049 ms, 2.11% CPU
Param -o 19, 1993.13 iops, 15.57 MB/sec, 9.577 ms, 2.30% CPU
Param -o 20, 1967.71 iops, 15.37 MB/sec, 10.121 ms, 2.30% CPU
Param -o 21, 1964.76 iops, 15.35 MB/sec, 10.699 ms, 1.29% CPU
Param -o 22, 1984.55 iops, 15.50 MB/sec, 11.099 ms, 1.76% CPU
Param -o 23, 1965.34 iops, 15.35 MB/sec, 11.658 ms, 1.37% CPU
Param -o 24, 1983.87 iops, 15.50 MB/sec, 12.161 ms, 1.48% CPU

As you can see, for small IOs, we got consistently better performance as we increased the queue depth for the first few runs. After a certain number of outstanding IOs, adding more started giving us very little improvement until things flatten out completely. As we kept adding more queue depth, all we had was more latency with no additional benefit in IOPS or throughput. If you have a better storage subsystem, you might need to try even higher queue depths. If you don’t hit an IOPS plateau with increasing average latency, you did not queue enough IO to fully exploit the capabilities of your storage subsystem.

So, in this setup, we seem to reach a limit at around 10 outstanding IOs and latency starts to ramp up more dramatically after that. Let’s see the full output for queue depth of 10 to get a good sense:

PS C:\DiskSpd> C:\DiskSpd\DiskSpd.exe -c1000G -d10 -w0 -r -b8k -o10 -t1 -h -L X:\testfile.dat

Command Line: C:\DiskSpd\DiskSpd.exe -c1000G -d10 -w0 -r -b8k -o10 -t1 -h -L X:\testfile.dat

Input parameters:

        timespan:   1
        -------------
        duration: 10s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        random seed: 0
        path: 'X:\testfile.dat'
                think time: 0ms
                burst size: 0
                software and hardware cache disabled
                performing read test
                block size: 8192
                using random I/O (alignment: 8192)
                number of outstanding I/O operations: 10
                stride size: 8192
                thread stride size: 0
                threads per file: 1
                using I/O Completion Ports
                IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:       10.01s
thread count:           1
proc count:             4

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|   8.58%|   1.09%|    7.49%|  91.45%
   1|   0.00%|   0.00%|    0.00%| 100.03%
   2|   0.00%|   0.00%|    0.00%|  99.88%
   3|   0.00%|   0.00%|    0.00%| 100.03%
-------------------------------------------
avg.|   2.15%|   0.27%|    1.87%|  97.85%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       160145408 |        19549 |      15.25 |    1952.47 |    5.125 |     8.135 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         160145408 |        19549 |      15.25 |    1952.47 |    5.125 |     8.135

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       160145408 |        19549 |      15.25 |    1952.47 |    5.125 |     8.135 | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         160145408 |        19549 |      15.25 |    1952.47 |    5.125 |     8.135

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | X:\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      3.101 |        N/A |      3.101
   25th |      3.961 |        N/A |      3.961
   50th |      4.223 |        N/A |      4.223
   75th |      4.665 |        N/A |      4.665
   90th |      5.405 |        N/A |      5.405
   95th |      6.681 |        N/A |      6.681
   99th |     21.494 |        N/A |     21.494
3-nines |    123.648 |        N/A |    123.648
4-nines |    335.632 |        N/A |    335.632
5-nines |    454.760 |        N/A |    454.760
6-nines |    454.760 |        N/A |    454.760
7-nines |    454.760 |        N/A |    454.760
8-nines |    454.760 |        N/A |    454.760
    max |    454.760 |        N/A |    454.760
 

Note that there is some variability here. This second run with the same parameters (1 thread, 10 outstanding IOs) yielded slightly fewer IOPS. You can reduce this variability by running with longer duration or averaging multiple runs. More on that later.

With this system, we don’t seem to have a CPU bottleneck. The overall CPU utilization is around 2% and the busiest core is under 9% of usage. This system has 4 cores and anything with less than 25% (1/4) overall CPU utilization is probably not an issue. In other configurations, you might run into CPU core bottlenecks, though…

 

8. Tune queue depth for small random IOs, part 2

 

Now let’s perform the same tuning exercise for small random IOS with a system with better storage performance and less capable cores. For this one, we’ll continue to use the same PowerShell script. However, this is on system using an SSD for storage and 8 slower CPU cores. Here’s that same script again:

1..16 | % { 
   $param = "-o $_"
   $result = C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k $param -t1 -h -L C:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()  
   "Param $param, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
}

Here’s the sample output from our second system:

Param -o 1, 7873.26 iops, 61.51 MB/sec, 0.126 ms, 3.96% CPU
Param -o 2, 14572.54 iops, 113.85 MB/sec, 0.128 ms, 7.25% CPU
Param -o 3, 23407.31 iops, 182.87 MB/sec, 0.128 ms, 6.76% CPU
Param -o 4, 31472.32 iops, 245.88 MB/sec, 0.127 ms, 19.02% CPU
Param -o 5, 32823.29 iops, 256.43 MB/sec, 0.152 ms, 20.02% CPU
Param -o 6, 33143.49 iops, 258.93 MB/sec, 0.181 ms, 20.71% CPU
Param -o 7, 33335.89 iops, 260.44 MB/sec, 0.210 ms, 20.13% CPU
Param -o 8, 33160.54 iops, 259.07 MB/sec, 0.241 ms, 21.28% CPU
Param -o 9, 36047.10 iops, 281.62 MB/sec, 0.249 ms, 20.86% CPU
Param -o 10, 33197.41 iops, 259.35 MB/sec, 0.301 ms, 20.49% CPU
Param -o 11, 35876.95 iops, 280.29 MB/sec, 0.306 ms, 22.36% CPU
Param -o 12, 32955.10 iops, 257.46 MB/sec, 0.361 ms, 20.41% CPU
Param -o 13, 33548.76 iops, 262.10 MB/sec, 0.367 ms, 20.92% CPU
Param -o 14, 34728.42 iops, 271.32 MB/sec, 0.400 ms, 24.65% CPU
Param -o 15, 32857.67 iops, 256.70 MB/sec, 0.456 ms, 22.07% CPU
Param -o 16, 33026.79 iops, 258.02 MB/sec, 0.484 ms, 21.51% CPU

As you can see, this SSD can deliver many more IOPS than the previous system which used multiple HDDs. We got consistently better performance as we increased the queue depth for the first few runs. As usual, after a certain number of outstanding IOs, adding more started giving us very little improvement until things flatten out completely and all we do is increase latency. This is coming from a single SSD. If you have multiple SSDs in Storage Spaces Pool or a RAID set, you might need to try even higher queue depths. Always make sure you increase –o parameter to reach the point where IOPS hit a peak and only latency increases.

So, in this setup, we seem to start losing steam at around 6 outstanding IOs and latency starts to ramp up more dramatically after queue depth reaches 8. Let’s see the full output for queue depth of 8 to get a good sense:

PS C:\> C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o8 -t1 -h -L C:\testfile.dat

Command Line: C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o8 -t1 -h -L C:\testfile.dat

Input parameters:

    timespan:   1
    -------------
    duration: 10s
    warm up time: 5s
    cool down time: 0s
    measuring latency
    random seed: 0
    path: 'C:\testfile.dat'
        think time: 0ms
        burst size: 0
        software and hardware cache disabled
        performing read test
        block size: 8192
        using random I/O (alignment: 8192)
        number of outstanding I/O operations: 8
        stride size: 8192
        thread stride size: 0
        threads per file: 1
        using I/O Completion Ports
        IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:    10.00s
thread count:        1
proc count:        8

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  99.06%|   2.97%|   96.09%|   0.94%
   1|   5.16%|   0.62%|    4.53%|  94.84%
   2|  14.53%|   2.81%|   11.72%|  85.47%
   3|  17.97%|   6.41%|   11.56%|  82.03%
   4|  24.06%|   5.16%|   18.91%|  75.94%
   5|   8.28%|   1.56%|    6.72%|  91.72%
   6|  16.09%|   3.91%|   12.19%|  83.90%
   7|   8.91%|   0.94%|    7.97%|  91.09%
-------------------------------------------
avg.|  24.26%|   3.05%|   21.21%|  75.74%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      2928967680 |       357540 |     279.32 |   35753.26 |    0.223 |     0.051 | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:        2928967680 |       357540 |     279.32 |   35753.26 |    0.223 |     0.051

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      2928967680 |       357540 |     279.32 |   35753.26 |    0.223 |     0.051 | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:        2928967680 |       357540 |     279.32 |   35753.26 |    0.223 |     0.051

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.114 |        N/A |      0.114
   25th |      0.209 |        N/A |      0.209
   50th |      0.215 |        N/A |      0.215
   75th |      0.224 |        N/A |      0.224
   90th |      0.245 |        N/A |      0.245
   95th |      0.268 |        N/A |      0.268
   99th |      0.388 |        N/A |      0.388
3-nines |      0.509 |        N/A |      0.509
4-nines |      2.905 |        N/A |      2.905
5-nines |      3.017 |        N/A |      3.017
6-nines |      3.048 |        N/A |      3.048
7-nines |      3.048 |        N/A |      3.048
8-nines |      3.048 |        N/A |      3.048
    max |      3.048 |        N/A |      3.048

 

Again you note that there is some variability here. This second run with the same parameters (1 thread, 8 outstanding IOs) yielded a few more IOPS. We’ll later cover some tips on how to average out multiple runs.

You can also see that apparently one of the CPU cores is being hit harder than others. There is clearly a potential bottleneck. Let’s look into that…

 

9. Tune threads for small random IOs with CPU bottleneck

 

In this 8-core system, any overall utilization above 12.5% (1/8 of the total) means a potential core bottleneck when using a single thread. You can actually see in the CPU table in our last run that our core 0 is pegged at 99%. We should be able to do better with multiple threads. Let’s try increasing the number of threads with a matching reduction of queue depth so we end up with the same number of total outstanding IOs.

$o = 8
$t = 1
While ($o -ge 1) { 
   $paramo = "-o $o"
   $paramt = “-t $t”
   $result = C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k $paramo $paramt -h -L C:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()
   “Param $paramo $paramt, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
   $o = $o / 2
   $t = $t * 2
}

Here’s the output:

Param -o 8 -t 1, 35558.31 iops, 277.80 MB/sec, 0.225 ms, 22.36% CPU
Param -o 4 -t 2, 37069.15 iops, 289.60 MB/sec, 0.215 ms, 25.23% CPU
Param -o 2 -t 4, 34592.04 iops, 270.25 MB/sec, 0.231 ms, 27.99% CPU
Param -o 1 -t 8, 34621.47 iops, 270.48 MB/sec, 0.230 ms, 26.76% CPU

As you can see, in my system, adding a second thread improved things a bit, reaching our best yet 37,000 IOPS without much of a change in latency. It seems like we were a bit limited by the performance of a single core. We call that being “core bound”. See below the full output for the run with two threads:

PS C:\> C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o4 -t2 -h -L C:\testfile.dat

Command Line: C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o4 -t2 -h -L C:\testfile.dat

Input parameters:

    timespan:   1
    -------------
    duration: 10s
    warm up time: 5s
    cool down time: 0s
    measuring latency
    random seed: 0
    path: 'C:\testfile.dat'
        think time: 0ms
        burst size: 0
        software and hardware cache disabled
        performing read test
        block size: 8192
        using random I/O (alignment: 8192)
        number of outstanding I/O operations: 4
        stride size: 8192
        thread stride size: 0
        threads per file: 2
        using I/O Completion Ports
        IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:    10.00s
thread count:        2
proc count:        8

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  62.19%|   1.87%|   60.31%|  37.81%
   1|  62.34%|   1.87%|   60.47%|  37.66%
   2|  11.41%|   0.78%|   10.62%|  88.75%
   3|  26.25%|   0.00%|   26.25%|  73.75%
   4|   8.59%|   0.47%|    8.12%|  91.56%
   5|  16.25%|   0.00%|   16.25%|  83.75%
   6|   7.50%|   0.47%|    7.03%|  92.50%
   7|   3.28%|   0.47%|    2.81%|  96.72%
-------------------------------------------
avg.|  24.73%|   0.74%|   23.98%|  75.31%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      1519640576 |       185503 |     144.92 |   18549.78 |    0.215 |     0.419 | C:\testfile.dat (1024MB)
     1 |      1520156672 |       185566 |     144.97 |   18556.08 |    0.215 |     0.404 | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:        3039797248 |       371069 |     289.89 |   37105.87 |    0.215 |     0.411

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |      1519640576 |       185503 |     144.92 |   18549.78 |    0.215 |     0.419 | C:\testfile.dat (1024MB)
     1 |      1520156672 |       185566 |     144.97 |   18556.08 |    0.215 |     0.404 | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:        3039797248 |       371069 |     289.89 |   37105.87 |    0.215 |     0.411

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | C:\testfile.dat (1024MB)
     1 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | C:\testfile.dat (1024MB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      0.088 |        N/A |      0.088
   25th |      0.208 |        N/A |      0.208
   50th |      0.210 |        N/A |      0.210
   75th |      0.213 |        N/A |      0.213
   90th |      0.219 |        N/A |      0.219
   95th |      0.231 |        N/A |      0.231
   99th |      0.359 |        N/A |      0.359
3-nines |      0.511 |        N/A |      0.511
4-nines |      1.731 |        N/A |      1.731
5-nines |     80.959 |        N/A |     80.959
6-nines |     90.252 |        N/A |     90.252
7-nines |     90.252 |        N/A |     90.252
8-nines |     90.252 |        N/A |     90.252
    max |     90.252 |        N/A |     90.252

You can see now that cores 0 and 1 are being used, with both at around 62% utilization. So we have effectively eliminated the core bottleneck that we had before.

For systems with more capable storage, it’s easier to get “core bound” and adding more threads can make a much more significant difference. As I mentioned, it’s important to keep an eye on the per-core CPU utilization (not only the total CPU utilization) to look out for these bottlenecks.

 

10. Multiple runs are better than one

 

One thing you might have notice with DiskSpd (or any other tools like it) is that the results are not always the same given the same parameters. Each run is a little different. For instance, let’s try running our “-b8K –o4 -t2” with the very same parameters a few times to see what happens:

1..8 | % { 
   $result = C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o4 -t2 -h -L C:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()
   “Run $_, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
}

Here are the results:

Run 1, 34371.97 iops, 268.53 MB/sec, 0.232 ms, 24.53% CPU
Run 2, 37138.29 iops, 290.14 MB/sec, 0.215 ms, 26.72% CPU
Run 3, 36920.81 iops, 288.44 MB/sec, 0.216 ms, 26.66% CPU
Run 4, 34538.00 iops, 269.83 MB/sec, 0.231 ms, 36.85% CPU
Run 5, 34406.91 iops, 268.80 MB/sec, 0.232 ms, 37.09% CPU
Run 6, 34393.72 iops, 268.70 MB/sec, 0.214 ms, 33.71% CPU
Run 7, 34451.48 iops, 269.15 MB/sec, 0.232 ms, 25.74% CPU
Run 8, 36964.47 iops, 288.78 MB/sec, 0.216 ms, 30.21% CPU

The results have a good amount of variability. You can look at the standard deviations by specifying the -D option to check how stable things are. But, in the end, how can you tell which measurements are the most accurate? Ideally, once you settle on a specific set of parameters, you should run DiskSpd a few times and average out the results. Here’s a sample PowerShell script to do it, using the last set of parameters we used for the 8KB IOs:

$tiops=0
$tmbps=0
$tlatency=0
$tcpu=0
$truns=10
1..$truns | % {
   $result = C:\DiskSpd\DiskSpd.exe -c1G -d10 -w0 -r -b8k -o4 -t2 -h -L C:\testfile.dat
   foreach ($line in $result) {if ($line -like "total:*") { $total=$line; break } }
   foreach ($line in $result) {if ($line -like "avg.*") { $avg=$line; break } }
   $mbps = $total.Split("|")[2].Trim()
   $iops = $total.Split("|")[3].Trim()
   $latency = $total.Split("|")[4].Trim()
   $cpu = $avg.Split("|")[1].Trim()
   “Run $_, $iops iops, $mbps MB/sec, $latency ms, $cpu CPU"
   $tiops += $iops
   $tmbps += $mbps
   $tlatency += $latency
   $tcpu  += $cpu.Replace("%","")
}
$aiops = $tiops / $truns
$ambps = $tmbps / $truns
$alatency = $tlatency / $truns
$acpu = $tcpu / $truns
“Average, $aiops iops, $ambps MB/sec, $alatency ms, $acpu % CPU"

The script essentially runs DiskSpd 10 times, totaling the numbers for IOPs, throughput, latency and CPU usage, so it can show an average at the end. The $truns variable represents the total number of runs desired. Variables starting with $t hold the totals. Variables starting with $a hold averages. Here’s a sample output:

Run 1, 37118.31 iops, 289.99 MB/sec, 0.215 ms, 35.78% CPU
Run 2, 34311.40 iops, 268.06 MB/sec, 0.232 ms, 38.67% CPU
Run 3, 36997.76 iops, 289.04 MB/sec, 0.215 ms, 38.90% CPU
Run 4, 34463.16 iops, 269.24 MB/sec, 0.232 ms, 24.16% CPU
Run 5, 37066.41 iops, 289.58 MB/sec, 0.215 ms, 25.14% CPU
Run 6, 37134.21 iops, 290.11 MB/sec, 0.215 ms, 26.02% CPU
Run 7, 34430.21 iops, 268.99 MB/sec, 0.232 ms, 23.61% CPU
Run 8, 35924.20 iops, 280.66 MB/sec, 0.222 ms, 25.21% CPU
Run 9, 33387.45 iops, 260.84 MB/sec, 0.239 ms, 21.64% CPU
Run 10, 36789.85 iops, 287.42 MB/sec, 0.217 ms, 25.86% CPU
Average, 35762.296 iops, 279.393 MB/sec, 0.2234 ms, 28.499 % CPU

As you can see, it’s a good idea to capture multiple runs. You might also want to run each iteration for a longer time, like 60 seconds instead of just 10 second.

Using 10 runs of 60 seconds (10 minutes total) might seem a little excessive, but that was the minimum recommended by one of our storage performance engineers. The problem with shorter runs is that they often don’t give the IO subsystem time to stabilize. This is particularly true when testing virtual file systems (such as those in cloud storage or virtual machines) when files are allocated dynamically. Also, SSDs exhibit write degradation and can sometimes take hours to reach a steady state (depending on how full the SSD is). So it's a good idea to run the test for a few hours in these configurations on a brand new system, since this could drop your initial IOPs number by 30% or more.

 

11. DiskSpd and SMB file shares

 

You can use DiskSpd to get the same type of performance information for SMB file shares. All you have to do is run DiskSpd from an SMB client with access to a file share.

It is as simple as mapping the file share to a drive letter using the old “NET USE” command or the new PowerShell cmdlet “New-SmbMapping”. You can also use a UNC path directly in the command line, instead of using drive letters.

Here are an example using the HDD-based system we used as our first few examples, now running remotely:

PS C:\diskspd> C:\DiskSpd\DiskSpd.exe -c1000G -d10 -w0 -r -b8k -o10 -t1 -h -L \\jose1011-st1\Share1\testfile.dat

Command Line: C:\DiskSpd\DiskSpd.exe -c1000G -d10 -w0 -r -b8k -o10 -t1 -h -L \\jose1011-st1\Share1\testfile.dat

Input parameters:

        timespan:   1
        -------------
        duration: 10s
        warm up time: 5s
        cool down time: 0s
        measuring latency
        random seed: 0
        path: '\\jose1011-st1\Share1\testfile.dat'
                think time: 0ms
                burst size: 0
                software and hardware cache disabled
                performing read test
                block size: 8192
                using random I/O (alignment: 8192)
                number of outstanding I/O operations: 10
                stride size: 8192
                thread stride size: 0
                threads per file: 1
                using I/O Completion Ports
                IO priority: normal

Results for timespan 1:
*******************************************************************************

actual test time:       10.01s
thread count:           1
proc count:             4

CPU |  Usage |  User  |  Kernel |  Idle
-------------------------------------------
   0|  12.96%|   0.62%|   12.34%|  86.98%
   1|   0.00%|   0.00%|    0.00%|  99.94%
   2|   0.00%|   0.00%|    0.00%|  99.94%
   3|   0.00%|   0.00%|    0.00%|  99.94%
-------------------------------------------
avg.|   3.24%|   0.16%|    3.08%|  96.70%

Total IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       158466048 |        19344 |      15.10 |    1933.25 |    5.170 |     6.145 | \\jose1011-st1\Share1\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         158466048 |        19344 |      15.10 |    1933.25 |    5.170 |     6.145

Read IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |       158466048 |        19344 |      15.10 |    1933.25 |    5.170 |     6.145 | \\jose1011-st1\Share1\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:         158466048 |        19344 |      15.10 |    1933.25 |    5.170 |     6.145

Write IO
thread |       bytes     |     I/Os     |     MB/s   |  I/O per s |  AvgLat  | LatStdDev |  file
-----------------------------------------------------------------------------------------------------
     0 |               0 |            0 |       0.00 |       0.00 |    0.000 |       N/A | \\jose1011-st1\Share1\testfile.dat (1000GB)
-----------------------------------------------------------------------------------------------------
total:                 0 |            0 |       0.00 |       0.00 |    0.000 |       N/A

  %-ile |  Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
    min |      3.860 |        N/A |      3.860
   25th |      4.385 |        N/A |      4.385
   50th |      4.646 |        N/A |      4.646
   75th |      5.052 |        N/A |      5.052
   90th |      5.640 |        N/A |      5.640
   95th |      6.243 |        N/A |      6.243
   99th |     12.413 |        N/A |     12.413
3-nines |     63.972 |        N/A |     63.972
4-nines |    356.710 |        N/A |    356.710
5-nines |    436.406 |        N/A |    436.406
6-nines |    436.406 |        N/A |    436.406
7-nines |    436.406 |        N/A |    436.406
8-nines |    436.406 |        N/A |    436.406
    max |    436.406 |        N/A |    436.406

This is an HDD-based storage system, so most of the latency comes from the local disk, not the remote SMB access. In fact, we achieved numbers similar to what we had locally before.

 

12. Conclusion

 

I hope you have learned how to use DiskSpd to perform some storage testing of your own. I encourage you to use it to look at the performance of the storage features in Windows Server 2012, Windows Server 2012 R2 and Windows Server Technical Preview. That includes Storage Spaces, SMB3 shares, Scale-Out File Server, Storage Replica and Storage QoS. Let me know if you were able to try it out and feel free to share some of your experiments via blog comments.

 

Thanks to Bartosz Nyczkowski, Dan Lovinger, David Berg and Scott Lee for their contributions to this blog post.

Case Studies on Storage Spaces, Scale-Out File Servers with SMB3 or both

$
0
0

There are many customers out there using Storage Spaces and Scale-Out File Servers with SMB3 since their initial release in Windows Server 2012 a few years back.

Every once in a while, someone will ask me for details on how these technologies were deployed by customers. The best source for those examples is the Microsoft Case Studies site.

The list below includes case studies on how a customer deployed a solution using Storage Spaces, SMB3 file servers or both combined:

And you should also note that the recently release Cloud Platform System (CPS) is another example of a solution that uses both Storage Spaces and Scale-Out File Servers with SMB3:

If you’re focused on gathering data about the performance of Storage Spaces and Scale-Out File Servers, there are a few interesting white papers available:

For more information about Storage Spaces or SMB, you can check these blog posts:

Using PowerShell to select Physical Disks for use with Storage Spaces

$
0
0

 

1. Introduction

 

If you use PowerShell to configure Storage Spaces, you probably noticed that selecting physical disks is an important part of the process.

You must select disks to create a pool and you might also need to do it also when you create a virtual disk using a subset of the disks.

 

2. Select all poolable disks

 

The simplest way to create a pool is to select all physical disks available that can be pooled.

The Get-PhysicalDisk cmdlet has a parameter to filter by the “CanPool” property for this exact purpose:

Get-PhysicalDisk -CanPool $true

You can also do the same thing by filtering the output by the “CanPool” property, which I find even simpler:

Get-PhysicalDisk | ? CanPool

 

3. Creating a pool

 

When creating a pool, you can use this cmdlet (in parenthesis) directly in the command line:

New-StoragePool -FriendlyName Pool1 -PhysicalDisk (Get-PhysicalDisk | ? CanPool)

Note that you probably need additional parameters on your “New-StoragePool” cmdlet, like providing the storage subsystem or the default provisioning type. I removed those here to keep things simple and focused on how you select the physical disks.

Some people (particularly those with a programming background) might prefer to store the list of physical disks in a variable and use that variable in the other cmdlets.

$Disks = Get-PhysicalDisk | ? CanPool

New-StoragePool -FriendlyName Pool1 -PhysicalDisk $Disks

If you’re writing a complex script, creating the variable helps break tasks into smaller chunks that are hopefully easier to understand.

 

4. Filtering by other properties

 

If you have just a simple configuration, it might be OK to put all your disks in a single pool.

However, you might want to create separate pools for different purposes and that’s when you want to make sure you can select exactly the disks you want.

For instance, you might want to put half your SSDs in a “high performance” pool by themselves and put all your HDDs plus the other half of your SSDs in a second pool where you will use tiering.

Or maybe you will put all your 4TB, 7.2k rpm disks in one pool and all your 1TB 15K rpm disks in a second pool.

 

Here are a few ways to filter disks, shown as commands to create a $Disks variable that you could later use to create a pool or a virtual disk.

1: All the HDDs:
   $Disks = Get-PhysicalDisk | ? CanPool | ? MediaType –eq HDD

2: All disks of a certain size:
   $Disks = Get-PhysicalDisk | ? CanPool | ? Size –gt 1TB

3: A specific disk model:
   $Disks = Get-PhysicalDisk | ? CanPool | ? Model –like ST95*

4: Specific Serial Numbers:
   $Disks = Get-PhysicalDisk | ? {"6VEK9B89;a011c94e;13110930".Contains($_.SerialNumber)}

5: A certain quantity of SSDs:
   $Disks = Get-PhysicalDisk | ? CanPool | ? MediaType –eq SSD| Select –First 10

 

Most of the examples above show the use of simple comparisons using a property and a constant value.

I used a few tricks like using the Contains string function to match a list or using the –like operator for patter matching using * as a wildcard.

PowerShell is indeed a powerful language and there are many, many ways to filter or select from a list.

 

5. Complex scenarios with enclosures

 

I find that the most challenging scenarios for selecting disks involve the use of enclosures.

In those cases, you want to spread the disks across enclosures for additional fault tolerance when using the IsEnclosureAware property of the pool.

For instance, you might have 4 enclosures with 40 disks each and you want to create 2 pools, each with 20 disks from each enclosure.

That will require a little scripting, which I show below. You basically create a variable to keep the list of disks and add to it as you loop through the enclosures:

 

# To select 20 HDDs from each enclosure

$PDisks = @()

$HDDsPerE = 20

Get-StorageEnclosure | % {

   $EDisks = $_ | Get-PhysicalDisk –CanPool $true | ? MediaType –eq HDD |

             Sort Slot | Select –First $HDDsPerEnc

   If ($EDisks.Count –ne $HDDsPerE) {

      Write-Error “Could not find $HDDsPerE HDDs on the enclosure” –ErrorAction Stop

   }

   $PDisks += $EDisks

}

New-StoragePool -FriendlyName Pool1 -PhysicalDisk $PDisks -EnclosureAwareDefault $true

 

In the example above, the $PDisks variable will hold all disks to pool and the $EDisks hold the disks to pool from a specific enclosure.

We basically enumerate the enclosures and get a subset of the physical disks using the object filtering techniques we discussed previously.

Then we add the $EDisks variable to the $PDisks variable, which will accumulate disks from the various enclosures.

We finally use the $PDisks variable to actually create the pool. Note again that you will need more parameters in the cmdlet to create the pool, but that’s not our focus here.

 

For our final example, we’ll use 4 SSDs and 16 HDDs per enclosure. It’s somewhat similar to the example above, but it is a more realistic scenario if you are using tiering:

 

# To select 16 HDDs and 4 SSDs from each enclosure

$PDisks = @()

$HDDsPerE = 16

$SSDsPerE = 4

Get-StorageEnclosure | % {

   $EName = $_.FriendlyName

   $EDisks = $_ | Get-PhysicalDisk –CanPool $true | ? MediaType –eq HDD |

             Sort Slot | Select –First $HDDsPerE

   If ($EDisks.Count –ne $HDDsPerE) {

      Write-Error “Could not find $HDDsPerE HDDs on enclosure $EName ” –ErrorAction Stop

   }

   $PDisks += $EDisks

   $EDisks = $_ | Get-PhysicalDisk –CanPool $true | ? MediaType –eq SSD |

             Sort Slot | Select –First $SSDsPerE

   If ($EDisks.Count –ne $SSDsPerE) {

      Write--Error “Could not find $SSDsPerE SSDs on enclosure $EName ” –ErrorAction Stop

   }

   $PDisks += $EDisks

}

New-StoragePool -FriendlyName Pool1 -PhysicalDisk $PDisks -EnclosureAwareDefault $true

 

Conclusion

 

I am sure you will need to customize things for your own environment, but I hope this blog post has put you on the right track.

It might be a good idea to write a little function for disk selection, maybe with a few parameters to fit your specific requirements.

And always remember to test your scripts carefully before deploying anything in a production environment.

Windows PowerShell equivalents for common networking commands (IPCONFIG, PING, NSLOOKUP)

$
0
0

Network troubleshooting is part any System Administrator’s life. Maybe you need to check the IP address of a machine or test if its networking connection is working. Maybe you need to see if DNS is properly configured or check the latency between two hosts.

If you have been in this field long enough, you probably have a few favorite commands that you learned years ago and use on a regular basis, like IPCONFIG or PING.

There are literally hundreds of networking-related PowerShell cmdlets in Windows these days. Just try out this command on your machine: Get-Command -Module Net* | Group Module

But more important than knowing every one of them, is to know the most useful cmdlets that have the potential to replace those old commands that you can’t live without.

And it’s when you combine the many networking cmdlets in ways that only PowerShell can do that you’ll find amazing new troubleshooting abilities…

 

IPCONFIG

Description: This command has many options, but the most common usage is just to show the IP address, subnet mask and default gateway for each network adapter in a machine.

PowerShell: Get-NetIPConfiguration or Get-NetIPAddress

Sample command lines:

  • Get-NetIPConfiguration
  • Get-NetIPAddress | Sort InterfaceIndex | FT InterfaceIndex, InterfaceAlias, AddressFamily, IPAddress, PrefixLength -Autosize
  • Get-NetIPAddress | ? AddressFamily -eq IPv4 | FT –AutoSize
  • Get-NetAdapter Wi-Fi | Get-NetIPAddress | FT -AutoSize

Sample output:

PS C:\> Get-NetIPConfiguration

InterfaceAlias       : Wi-Fi
InterfaceIndex       : 3
InterfaceDescription : Dell Wireless 1703 802.11b|g|n (2.4GHz)
NetProfile.Name      : HomeWifi
IPv6Address          : fded:b22c:44c4:1:88f2:9970:4082:4118
IPv4Address          : 192.168.1.2
IPv6DefaultGateway   :
IPv4DefaultGateway   : 192.168.1.1
DNSServer            : 192.168.1.1

InterfaceAlias       : Bluetooth Network Connection
InterfaceIndex       : 6
InterfaceDescription : Bluetooth Device (Personal Area Network)
NetAdapter.Status    : Disconnected

InterfaceAlias       : Ethernet
InterfaceIndex       : 4
InterfaceDescription : Realtek PCIe GBE Family Controller
NetAdapter.Status    : Disconnected

PS C:\> Get-NetIPAddress | Sort InterfaceIndex | FT InterfaceIndex, InterfaceAlias, AddressFamily, IPAddress, PrefixLength –Autosize

InterfaceIndex InterfaceAlias                                AddressFamily IPAddress                            PrefixLength
-------------- --------------                                ------------- ---------                            -------
             1 Loopback Pseudo-Interface 1                            IPv6 ::1                                      128
             1 Loopback Pseudo-Interface 1                            IPv4 127.0.0.1                                  8
             3 Wi-Fi                                                  IPv6 fe80::88f2:9970:4082:4118%3               64
             3 Wi-Fi                                                  IPv6 fded:b22c:44c4:1:f188:1e45:58e3:9242     128
             3 Wi-Fi                                                  IPv6 fded:b22c:44c4:1:88f2:9970:4082:4118      64
             3 Wi-Fi                                                  IPv4 192.168.1.2                               24
             4 Ethernet                                               IPv6 fe80::ce6:97c9:ae58:b393%4                64
             4 Ethernet                                               IPv4 169.254.179.147                           16
             6 Bluetooth Network Connection                           IPv6 fe80::2884:6750:b46b:cec4%6               64
             6 Bluetooth Network Connection                           IPv4 169.254.206.196                           16
             7 Local Area Connection* 3                               IPv6 fe80::f11f:1051:2f3d:882%7                64
             7 Local Area Connection* 3                               IPv4 169.254.8.130                             16
             8 Teredo Tunneling Pseudo-Interface                      IPv6 2001:0:5ef5:79fd:1091:f90:e7e9:62f0       64
             8 Teredo Tunneling Pseudo-Interface                      IPv6 fe80::1091:f90:e7e9:62f0%8                64
             9 isatap.{024820F0-C990-475F-890B-B42EA24003F1}          IPv6 fe80::5efe:192.168.1.2%9                 128

PS C:\> Get-NetIPAddress | ? AddressFamily -eq IPv4 | FT –AutoSize

ifIndex IPAddress       PrefixLength PrefixOrigin SuffixOrigin AddressState PolicyStore
------- ---------       ------------ ------------ ------------ ------------ -----------
7       169.254.8.130             16 WellKnown    Link         Tentative    ActiveStore
6       169.254.206.196           16 WellKnown    Link         Tentative    ActiveStore
3       192.168.1.2               24 Dhcp         Dhcp         Preferred    ActiveStore
1       127.0.0.1                  8 WellKnown    WellKnown    Preferred    ActiveStore
4       169.254.179.147           16 WellKnown    Link         Tentative    ActiveStore

PS C:\> Get-NetAdapter Wi-Fi | Get-NetIPAddress | FT -AutoSize

ifIndex IPAddress                            PrefixLength PrefixOrigin        SuffixOrigin AddressState PolicyStore
------- ---------                            ------------ ------------        ------------ ------------ -----------
3       fe80::88f2:9970:4082:4118%3                    64 WellKnown           Link         Preferred    ActiveStore
3       fded:b22c:44c4:1:f188:1e45:58e3:9242          128 RouterAdvertisement Random       Preferred    ActiveStore
3       fded:b22c:44c4:1:88f2:9970:4082:4118           64 RouterAdvertisement Link         Preferred    ActiveStore
3       192.168.1.2                                    24 Dhcp                Dhcp         Preferred    ActiveStore

 

PING

Description: Checks connectivity to a specific host. Commonly used to check for liveliness, but also used to measure network latency.

PowerShell: Test-NetConnection

Sample command lines:

  • Test-NetConnection www.microsoft.com
  • Test-NetConnection -ComputerName www.microsoft.com -InformationLevel Detailed
  • Test-NetConnection -ComputerName www.microsoft.com | Select -ExpandProperty PingReplyDetails | FT Address, Status, RoundTripTime
  • 1..10 | % { Test-NetConnection -ComputerName www.microsoft.com -RemotePort 80 } | FT -AutoSize

Sample output

PS C:\> Test-NetConnection www.microsoft.com

ComputerName           : www.microsoft.com
RemoteAddress          : 104.66.197.237
InterfaceAlias         : Wi-Fi
SourceAddress          : 192.168.1.2
PingSucceeded          : True
PingReplyDetails (RTT) : 22 ms

PS C:\> Test-NetConnection -ComputerName www.microsoft.com -InformationLevel Detailed

ComputerName             : www.microsoft.com
RemoteAddress            : 104.66.197.237
AllNameResolutionResults : 104.66.197.237
                           2600:1409:a:396::2768
                           2600:1409:a:39b::2768
InterfaceAlias           : Wi-Fi
SourceAddress            : 192.168.1.2
NetRoute (NextHop)       : 192.168.1.1
PingSucceeded            : True
PingReplyDetails (RTT)   : 14 ms

PS C:\> Test-NetConnection -ComputerName www.microsoft.com | Select -ExpandProperty PingReplyDetails | FT Address, Status, RoundTripTime -Autosize

Address         Status RoundtripTime
-------         ------ -------------
104.66.197.237 Success            22

PS C:\> 1..10 | % { Test-NetConnection -ComputerName www.microsoft.com -RemotePort 80 } | FT -AutoSize

ComputerName      RemotePort RemoteAddress  PingSucceeded PingReplyDetails (RTT) TcpTestSucceeded
------------      ---------- -------------  ------------- ---------------------- ----------------
www.microsoft.com 80         104.66.197.237 True          17 ms                  True
www.microsoft.com 80         104.66.197.237 True          16 ms                  True
www.microsoft.com 80         104.66.197.237 True          15 ms                  True
www.microsoft.com 80         104.66.197.237 True          18 ms                  True
www.microsoft.com 80         104.66.197.237 True          20 ms                  True
www.microsoft.com 80         104.66.197.237 True          20 ms                  True
www.microsoft.com 80         104.66.197.237 True          20 ms                  True
www.microsoft.com 80         104.66.197.237 True          20 ms                  True
www.microsoft.com 80         104.66.197.237 True          15 ms                  True
www.microsoft.com 80         104.66.197.237 True          13 ms                  True

 

NSLOOKUP

Description: Name server lookup. Mostly used to find the IP address for a given DNS name (or vice-versa). Has many, many options.

PowerShell: Resolve-DnsName

Sample command lines:

  • Resolve-DnsName www.microsoft.com
  • Resolve-DnsName microsoft.com -type SOA
  • Resolve-DnsName microsoft.com -Server 8.8.8.8 –Type A

Sample output

PS C:\> Resolve-DnsName www.microsoft.com

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
www.microsoft.com              CNAME  6     Answer     toggle.www.ms.akadns.net
toggle.www.ms.akadns.net       CNAME  6     Answer     www.microsoft.com-c.edgekey.net
www.microsoft.com-c.edgekey.ne CNAME  6     Answer     www.microsoft.com-c.edgekey.net.globalredir.akadns.net
t
www.microsoft.com-c.edgekey.ne CNAME  6     Answer     e10088.dspb.akamaiedge.net
t.globalredir.akadns.net

Name       : e10088.dspb.akamaiedge.net
QueryType  : AAAA
TTL        : 6
Section    : Answer
IP6Address : 2600:1409:a:39b::2768

Name       : e10088.dspb.akamaiedge.net
QueryType  : AAAA
TTL        : 6
Section    : Answer
IP6Address : 2600:1409:a:396::2768

Name       : e10088.dspb.akamaiedge.net
QueryType  : A
TTL        : 6
Section    : Answer
IP4Address : 104.66.197.237

PS C:\> Resolve-DnsName microsoft.com -type SOA

Name                        Type TTL   Section    PrimaryServer               NameAdministrator           SerialNumber
----                        ---- ---   -------    -------------               -----------------           ------------
microsoft.com               SOA  2976  Answer     ns1.msft.net                msnhst.microsoft.com        2015041801

PS C:\> Resolve-DnsName microsoft.com -Server 8.8.8.8 –Type A

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
microsoft.com                                  A      1244  Answer     134.170.188.221
microsoft.com                                  A      1244  Answer     134.170.185.46

 

ROUTE

Description: Shows the IP routes in a given system (also used to add and delete routes)

PowerShell: Get-NetRoute (also New-NetRoute and Remove-NetRoute)

Sample command lines:

  • Get-NetRoute -Protocol Local -DestinationPrefix 192.168*
  • Get-NetAdapter Wi-Fi | Get-NetRoute

Sample output:

PS C:\WINDOWS\system32> Get-NetRoute -Protocol Local -DestinationPrefix 192.168*

ifIndex DestinationPrefix NextHop RouteMetric PolicyStore
------- ----------------- ------- ----------- -----------
2       192.168.1.255/32  0.0.0.0         256 ActiveStore
2       192.168.1.5/32    0.0.0.0         256 ActiveStore
2       192.168.1.0/24    0.0.0.0         256 ActiveStore

PS C:\WINDOWS\system32> Get-NetAdapter Wi-Fi | Get-NetRoute

ifIndex DestinationPrefix                        NextHop     RouteMetric PolicyStore
------- -----------------                        -------     ----------- -----------
2       255.255.255.255/32                       0.0.0.0             256 ActiveStore
2       224.0.0.0/4                              0.0.0.0             256 ActiveStore
2       192.168.1.255/32                         0.0.0.0             256 ActiveStore
2       192.168.1.5/32                           0.0.0.0             256 ActiveStore
2       192.168.1.0/24                           0.0.0.0             256 ActiveStore
2       0.0.0.0/0                                192.168.1.1           0 ActiveStore
2       ff00::/8                                 ::                  256 ActiveStore
2       fe80::d1b9:9258:1fa:33e9/128             ::                  256 ActiveStore
2       fe80::/64                                ::                  256 ActiveStore
2       fded:b22c:44c4:1:d1b9:9258:1fa:33e9/128  ::                  256 ActiveStore
2       fded:b22c:44c4:1:c025:aa72:9331:442/128  ::                  256 ActiveStore
2       fded:b22c:44c4:1::/64                    ::                  256 ActiveStore

 

TRACERT

Description: Trace route. Shows the IP route to a host, including all the hops between your computer and that host.

PowerShell: Test-NetConnection –TraceRoute

Sample command lines:

  • Test-NetConnection www.microsoft.com –TraceRoute
  • Test-NetConnection outlook.com -TraceRoute | Select -ExpandProperty TraceRoute | % { Resolve-DnsName $_ -type PTR -ErrorAction SilentlyContinue }

Sample output:

PS C:\> Test-NetConnection www.microsoft.com–TraceRoute

ComputerName           : www.microsoft.com
RemoteAddress          : 104.66.197.237
InterfaceAlias         : Wi-Fi
SourceAddress          : 192.168.1.2
PingSucceeded          : True
PingReplyDetails (RTT) : 16 ms
TraceRoute             : 192.168.1.1
                         10.0.0.1
                         TimedOut
                         68.86.113.181
                         69.139.164.2
                         68.85.240.94
                         68.86.93.165
                         68.86.83.126
                         104.66.197.237

PS C:\> Test-NetConnection outlook.com -TraceRoute | Select -ExpandProperty TraceRoute | % { Resolve-DnsName $_ -type PTR -ErrorAction SilentlyContinue }

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
125.144.85.68.in-addr.arpa     PTR    7200  Answer     te-0-1-0-10-sur02.bellevue.wa.seattle.comcast.net
142.96.86.68.in-addr.arpa      PTR    4164  Answer     be-1-sur03.bellevue.wa.seattle.comcast.net
6.164.139.69.in-addr.arpa      PTR    2469  Answer     be-40-ar01.seattle.wa.seattle.comcast.net
165.93.86.68.in-addr.arpa      PTR    4505  Answer     be-33650-cr02.seattle.wa.ibone.comcast.net
178.56.167.173.in-addr.arpa    PTR    7200  Answer     as8075-1-c.seattle.wa.ibone.comcast.net
248.82.234.191.in-addr.arpa    PTR    3600  Answer     ae11-0.co2-96c-1a.ntwk.msn.net

 

NETSTAT

Description: Shows current TCP/IP network connections.

PowerShell: Get-NetTCPConnection

Sample command lines:

  • Get-NetTCPConnection | Group State, RemotePort | Sort Count | FT Count, Name –Autosize
  • Get-NetTCPConnection | ? State -eq Established | FT –Autosize
  • Get-NetTCPConnection | ? State -eq Established | ? RemoteAddress -notlike 127* | % { $_; Resolve-DnsName $_.RemoteAddress -type PTR -ErrorAction SilentlyContinue }

Sample output:

PS C:\> Get-NetTCPConnection | Group State, RemotePort | Sort Count | FT Count, Name -Autosize

Count Name
----- ----
    1 SynSent, 9100
    1 Established, 40028
    1 Established, 65001
    1 Established, 27015
    1 Established, 5223
    1 Established, 49227
    1 Established, 49157
    1 Established, 49156
    1 Established, 12350
    1 Established, 49200
    2 Established, 5354
    2 TimeWait, 5357
    2 Established, 80
    3 Established, 443
   36 Listen, 0

PS C:\> Get-NetTCPConnection | ? State -eq Established | FT -Autosize

LocalAddress LocalPort RemoteAddress   RemotePort State       AppliedSetting
------------ --------- -------------   ---------- -----       --------------
127.0.0.1    65001     127.0.0.1       49200      Established Internet
192.168.1.2  59619     91.190.218.57   12350      Established Internet
192.168.1.2  57993     213.199.179.175 40028      Established Internet
192.168.1.2  54334     17.158.28.49    443        Established Internet
192.168.1.2  54320     96.17.8.170     80         Established Internet
192.168.1.2  54319     23.3.105.144    80         Established Internet
192.168.1.2  54147     65.55.68.119    443        Established Internet
192.168.1.2  49257     17.143.162.214  5223       Established Internet
127.0.0.1    49227     127.0.0.1       27015      Established Internet
127.0.0.1    49200     127.0.0.1       65001      Established Internet
192.168.1.2  49197     157.56.98.92    443        Established Internet
127.0.0.1    49157     127.0.0.1       5354       Established Internet
127.0.0.1    49156     127.0.0.1       5354       Established Internet
127.0.0.1    27015     127.0.0.1       49227      Established Internet
127.0.0.1    5354      127.0.0.1       49157      Established Internet
127.0.0.1    5354      127.0.0.1       49156      Established Internet

PS C:\> Get-NetTCPConnection | ? State -eq Established | ? RemoteAddress -notlike 127* | % { $_; Resolve-DnsName $_.RemoteAddress -type PTR -ErrorAction SilentlyContinue }

LocalAddress                        LocalPort RemoteAddress                       RemotePort State       AppliedSetting
------------                        --------- -------------                       ---------- -----       --------------
192.168.1.2                         59619     91.190.218.57                       12350      Established Internet
192.168.1.2                         57993     213.199.179.175                     40028      Established Internet
192.168.1.2                         54334     17.158.28.49                        443        Established Internet
192.168.1.2                         54320     96.17.8.170                         80         Established Internet

Name      : 170.8.17.96.in-addr.arpa
QueryType : PTR
TTL       : 86377
Section   : Answer
NameHost  : a96-17-8-170.deploy.akamaitechnologies.com

192.168.1.2                         54319     23.3.105.144                        80         Established Internet

Name      : 144.105.3.23.in-addr.arpa
QueryType : PTR
TTL       : 7
Section   : Answer
NameHost  : a23-3-105-144.deploy.static.akamaitechnologies.com

192.168.1.2                         54147     65.55.68.119                        443        Established Internet

Name      : 119.68.55.65.in-addr.arpa
QueryType : PTR
TTL       : 850
Section   : Answer
NameHost  : snt404-m.hotmail.com

192.168.1.2                         49257     17.143.162.214                      5223       Established Internet

192.168.1.2                         49197     157.56.98.92                        443        Established Internet

Name      : 92.98.56.157.in-addr.arpa
QueryType : PTR
TTL       : 3600
Section   : Answer
NameHost  : bn1wns1011516.wns.windows.com

Note: Including a PDF version of the output in case you can't see it too well on the web with the lines wrapping and all. See below.

The Deprecation of SMB1 – You should be planning to get rid of this old SMB dialect

$
0
0

I regularly get a question about when will SMB1 be completely removed from Windows. This blog post summarizes the current state of this old SMB dialect in Windows client and server.

 

1) SMB1 is deprecated, but not yet removed

We already added SMB1 to the Windows Server 2012 R2 deprecation list in June 2013. That does not mean it’s fully removed, but that the feature is “planned for potential removal in subsequent releases”. You can find the Windows Server 2012 R2 deprecation list at https://technet.microsoft.com/en-us/library/dn303411.aspx.

 

2) Windows Server 2003 is going away

The last supported Windows operating system that can only negotiate SMB1 is Windows Server 2003. All other currently supported Windows operating systems (client and server) are able to negotiate SMB2 or higher. Windows Server 2003 support will end on July 14 of this year, as you probably heard.

 

3) SMB versions in current releases of Windows and Windows Server

Aside from Windows Server 2003, all other versions of Windows (client and server) support newer versions of SMB:

  • Windows Server 2008 or Windows Vista – SMB1 or SMB2
  • Windows Server 2008 R2 or Windows 7 – SMB1 or SMB2
  • Windows Server 2012 and Windows 8 – SMB1, SMB2 or SMB3
  • Windows Server 2012 R2 and Windows 8.1 – SMB1, SMB2 or SMB3

For details on specific dialects and how they are negotiated, see this blog post on SMB dialects and Windows versions.

image 

4) SMB1 removal in Windows Server 2012 R2 and Windows 8.1

In Windows Server 2012 R2 and Windows 8.1, we made SMB1 an optional component that can be completely removed. That optional component is enabled by default, but a system administrator now has the option to completely disable it. For more details, see this blog post on how to completely remove SMB1 in Windows Server 2012 R2.

 

5) SMB1 removal in Windows 10 Technical Preview and Windows Server Technical Preview

SMB1 will continue to be an optional component enabled by default with Windows 10, which is scheduled to be released in 2015. The next version of Windows Server, which is expected in 2016, will also likely continue to have SMB as an optional component enabled by default. In that release we will add an option to audit SMB1 usage, so IT Administrators can assess if they can disable SMB1 on their own.

 

6) What you should be doing about SMB1

If you are a systems administrator and you manage IT infrastructure that relies on SMB1, you should prepare to remove SMB1.  Once Windows Server 2003 is gone, the main concern will be third party software or hardware like printers, scanners, NAS devices and WAN accelerators. You should make sure that any new software and hardware that requires the SMB protocol is able to negotiate newer versions (at least SMB2, preferably SMB3). For existing devices and software that only support SMB1, you should contact the manufacturer for updates to support the newer dialects.

If you are a software or hardware manufacturer that has a dependency on the SMB1 protocol, you should have a clear plan for removing any such dependencies. Your hardware or software should be ready to operate in an environment where Windows clients and servers only support SMB2 or SMB3. While it’s true that today SMB1 still works in most environments, the fact that the feature is deprecated is a warning that it could go away at any time.

 

7) Complete removal of SMB1

Since SMB1 is a deprecated component, we will assess for its complete removal with every new release.

Viewing all 143 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>