|
@@ -44,6 +44,14 @@ const (
|
|
|
|
|
|
fieldTransport11TCPLen = 13
|
|
fieldTransport11TCPLen = 13
|
|
fieldTransport11UDPLen = 10
|
|
fieldTransport11UDPLen = 10
|
|
|
|
+
|
|
|
|
+ // kernel version >= 4.14 MaxLen
|
|
|
|
+ // See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
|
|
|
|
+ fieldTransport11RDMAMaxLen = 28
|
|
|
|
+
|
|
|
|
+ // kernel version <= 4.2 MinLen
|
|
|
|
+ // See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
|
|
|
|
+ fieldTransport11RDMAMinLen = 20
|
|
)
|
|
)
|
|
|
|
|
|
// A Mount is a device mount parsed from /proc/[pid]/mountstats.
|
|
// A Mount is a device mount parsed from /proc/[pid]/mountstats.
|
|
@@ -233,6 +241,33 @@ type NFSTransportStats struct {
|
|
// A running counter, incremented on each request as the current size of the
|
|
// A running counter, incremented on each request as the current size of the
|
|
// pending queue.
|
|
// pending queue.
|
|
CumulativePendingQueue uint64
|
|
CumulativePendingQueue uint64
|
|
|
|
+
|
|
|
|
+ // Stats below only available with stat version 1.1.
|
|
|
|
+ // Transport over RDMA
|
|
|
|
+
|
|
|
|
+ // accessed when sending a call
|
|
|
|
+ ReadChunkCount uint64
|
|
|
|
+ WriteChunkCount uint64
|
|
|
|
+ ReplyChunkCount uint64
|
|
|
|
+ TotalRdmaRequest uint64
|
|
|
|
+
|
|
|
|
+ // rarely accessed error counters
|
|
|
|
+ PullupCopyCount uint64
|
|
|
|
+ HardwayRegisterCount uint64
|
|
|
|
+ FailedMarshalCount uint64
|
|
|
|
+ BadReplyCount uint64
|
|
|
|
+ MrsRecovered uint64
|
|
|
|
+ MrsOrphaned uint64
|
|
|
|
+ MrsAllocated uint64
|
|
|
|
+ EmptySendctxQ uint64
|
|
|
|
+
|
|
|
|
+ // accessed when receiving a reply
|
|
|
|
+ TotalRdmaReply uint64
|
|
|
|
+ FixupCopyCount uint64
|
|
|
|
+ ReplyWaitsForSend uint64
|
|
|
|
+ LocalInvNeeded uint64
|
|
|
|
+ NomsgCallCount uint64
|
|
|
|
+ BcallCount uint64
|
|
}
|
|
}
|
|
|
|
|
|
// parseMountStats parses a /proc/[pid]/mountstats file and returns a slice
|
|
// parseMountStats parses a /proc/[pid]/mountstats file and returns a slice
|
|
@@ -587,14 +622,17 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
|
|
expectedLength = fieldTransport11TCPLen
|
|
expectedLength = fieldTransport11TCPLen
|
|
} else if protocol == "udp" {
|
|
} else if protocol == "udp" {
|
|
expectedLength = fieldTransport11UDPLen
|
|
expectedLength = fieldTransport11UDPLen
|
|
|
|
+ } else if protocol == "rdma" {
|
|
|
|
+ expectedLength = fieldTransport11RDMAMinLen
|
|
} else {
|
|
} else {
|
|
return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
|
|
return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
|
|
}
|
|
}
|
|
- if len(ss) != expectedLength {
|
|
|
|
- return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v", ErrFileParse, ss)
|
|
|
|
|
|
+ if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) ||
|
|
|
|
+ (protocol == "rdma" && len(ss) < expectedLength) {
|
|
|
|
+ return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v, protocol: %v", ErrFileParse, ss, protocol)
|
|
}
|
|
}
|
|
default:
|
|
default:
|
|
- return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q", ErrFileParse, statVersion)
|
|
|
|
|
|
+ return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol)
|
|
}
|
|
}
|
|
|
|
|
|
// Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
|
|
// Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
|
|
@@ -604,7 +642,9 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
|
|
// Note: slice length must be set to length of v1.1 stats to avoid a panic when
|
|
// Note: slice length must be set to length of v1.1 stats to avoid a panic when
|
|
// only v1.0 stats are present.
|
|
// only v1.0 stats are present.
|
|
// See: https://github.com/prometheus/node_exporter/issues/571.
|
|
// See: https://github.com/prometheus/node_exporter/issues/571.
|
|
- ns := make([]uint64, fieldTransport11TCPLen)
|
|
|
|
|
|
+ //
|
|
|
|
+ // Note: NFS Over RDMA slice length is fieldTransport11RDMAMaxLen
|
|
|
|
+ ns := make([]uint64, fieldTransport11RDMAMaxLen+3)
|
|
for i, s := range ss {
|
|
for i, s := range ss {
|
|
n, err := strconv.ParseUint(s, 10, 64)
|
|
n, err := strconv.ParseUint(s, 10, 64)
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -622,9 +662,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
|
|
// we set them to 0 here.
|
|
// we set them to 0 here.
|
|
if protocol == "udp" {
|
|
if protocol == "udp" {
|
|
ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
|
|
ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
|
|
|
|
+ } else if protocol == "tcp" {
|
|
|
|
+ ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...)
|
|
|
|
+ } else if protocol == "rdma" {
|
|
|
|
+ ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...)
|
|
}
|
|
}
|
|
|
|
|
|
return &NFSTransportStats{
|
|
return &NFSTransportStats{
|
|
|
|
+ // NFS xprt over tcp or udp
|
|
Protocol: protocol,
|
|
Protocol: protocol,
|
|
Port: ns[0],
|
|
Port: ns[0],
|
|
Bind: ns[1],
|
|
Bind: ns[1],
|
|
@@ -636,8 +681,32 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
|
|
BadTransactionIDs: ns[7],
|
|
BadTransactionIDs: ns[7],
|
|
CumulativeActiveRequests: ns[8],
|
|
CumulativeActiveRequests: ns[8],
|
|
CumulativeBacklog: ns[9],
|
|
CumulativeBacklog: ns[9],
|
|
- MaximumRPCSlotsUsed: ns[10],
|
|
|
|
- CumulativeSendingQueue: ns[11],
|
|
|
|
- CumulativePendingQueue: ns[12],
|
|
|
|
|
|
+
|
|
|
|
+ // NFS xprt over tcp or udp
|
|
|
|
+ // And statVersion 1.1
|
|
|
|
+ MaximumRPCSlotsUsed: ns[10],
|
|
|
|
+ CumulativeSendingQueue: ns[11],
|
|
|
|
+ CumulativePendingQueue: ns[12],
|
|
|
|
+
|
|
|
|
+ // NFS xprt over rdma
|
|
|
|
+ // And stat Version 1.1
|
|
|
|
+ ReadChunkCount: ns[13],
|
|
|
|
+ WriteChunkCount: ns[14],
|
|
|
|
+ ReplyChunkCount: ns[15],
|
|
|
|
+ TotalRdmaRequest: ns[16],
|
|
|
|
+ PullupCopyCount: ns[17],
|
|
|
|
+ HardwayRegisterCount: ns[18],
|
|
|
|
+ FailedMarshalCount: ns[19],
|
|
|
|
+ BadReplyCount: ns[20],
|
|
|
|
+ MrsRecovered: ns[21],
|
|
|
|
+ MrsOrphaned: ns[22],
|
|
|
|
+ MrsAllocated: ns[23],
|
|
|
|
+ EmptySendctxQ: ns[24],
|
|
|
|
+ TotalRdmaReply: ns[25],
|
|
|
|
+ FixupCopyCount: ns[26],
|
|
|
|
+ ReplyWaitsForSend: ns[27],
|
|
|
|
+ LocalInvNeeded: ns[28],
|
|
|
|
+ NomsgCallCount: ns[29],
|
|
|
|
+ BcallCount: ns[30],
|
|
}, nil
|
|
}, nil
|
|
}
|
|
}
|