Saturday, 31 January 2015

Experiments with iNodes (Files) and Memory Utilization

Here are the results of some experiments with CDOT 8.2.1 and seeing if setting max files affects memory utilization at the time of setting or not. This is of course using a SIM in VMware Workstation, the SIM has been given 4GB RAM, and we’re taking the memory stats from the Windows 7 resource monitor. Whether this is valid experiment, I leave it up to the reader to decide. And - hopefully this isn’t a stupid question - does anyone know of a way to get memory stats from a NetApp via the CLI?

1) Create 10 largish volumes for a SIM (max vol size for the SIM is 16t)

vol create -volume vol001 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol002 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol003 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol004 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol005 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol006 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol007 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol008 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol009 -size 10t -aggregate aggr1 -space-guarantee none
vol create -volume vol010 -size 10t -aggregate aggr1 -space-guarantee none

2) Output of ::> vol show -field files,files-used

vserver volume files  files-used
------- ------ ------ ----------
SVM1    vol001 31876689 97
SVM1    vol002 31876689 97
SVM1    vol003 31876689 97
SVM1    vol004 31876689 97
SVM1    vol005 31876689 97
SVM1    vol006 31876689 97
SVM1    vol007 31876689 97
SVM1    vol008 31876689 97
SVM1    vol009 31876689 97
SVM1    vol010 31876689 97

CHECK 1: Post Volume creates

Image: Commit (KB) = 56’980, Working Set (KB) = 1’874’360, Shareable (KB) = 1’831’080, Private (KB) = 43’280

3) Mount All the Volumes

vol mount -volume vol001 -junction-path /vol001
vol mount -volume vol002 -junction-path /vol002
vol mount -volume vol003 -junction-path /vol003
vol mount -volume vol004 -junction-path /vol004
vol mount -volume vol005 -junction-path /vol005
vol mount -volume vol006 -junction-path /vol006
vol mount -volume vol007 -junction-path /vol007
vol mount -volume vol008 -junction-path /vol008
vol mount -volume vol009 -junction-path /vol009
vol mount -volume vol010 -junction-path /vol010

CHECK 2: Post Mounting the Volumes

Image: Commit (KB) = 56’980, Working Set (KB) = 1’874’360, Shareable (KB) = 1’831’080, Private (KB) = 43’280

Result = no (discernable) change

4) Create Shares to All the Volumes

cifs share create vol001 -path /vol001
cifs share create vol002 -path /vol002
cifs share create vol003 -path /vol003
cifs share create vol004 -path /vol004
cifs share create vol005 -path /vol005
cifs share create vol006 -path /vol006
cifs share create vol007 -path /vol007
cifs share create vol008 -path /vol008
cifs share create vol009 -path /vol009
cifs share create vol010 -path /vol010

CHECK 3: Post Creating the Shares

Image: Commit (KB) = 58’700, Working Set (KB) = 1’876’068, Shareable (KB) = 1’831’120, Private (KB) = 44’948

Result = no (discernable) change

5) Mapping the Shares to a Windows Client

net use * \\SVM1\vol001
net use * \\SVM1\vol002
net use * \\SVM1\vol003
net use * \\SVM1\vol004
net use * \\SVM1\vol005
net use * \\SVM1\vol006
net use * \\SVM1\vol007
net use * \\SVM1\vol008
net use * \\SVM1\vol009
net use * \\SVM1\vol010

CHECK 4: Post Mapping to the Shares

Image: Commit (KB) = 57’572, Working Set (KB) = 1’874’944, Shareable (KB) = 1’831’124, Private (KB) = 43’820

Result = no (discernable) change

6) Modifying the iNodes count (Max Files) Per Volume

vol modify -volume vol001 -files 2040109444
vol modify -volume vol002 -files 2040109444
vol modify -volume vol003 -files 2040109444
vol modify -volume vol004 -files 2040109444
vol modify -volume vol005 -files 2040109444
vol modify -volume vol006 -files 2040109444
vol modify -volume vol007 -files 2040109444
vol modify -volume vol008 -files 2040109444
vol modify -volume vol009 -files 2040109444
vol modify -volume vol010 -files 2040109444

CHECK 5: Post Increasing iNodes

Image: Commit (KB) = 57’572, Working Set (KB) = 1’874’944, Shareable (KB) = 1’831’124, Private (KB) = 43’820

Result = no (discernable) change

FINAL CONCLUSION

From this test, it would appear that modifying the maxfiles number does not result in an immediate increase in memory consumption at the time of application of the setting; and that the increase in memory utilization will occur when the iNodes are used.

APPENDIX: From CDOT Man Pages

[-files {integer}] - Total Files (for user-visible data)
This optionally specifies the total number of files for user-visible data permitted on the volume. This value can be raised or lowered. Raising the total number of files does not immediately cause additional disk space to be used to track files. Instead, as more files are created on the volume, the system dynamically increases the number of disk blocks that are used to track files. The space assigned to track files is never freed, and the files value cannot be decreased below the current number of files that can be tracked within the assigned space for the volume.

Thursday, 29 January 2015

When Making a Volume Smaller Makes the Free Space Larger!

If you have Qtree tracking quotas enabled, and a user connects to a share via the Qtree (or a lower level), the Windows Client will report the logical size of data in the Qtree and the logical size of the volume.

Q: But what about if you have dedupe?

Very roughly ...

The Windows Client will report the logical size of the data whilst logical data in qtree is less than the logical size of the volume.
If the logical data in the qtree is greater than the logical size of the volume, the Windows Client will report the deduped size.

Q: But what happens when we go from logical size of data in the Qtree is less than the logical size of the volume, to logical size of data in the Qtree is greater than the logical size of the volume?

Firstly, setting up our demo 1 GB volume in CDOT ::>

vol create testvol1 -vserver CIFSV1 -aggregate N1_aggr1 -size 1g -space-guarantee none -percent-snapshot-space 0
vol mount testvol1 -vserver CIFSV1 -junction-path /testvol1
qtree create -vserver CIFSV1 -volume testvol1 -qtree qtree1
cifs share create -vserver CIFSV1 -share-name testvol1 -path /testvol1
cifs share create -vserver CIFSV1 -share-name qtree1 -path /testvol1/qtree1
quota policy rule create -vserver CIFSV1 -policy-name default -volume testvol1 -type tree -target qtree1 -threshold "-"
vol quota on -vserver CIFSV1 -volume testvol1
sis on -vserver CIFSV1 -volume testvol1

And mapping via a Windows client and the DOS prompt to the volume share and qtree share >

net use T: \\CIFSV1\testvol1
net use Q: \\CIFSV1\qtree1

We fill the Qtree with 4 sets of the same ~250 MB of data (but not quite) and run dedupe (we’ll roughly get a 4:1 dedupe ratio) ::>

sis start -vserver CIFSV1 -volume testvol1

After the dedupe has finished, this is what our client sees:

Image: Volume share with 761 MB free

Image: Qtree share with 12.4 MB free
So, there’s only 12.4 MB space left according to the Qtree mapped drive, but 761 MB space left according to the volume mapped drive.

What happens when we try and add more than 12.4 MB to the Qtree (say another set of ~250 MB)?

The answer is that it won’t go!

Image: Unable to add to the Qtree when the volume has plenty of space!

Q: But what if instead of increasing the size of the volume we reduce the size of the volume, so that the logical size of data in the Qtree is greater than in the volume? ::>

vol size testvol1 -vserver CIFSV1 -new-size 750m

Our Windows client now reports the deduped size of data in the volume over the Qtree share!

Image: Volume share with 487 MB free
Image: Qtree share with 487 MB free
And now we can add our fifth set of ~250 MB data to the Qtree!

Image: Now we can add more data to the Qtree!

Get All Modified Files in a Clustered ONTAP Volume using API

Introduction

Get-ModifiedFiles.ps1 is a PowerShell tool to find all the modified files in a Clustered ONTAP volume in the last X hours. Basically it works by recursively doing a Read-NcDirectory within all the folders in the volume. The script can either be run interactively like so:

PS C:\> .\Get-ModifiedFiles.ps1

Or non-interactively:

PS C:\ > .\Get-ModifiedFiles.ps1 -Cluster CLUSTERNAME -Username CDOTLOGIN -Password PASSWORD -Vserver SVMNAME -Volume VOLUME -Hours X

WARNING: It is not recommended to run this on production CDOT clusters since it can generate substantial CPU load whilst it is running!

The Script

Note: Tabs have been removed to display the script better in blogger.

# Get-ModifiedFiles.ps1
# A program to find the files modified in a specific NetApp Clustered ONTAP Volume, in the last X hours!

Param(
[String]$Cluster,
[String]$Username,
[String]$Password,
[String]$Vserver,
[String]$Volume,
[Int16]$Hours
)

"";"<<< Get Files Modified in the Last X Hours in a Volume >>>";""

# CHECK FOR DATA ONTAP POWERSHELL TOOLKIT

If(!(Get-Module DataONTAP)){Import-Module DataONTAP -ErrorAction SilentlyContinue}
If(!(Get-Module DataONTAP)){"Cannot find Data ONTAP PowerShell Toolkit - exiting!";"";exit}

# ACQUIRE DETAILS FOR THE SCAN

