diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/linux_xfs/filesys.c | |
download | pcp-debian/3.9.10.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/linux_xfs/filesys.c')
-rw-r--r-- | src/pmdas/linux_xfs/filesys.c | 183 |
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; +} |