Skip to content

Instantly share code, notes, and snippets.

@pillowtrucker
Created November 16, 2023 10:27
Show Gist options
  • Save pillowtrucker/bb5663e93af5c77f19dc47c41a637b40 to your computer and use it in GitHub Desktop.
Save pillowtrucker/bb5663e93af5c77f19dc47c41a637b40 to your computer and use it in GitHub Desktop.
global theStats[64]
global theShorts[100]
global theErrors[64]
global timestamps[64]
global aggTotalNFSRead
global aggTotalXFSRead
global aggGenericFileRead
global aggNFSConcurrency
global currentConcurrency[10]
probe module("nfsd").function("nfsd_splice_read") {
caller = "nfsd_splice_read"
wantCount = kernel_long($count)
theFilename = fullpath_struct_path(&$file->f_path)
offAsStr = sprintf("%d",$offset)
myKey = caller . theFilename . offAsStr
# printf("[ENTER NFSD] Why the heck does nothing match %s.",myKey)
# printf("Process %d ( %s ) wanted to read %d bytes from file %s at offset %d\n",pid(),execname(),wantCount,theFilename,$offset)
theStats[myKey] = wantCount;
if (theFilename in currentConcurrency) {
currentConcurrency[theFilename]++
}
else {
currentConcurrency[theFilename] = 1
}
aggNFSConcurrency[theFilename] <<< currentConcurrency[theFilename]
timestamps[myKey] = gettimeofday_us()
}
probe module("xfs").function("xfs_file_buffered_aio_read") {
caller = "xfs_file_buffered_aio_read"
theFilename = fullpath_struct_path(&$iocb->ki_filp->f_path)
theOffset = $iocb->ki_pos
offAsStr = sprintf("%d",theOffset)
wtf = "nfsd_splice_read" . theFilename . offAsStr
# printf("[ENTER XFS] Why the heck does nothing match %s.",wtf)
if (wtf in timestamps) {
# printf("On xfs read hook enter found existing nfsd transaction for file %s at offset %d.\n",theFilename,theOffset)
}
else {
# printf("Ignoring xfs read for file %s at offset %d with no matching nfsd transaction.\n",theFilename,theOffset)
next
}
myKey = caller . theFilename . offAsStr
# printf("Process %d ( %s ) started xfs read from file %s at offset %d.\n",pid(),execname(),theFilename,theOffset)
timestamps[myKey] = gettimeofday_us()
}
probe module("xfs").function("xfs_file_buffered_aio_read").return {
caller = "xfs_file_buffered_aio_read"
theFilename = fullpath_struct_path(&$iocb->ki_filp->f_path)
theOffset = $iocb->ki_pos
offAsStr = sprintf("%d",theOffset)
wtf = "nfsd_splice_read" . theFilename . offAsStr
if (wtf in timestamps) {
# printf("On xfs read hook return found existing nfsd transaction for file %s at offset %d.\n",theFilename,theOffset)
}
else {
# printf("Ignoring xfs read return for file %s at offset %d with no matching nfsd transaction.\n",theFilename,theOffset)
next
}
myKey = caller . theFilename . offAsStr
myRunTime = gettimeofday_us() - timestamps[myKey]
aggTotalXFSRead[theFilename] <<< myRunTime
delete timestamps[myKey]
printf("Process %d ( %s ) finished xfs read from file %s at offset %d in about %d microseconds.\n",pid(),execname(),theFilename,theOffset,myRunTime)
}
probe kernel.function("generic_file_read_iter") {
caller = "generic_file_read_iter"
theFilename = fullpath_struct_path(&$iocb->ki_filp->f_path)
theOffset = $iocb->ki_pos
offAsStr = sprintf("%d",theOffset)
wtf = "nfsd_splice_read" . theFilename . offAsStr
if (wtf in timestamps) {
# printf("On generic read hook enter found existing nfsd transaction for file %s at offset %d.\n",theFilename,theOffset)
}
else {
# printf("Ignoring generic read for file %s at offset %d with no matching nfsd transaction.\n",theFilename,theOffset)
next
}
myKey = caller . theFilename . offAsStr
# printf("Process %d ( %s ) started generic read from file %s at offset %d.\n",pid(),execname(),theFilename,theOffset)
timestamps[myKey] = gettimeofday_us()
}
probe kernel.function("generic_file_read_iter").return {
caller = "generic_file_read_iter"
theFilename = fullpath_struct_path(&$iocb->ki_filp->f_path)
theOffset = $iocb->ki_pos
offAsStr = sprintf("%d",theOffset)
wtf = "nfsd_splice_read" . theFilename . offAsStr
if (wtf in timestamps) {
# printf("On generic read hook return found existing nfsd transaction for file %s at offset %d.\n",theFilename,theOffset)
}
else {
# printf("Ignoring generic read return for file %s at offset %d with no matching nfsd transaction.\n",theFilename,theOffset)
next
}
myKey = caller . theFilename . offAsStr
myRunTime = gettimeofday_us() - timestamps[myKey]
aggGenericFileRead[theFilename] <<< myRunTime
delete timestamps[myKey]
printf("Process %d ( %s ) finished generic read from file %s at offset %d in about %d microseconds.\n",pid(),execname(),theFilename,theOffset,myRunTime)
}
probe module("nfsd").function("nfsd_splice_read").return {
caller = "nfsd_splice_read"
theFilename = fullpath_struct_path(&$file->f_path)
offAsStr = sprintf("%d",$offset)
myKey = caller . theFilename . offAsStr
myRunTime = gettimeofday_us() - timestamps[myKey]
currentConcurrency[theFilename]--
aggNFSConcurrency[theFilename] <<< currentConcurrency[theFilename]
if ($return == 0) {
gotCount = kernel_long($count)
tally = theStats[myKey] - gotCount;
if (tally == 0) {
printf("Process %d ( %s ) finished read %d bytes from file %s at offset %d matching with requested length, this took about %d microseconds.\n",pid(),execname(),gotCount,theFilename,$offset,myRunTime)
}
else {
theShorts[myKey] = tally;
printf("Process %d ( %s ) finished read %d bytes from file %s at offset %d with read short by %d bytes, this took about %d microseconds.\n",pid(),execname(),gotCount,theFilename,$offset,tally,myRunTime)
}
}
else {
theErrors[myKey] = tally;
printf("Process %d ( %s ) got error in read with code %d in file %s at offset %d, this took about %d microseconds.\n",pid(),execname(),$return,theFilename,$offset,myRunTime)
}
aggTotalNFSRead[theFilename] <<< myRunTime
delete theStats[myKey]
delete timestamps[myKey]
}
probe end {
printf("Statistics:\n")
foreach (k in aggNFSConcurrency) {
maxC = @max(aggNFSConcurrency[k])
avgC = @avg(aggNFSConcurrency[k])
printf("%s maximum concurrency %d, average %d.\n",k,maxC,avgC)
}
foreach (k in aggTotalNFSRead) {
maxRT = @max(aggTotalNFSRead[k])
avgRT = @avg(aggTotalNFSRead[k])
printf("%s maximum nfs read time per chunk %d microseconds, average %d microseconds.\n",k,maxRT,avgRT)
}
foreach (k in aggTotalXFSRead) {
maxRT = @max(aggTotalXFSRead[k])
avgRT = @avg(aggTotalXFSRead[k])
printf("%s maximum xfs read time per chunk %d microseconds, average %d microseconds.\n",k,maxRT,avgRT)
}
foreach (k in aggGenericFileRead) {
maxRT = @max(aggGenericFileRead[k])
avgRT = @avg(aggGenericFileRead[k])
printf("%s maximum generic read time per chunk %d microseconds, average %d microseconds.\n",k,maxRT,avgRT)
}
printf("Error summary:\n")
foreach (k in theShorts) {
v = theShorts[k]
printf("%s short %d bytes.\n",k,v)
}
foreach (k in theErrors) {
v = theErrors[k]
printf("%s error code %d.\n",k,v)
}
foreach (k in theStats) {
v = theStats[k]
printf("Read of %s not finished by end of trace while reading %d bytes",k,v)
if (k in timestamps) {
printf(" with last timestamp %d.",timestamps[k])
}
else {
printf(" with no known last timestamp.")
}
printf("\n")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment