/* * QUOTA An implementation of the diskquota system for the LINUX operating * system. QUOTA is implemented using the BSD systemcall interface * as the means of communication with the user level. Should work for * all filesystems because of integration into the VFS layer of the * operating system. This is based on the Melbourne quota system wich * uses both user and group quota files. * * Program to query for the internal statistics. * * Author: Marco van Wieringen * * 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. */ #include "config.h" #include #include #include #include #include #include #include "pot.h" #include "common.h" #include "quota.h" #include "quotasys.h" #include "quotaio.h" #include "quotaio_v1.h" #include "dqblk_v1.h" #include "quotaio_v2.h" #include "dqblk_v2.h" char *progname; static int get_proc_num(char *name) { int ret; char namebuf[PATH_MAX] = "/proc/sys/fs/quota/"; FILE *f; sstrncat(namebuf, name, PATH_MAX); if (!(f = fopen(namebuf, "r"))) { errstr(_("Cannot read stat file %s: %s\n"), namebuf, strerror(errno)); return -1; } fscanf(f, "%d", &ret); fclose(f); return ret; } static int get_stats(struct util_dqstats *dqstats) { struct v1_dqstats old_dqstats; struct v2_dqstats v0_dqstats; int ret = -1; struct stat st; signal(SIGSEGV, SIG_IGN); /* Ignore SIGSEGV due to bad quotactl() */ if (!stat("/proc/sys/fs/quota", &st)) { dqstats->version = 6*10000+5*100+1; dqstats->lookups = get_proc_num("lookups"); dqstats->drops = get_proc_num("drops"); dqstats->reads = get_proc_num("reads"); dqstats->writes = get_proc_num("writes"); dqstats->cache_hits = get_proc_num("cache_hits"); dqstats->allocated_dquots = get_proc_num("allocated_dquots"); dqstats->free_dquots = get_proc_num("free_dquots"); dqstats->syncs = get_proc_num("syncs"); } else if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) >= 0) { /* Structures are currently the same */ memcpy(dqstats, &old_dqstats, sizeof(old_dqstats)); dqstats->version = 0; } else { /* Sadly these all are possible to get from kernel :( */ if (errno != EINVAL && errno != EPERM && errno != EFAULT) { errstr(_("Error while getting quota statistics from kernel: %s\n"), strerror(errno)); goto out; } if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (caddr_t)&v0_dqstats) < 0) { errstr(_("Error while getting old quota statistics from kernel: %s\n"), strerror(errno)); goto out; } memcpy(dqstats, &v0_dqstats, sizeof(v0_dqstats)); } ret = 0; out: signal(SIGSEGV, SIG_DFL); return ret; } static inline int print_stats(struct util_dqstats *dqstats) { if (!dqstats->version) printf(_("Kernel quota version: old\n")); else printf(_("Kernel quota version: %u.%u.%u\n"), dqstats->version/10000, dqstats->version/100%100, dqstats->version%100); printf(_("Number of dquot lookups: %ld\n"), (long)dqstats->lookups); printf(_("Number of dquot drops: %ld\n"), (long)dqstats->drops); printf(_("Number of dquot reads: %ld\n"), (long)dqstats->reads); printf(_("Number of dquot writes: %ld\n"), (long)dqstats->writes); printf(_("Number of quotafile syncs: %ld\n"), (long)dqstats->syncs); printf(_("Number of dquot cache hits: %ld\n"), (long)dqstats->cache_hits); printf(_("Number of allocated dquots: %ld\n"), (long)dqstats->allocated_dquots); printf(_("Number of free dquots: %ld\n"), (long)dqstats->free_dquots); printf(_("Number of in use dquot entries (user/group): %ld\n"), (long)(dqstats->allocated_dquots - dqstats->free_dquots)); return 0; } int main(int argc, char **argv) { struct util_dqstats dqstats; gettexton(); progname = basename(argv[0]); if (!get_stats(&dqstats)) print_stats(&dqstats); return 0; }