$SecurePass = $null
If($Password)    { $SecurePass = $Password | ConvertTo-SecureString -AsPlainText -Force }

If(!$Cluster -or !$Username -or !$SecurePass -or !$Vserver){
">>> Enter Connection Details ";""
If(!$Cluster)    { $Cluster    = Read-Host "Cluster " }
If(!$Username)   { $Username   = Read-Host "Username" }
If(!$SecurePass) { $SecurePass = Read-Host "Password" -AsSecureString}
If(!$Vserver)    { $Vserver    = Read-Host "Vserver " }
""
}

$Credential = New-Object System.Management.Automation.PsCredential($Username,$SecurePass)
$Connection = $null
$Connection = Connect-NcController -Name $Cluster -Credential $Credential -ErrorAction SilentlyContinue
If(!$Connection){"Unable to connect to $Cluster - exiting!";"";exit}
$Connection = Get-NcVserver $Vserver
If(!$Connection){"Unable to connect to $Vserver - exiting!";"";exit}
$Global:CurrentNcController.Vserver = $Vserver

# ACQUIRE VOLUME DETAILS

If(!$Volume){
">>> List of Volumes in $Vserver ";""
$Attributes = Get-NcVol -Template
$Query      = Get-NcVol -Template
Initialize-NcObjectProperty -object $Query -name VolumeStateAttributes
$Query.VolumeStateAttributes.IsVserverRoot = ""
$VolumesList = (Get-NcVol -Attributes $Attributes -Query $Query).Name
$VolumesList
""
$Volume   = Read-Host "Volume  "
}

# CHOOSE HOW MANY HOURS BACK TO CHECK

IF(!$Hours){$Hours = Read-Host "Hours   ";""}

# GETTING TIMESTAMP FROM A NODE (NODE 1)

$Global:CurrentNcController.Vserver = $null
[int64]$Timestamp  = 0
$Attributes        = Get-NcNode -Template
$Nodes             = (Get-NcNode -Attributes $Attributes).Node
$Timestamp         = (Get-NcTime -Node ($Nodes[0])).localtime
$AdjustedTimestamp = $Timestamp - ($hours * 60 * 60)
$Global:CurrentNcController.Vserver = $Vserver

# STARTING

$StartDate = date
">>> START TIME = $StartDate";""

# SCAN THROUGH ALL FOLDERS IN THE VOLUME

[System.Array]$Global:ModifiedFiles = @()
[int64]$Global:FolderCount = 0
[int64]$Global:FileCount = 0

$Attributes = Read-NcDirectory -Template
$Attributes.Empty = ""
$Attributes.Type  = ""
$Attributes.Name  = ""
$Attributes.ModifiedTimeStamp = ""

$ReadPath = "/vol/$Volume"

Function GetDirInfoRecursive {
Param([String]$PathToReadRecursive)     
Write-Host "." -ForegroundColor Cyan -NoNewLine
$GetDirInfo = Read-NcDirectory $PathToReadRecursive -Attributes $Attributes
Foreach ($line in $GetDirInfo){
If($line.Type -eq "directory"){
If(($line.Name -ne ".") -and ($line.Name -ne "..") -and ($line.Name -ne ".snapshot")) {
$Global:FolderCount ++
If ($line.Empty -ne "False"){
$NewPathToRead = $PathToReadRecursive + "/" + $line.Name
GetDirInfoRecursive $NewPathToRead             
}
}                   
} elseif($line.Type -eq "file"){
$Global:FileCount ++
If($line.ModifiedTimeStamp -gt $AdjustedTimestamp){
$FileDetails = ($line.Name) + " @ " + $PathToReadRecursive
$Global:ModifiedFiles += $FileDetails
}
}
}
}

GetDirInfoRecursive $ReadPath

# FINISHING

$FinishDate = date
"";"";">>> FINISH TIME = $FinishDate";""

# OUTPUT TO SCREEN

">>> OUTPUT <<<";""
"Files modified $Hours hours before $StartDate :";""
$Global:ModifiedFiles
"";"Processed " + $Global:FileCount + " files and " + $Global:FolderCount + " folders."
"Started at $StartDate"
"Finished at $FinishDate";""

# OUTPUT TO NOTEPAD

$UsersProfilePath = $env:USERPROFILE
$Date = Get-Date -uformat "%Y%m%d%H%M"
$OutputFile = $UsersProfilePath + "\ModifiedFiles_" + $Cluster + "_" + $Vserver + "_" + $date + ".txt"
$Global:ModifiedFiles | Out-File $OutputFile
Notepad $OutputFile

# END

Example Outputs

Example 1: Interactive
Example 2: Non-Interactive