The proc.fd.count Linux PMDA metric is calculated for a process by
counting symlinks in the proc/<pid>/fd directory.
---
src/pmdas/linux/clusters.h | 1 +
src/pmdas/linux/help | 3 +++
src/pmdas/linux/pmda.c | 19 ++++++++++++++++++-
src/pmdas/linux/proc_pid.c | 38 ++++++++++++++++++++++++++++++++++++++
src/pmdas/linux/proc_pid.h | 14 ++++++++++++++
src/pmdas/linux/root_linux | 7 ++++++-
6 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/src/pmdas/linux/clusters.h b/src/pmdas/linux/clusters.h
index fd5dd1c..be845bf 100644
--- a/src/pmdas/linux/clusters.h
+++ b/src/pmdas/linux/clusters.h
@@ -70,6 +70,7 @@ enum {
CLUSTER_NET_CLS_PROCS, /* 48 network classification group processes */
CLUSTER_INTERRUPT_LINES,/* 49 /proc/interrupts percpu interrupts */
CLUSTER_INTERRUPT_OTHER,/* 50 /proc/interrupts percpu interrupts */
+ CLUSTER_PID_FD, /* 51 /proc/<pid>/fd */
NUM_CLUSTERS /* one more than highest numbered cluster */
};
diff --git a/src/pmdas/linux/help b/src/pmdas/linux/help
index 169fb80..9616c90 100644
--- a/src/pmdas/linux/help
+++ b/src/pmdas/linux/help
@@ -972,6 +972,9 @@ Number of times a process has been scheduled to run on a
CPU (this is
incremented when a task actually reaches a CPU to run on, not simply
when it is added to the run queue).
+@ proc.fd.count
+Number of file descriptors this process has open.
+
@ network.ip.forwarding count of ip forwarding
@ network.ip.defaultttl count of ip defaultttl
@ network.ip.inreceives count of ip inreceives
diff --git a/src/pmdas/linux/pmda.c b/src/pmdas/linux/pmda.c
index 77bfe71..f7eddd5 100644
--- a/src/pmdas/linux/pmda.c
+++ b/src/pmdas/linux/pmda.c
@@ -4390,6 +4390,13 @@ pmdaMetric linux_metrictab[] = {
{ NULL, {PMDA_PMID(CLUSTER_NET_CLS_GROUPS,0), PM_TYPE_U64,
PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
+/*
+ * proc/<pid>/fd cluster
+ */
+
+ /* proc.fd.count */
+ { NULL, {PMDA_PMID(CLUSTER_PID_FD,0), PM_TYPE_U32, PROC_INDOM,
PM_SEM_INSTANT,
+ PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } },
};
int
@@ -4484,7 +4491,7 @@ linux_refresh(pmdaExt *pmda, int *need_refresh)
if (need_refresh[CLUSTER_PID_STAT] || need_refresh[CLUSTER_PID_STATM] ||
need_refresh[CLUSTER_PID_STATUS] || need_refresh[CLUSTER_PID_IO] ||
- need_refresh[CLUSTER_PID_SCHEDSTAT])
+ need_refresh[CLUSTER_PID_SCHEDSTAT] || need_refresh[CLUSTER_PID_FD])
refresh_proc_pid(&proc_pid);
if (need_refresh[CLUSTER_KERNEL_UNAME])
@@ -4582,6 +4589,7 @@ linux_instance(pmInDom indom, int inst, char *name,
__pmInResult **result, pmdaE
need_refresh[CLUSTER_PID_STATUS]++;
need_refresh[CLUSTER_PID_SCHEDSTAT]++;
need_refresh[CLUSTER_PID_IO]++;
+ need_refresh[CLUSTER_PID_FD]++;
break;
case SCSI_INDOM:
need_refresh[CLUSTER_SCSI]++;
@@ -6563,6 +6571,15 @@ linux_fetchCallBack(pmdaMetric *mdesc, unsigned int
inst, pmAtomValue *atom)
return PM_ERR_INST;
return interrupts_fetch(idp->cluster, idp->item, inst, atom);
+ case CLUSTER_PID_FD:
+ if ((entry = fetch_proc_pid_fd(inst, &proc_pid)) == NULL)
+ return PM_ERR_INST;
+ if (idp->item != PROC_PID_FD_COUNT)
+ return PM_ERR_INST;
+
+ atom->ul = entry->fd_count;
+ break;
+
default: /* unknown cluster */
return PM_ERR_PMID;
}
diff --git a/src/pmdas/linux/proc_pid.c b/src/pmdas/linux/proc_pid.c
index dab510e..b35928c 100644
--- a/src/pmdas/linux/proc_pid.c
+++ b/src/pmdas/linux/proc_pid.c
@@ -108,6 +108,7 @@ refresh_proc_pidlist(proc_pid_t *proc_pid, proc_pid_list_t
*pidlist)
ep->maps_fetched = 0;
ep->io_fetched = 0;
ep->wchan_fetched = 0;
+ ep->fd_fetched = 0;
}
}
@@ -638,6 +639,43 @@ fetch_proc_pid_io(int id, proc_pid_t *proc_pid)
}
/*
+ * fetch a proc/<pid>/fd entry for pid
+ */
+proc_pid_entry_t *
+fetch_proc_pid_fd(int id, proc_pid_t *proc_pid)
+{
+ __pmHashNode *node = __pmHashSearch(id, &proc_pid->pidhash);
+ proc_pid_entry_t *ep;
+
+ if (node == NULL)
+ return NULL;
+ ep = (proc_pid_entry_t *)node->data;
+
+ if (ep->fd_fetched == 0) {
+ char buf[PATH_MAX];
+ uint32_t de_count = 0;
+ DIR *dir;
+ struct dirent *de;
+
+ sprintf(buf, "/proc/%d/fd", ep->id);
+ dir = opendir(buf);
+ if (dir == NULL) {
+ __pmNotifyErr(LOG_ERR, "failed to open pid fd path %s\n",
+ buf);
+ return NULL;
+ }
+ while ((de = readdir(dir)) != NULL) {
+ de_count++;
+ }
+ closedir(dir);
+ ep->fd_count = de_count - 2; /* subtract cwd and parent entries */
+ }
+ ep->fd_fetched = 1;
+
+ return ep;
+}
+
+/*
* Extract the ith (space separated) field from a char buffer.
* The first field starts at zero.
* BEWARE: return copy is in a static buffer.
diff --git a/src/pmdas/linux/proc_pid.h b/src/pmdas/linux/proc_pid.h
index dd59c68..ddcb2cc 100644
--- a/src/pmdas/linux/proc_pid.h
+++ b/src/pmdas/linux/proc_pid.h
@@ -139,6 +139,11 @@
#define PROC_PID_IO_WRITE_BYTES 5
#define PROC_PID_IO_CANCELLED_BYTES 6
+/*
+ * metrics in /proc/<pid>/fd
+ */
+#define PROC_PID_FD_COUNT 0
+
typedef struct { /* /proc/<pid>/status */
char *uid;
char *gid;
@@ -204,6 +209,12 @@ typedef struct {
int wchan_fetched;
int wchan_buflen;
char *wchan_buf;
+
+ /* /proc/<pid>/fd cluster */
+ int fd_fetched;
+ int fd_buflen;
+ char *fd_buf;
+ uint32_t fd_count;
} proc_pid_entry_t;
typedef struct {
@@ -247,6 +258,9 @@ extern proc_pid_entry_t *fetch_proc_pid_schedstat(int,
proc_pid_t *);
/* fetch a proc/<pid>/io entry for pid */
extern proc_pid_entry_t *fetch_proc_pid_io(int, proc_pid_t *);
+/* fetch a proc/<pid>/fd entry for pid */
+extern proc_pid_entry_t *fetch_proc_pid_fd(int, proc_pid_t *);
+
extern int _pm_pid_io_fields; /* count of fields in proc/<pid>/io */
/* extract the ith space separated field from a buffer */
diff --git a/src/pmdas/linux/root_linux b/src/pmdas/linux/root_linux
index 2c4ff8f..8df9f4f 100644
--- a/src/pmdas/linux/root_linux
+++ b/src/pmdas/linux/root_linux
@@ -677,9 +677,10 @@ proc {
psinfo
memory
runq
- id
+ id
io
schedstat
+ fd
}
proc.psinfo {
@@ -795,6 +796,10 @@ proc.schedstat {
pcount 60:31:2
}
+proc.fd {
+ count 60:51:0
+}
+
xfs {
allocs
alloc_btree
--
1.7.1
|