summaryrefslogtreecommitdiff
path: root/src/pmdas/linux_xfs/filesys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/linux_xfs/filesys.c')
-rw-r--r--src/pmdas/linux_xfs/filesys.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/pmdas/linux_xfs/filesys.c b/src/pmdas/linux_xfs/filesys.c
new file mode 100644
index 0000000..34f8b66
--- /dev/null
+++ b/src/pmdas/linux_xfs/filesys.c
@@ -0,0 +1,183 @@
+/*
+ * XFS Filesystems Cluster
+ *
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 2004,2007 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "filesys.h"
+#include "proc_fs_xfs.h"
+
+static void
+refresh_filesys_projects(pmInDom qindom, filesys_t *fs)
+{
+ char buffer[MAXPATHLEN];
+ project_t *qp;
+ fs_quota_stat_t s;
+ fs_disk_quota_t d;
+ size_t idsz, devsz;
+ FILE *projects;
+ char *p, *idend;
+ uint32_t prid;
+ int qcmd, sts;
+
+ qcmd = QCMD(Q_XGETQSTAT, XQM_PRJQUOTA);
+ if (quotactl(qcmd, fs->device, 0, (void*)&s) < 0)
+ return;
+
+ if (s.qs_flags & XFS_QUOTA_PDQ_ENFD)
+ fs->flags |= FSF_QUOT_PROJ_ENF;
+ if (s.qs_flags & XFS_QUOTA_PDQ_ACCT)
+ fs->flags |= FSF_QUOT_PROJ_ACC;
+ else
+ return;
+
+ if ((projects = xfs_statsfile("/etc/projects", "r")) == NULL)
+ return;
+
+ qcmd = QCMD(Q_XQUOTASYNC, XQM_PRJQUOTA);
+ quotactl(qcmd, fs->device, 0, NULL);
+
+ while (fgets(buffer, sizeof(buffer), projects)) {
+ if (buffer[0] == '#')
+ continue;
+
+ prid = strtol(buffer, &idend, 10);
+ idsz = idend - buffer;
+ qcmd = QCMD(Q_XGETQUOTA, XQM_PRJQUOTA);
+ if (!idsz || quotactl(qcmd, fs->device, prid, (void *)&d) < 0)
+ continue;
+
+ devsz = strlen(fs->device);
+ p = malloc(idsz+devsz+2);
+ if (!p)
+ continue;
+ memcpy(p, buffer, idsz);
+ p[idsz] = ':';
+ memcpy(&p[idsz+1], fs->device, devsz+1);
+
+ qp = NULL;
+ sts = pmdaCacheLookupName(qindom, p, NULL, (void **)&qp);
+ if (sts == PMDA_CACHE_ACTIVE) /* repeated line in /etc/projects? */
+ goto next;
+ if (sts != PMDA_CACHE_INACTIVE) {
+ qp = (project_t *)malloc(sizeof(project_t));
+ if (!qp)
+ goto next;
+ if (pmDebug & DBG_TRACE_LIBPMDA)
+ fprintf(stderr, "refresh_filesys_projects: add \"%s\"\n", p);
+ }
+ qp->space_hard = d.d_blk_hardlimit;
+ qp->space_soft = d.d_blk_softlimit;
+ qp->space_used = d.d_bcount;
+ qp->space_time_left = d.d_btimer;
+ qp->files_hard = d.d_ino_hardlimit;
+ qp->files_soft = d.d_ino_softlimit;
+ qp->files_used = d.d_icount;
+ qp->files_time_left = d.d_itimer;
+ pmdaCacheStore(qindom, PMDA_CACHE_ADD, p, (void *)qp);
+next:
+ free(p);
+ }
+ fclose(projects);
+}
+
+char *
+scan_filesys_options(const char *options, const char *option)
+{
+ static char buffer[128];
+ char *s;
+
+ strncpy(buffer, options, sizeof(buffer));
+ buffer[sizeof(buffer)-1] = '\0';
+
+ s = strtok(buffer, ",");
+ while (s) {
+ if (strcmp(s, option) == 0)
+ return s;
+ s = strtok(NULL, ",");
+ }
+ return NULL;
+}
+
+int
+refresh_filesys(pmInDom filesys_indom, pmInDom quota_indom)
+{
+ char buf[MAXPATHLEN];
+ char realdevice[MAXPATHLEN];
+ filesys_t *fs;
+ pmInDom indom = filesys_indom;
+ FILE *fp;
+ char *path, *device, *type, *options;
+ int sts;
+
+ pmdaCacheOp(quota_indom, PMDA_CACHE_INACTIVE);
+ pmdaCacheOp(filesys_indom, PMDA_CACHE_INACTIVE);
+
+ if ((fp = xfs_statsfile("/proc/mounts", "r")) == NULL)
+ return -oserror();
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if ((device = strtok(buf, " ")) == 0)
+ continue;
+
+ path = strtok(NULL, " ");
+ type = strtok(NULL, " ");
+ options = strtok(NULL, " ");
+ if (strcmp(type, "xfs") != 0)
+ continue;
+ if (strncmp(device, "/dev", 4) != 0)
+ continue;
+ if (realpath(device, realdevice) != NULL)
+ device = realdevice;
+
+ sts = pmdaCacheLookupName(indom, device, NULL, (void **)&fs);
+ if (sts == PMDA_CACHE_ACTIVE) /* repeated line in /proc/mounts? */
+ continue;
+ if (sts == PMDA_CACHE_INACTIVE) { /* re-activate an old mount */
+ pmdaCacheStore(indom, PMDA_CACHE_ADD, device, fs);
+ if (strcmp(path, fs->path) != 0) { /* old device, new path */
+ free(fs->path);
+ fs->path = strdup(path);
+ }
+ if (strcmp(options, fs->options) != 0) { /* old device, new opts */
+ free(fs->options);
+ fs->options = strdup(options);
+ }
+ }
+ else { /* new mount */
+ if ((fs = malloc(sizeof(filesys_t))) == NULL)
+ continue;
+ fs->device = strdup(device);
+ fs->path = strdup(path);
+ fs->options = strdup(options);
+ if (pmDebug & DBG_TRACE_LIBPMDA)
+ fprintf(stderr, "refresh_filesys: add \"%s\" \"%s\"\n",
+ fs->path, device);
+ pmdaCacheStore(indom, PMDA_CACHE_ADD, device, fs);
+ }
+ fs->flags = 0;
+ refresh_filesys_projects(quota_indom, fs);
+ }
+
+ /*
+ * success
+ * Note: we do not call statfs() here since only some instances
+ * may be requested (rather, we do it in xfs_fetch, see pmda.c).
+ */
+ fclose(fp);
+ return 0;
+}