|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
d40955 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
d40955 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
d40955 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
d40955 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
d40955 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
d40955 |
* GNU General Public License for more details.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
d40955 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
d40955 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
d40955 |
* 02110-1301, USA.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/statusProcfs.c#4 $
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* Proc filesystem interface to the old GET_DEDUPE_STATS and
|
|
Packit Service |
d40955 |
* GET_KERNEL_STATS ioctls, which can no longer be supported in 4.4
|
|
Packit Service |
d40955 |
* and later kernels. These files return the same data as the old
|
|
Packit Service |
d40955 |
* ioctls do, in order to require minimal changes to our (and
|
|
Packit Service |
d40955 |
* customers') utilties and test code.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* +--+----- /proc/vdo procfsRoot
|
|
Packit Service |
d40955 |
* |
|
|
Packit Service |
d40955 |
* +-+----- vdo<n> config->poolName
|
|
Packit Service |
d40955 |
* |
|
|
Packit Service |
d40955 |
* +------- dedupe_stats GET_DEDUPE_STATS ioctl
|
|
Packit Service |
d40955 |
* +------- kernel_stats GET_KERNEL_STATS ioctl
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
#include "statusProcfs.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include <linux/version.h>
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "memoryAlloc.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "releaseVersions.h"
|
|
Packit Service |
d40955 |
#include "statistics.h"
|
|
Packit Service |
d40955 |
#include "vdo.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "dedupeIndex.h"
|
|
Packit Service |
d40955 |
#include "ioSubmitter.h"
|
|
Packit Service |
d40955 |
#include "kernelStatistics.h"
|
|
Packit Service |
d40955 |
#include "logger.h"
|
|
Packit Service |
d40955 |
#include "memoryUsage.h"
|
|
Packit Service |
d40955 |
#include "threadDevice.h"
|
|
Packit Service |
d40955 |
#include "vdoCommon.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
static struct proc_dir_entry *procfsRoot = NULL;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static int statusDedupeShow(struct seq_file *m, void *v)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
KernelLayer *layer = (KernelLayer *) m->private;
|
|
Packit Service |
d40955 |
VDOStatistics *stats;
|
|
Packit Service |
d40955 |
size_t len = sizeof(VDOStatistics);
|
|
Packit Service |
d40955 |
RegisteredThread allocatingThread, instanceThread;
|
|
Packit Service |
d40955 |
registerAllocatingThread(&allocatingThread, NULL);
|
|
Packit Service |
d40955 |
registerThreadDevice(&instanceThread, layer);
|
|
Packit Service |
d40955 |
int result = ALLOCATE(1, VDOStatistics, __func__, &stats);
|
|
Packit Service |
d40955 |
if (result == VDO_SUCCESS) {
|
|
Packit Service |
d40955 |
getKVDOStatistics(&layer->kvdo, stats);
|
|
Packit Service |
d40955 |
seq_write(m, stats, len);
|
|
Packit Service |
d40955 |
FREE(stats);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
unregisterThreadDeviceID();
|
|
Packit Service |
d40955 |
unregisterAllocatingThread();
|
|
Packit Service |
d40955 |
return result;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static int statusDedupeOpen(struct inode *inode, struct file *file)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
|
Packit Service |
d40955 |
return single_open(file, statusDedupeShow, PDE_DATA(inode));
|
|
Packit Service |
d40955 |
#else
|
|
Packit Service |
d40955 |
return single_open(file, statusDedupeShow, PDE(inode)->data);
|
|
Packit Service |
d40955 |
#endif
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
static const struct file_operations vdoProcfsDedupeOps = {
|
|
Packit Service |
d40955 |
.open = statusDedupeOpen,
|
|
Packit Service |
d40955 |
.read = seq_read,
|
|
Packit Service |
d40955 |
.llseek = seq_lseek,
|
|
Packit Service |
d40955 |
.release = single_release,
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static void copyBioStat(BioStats *b, const AtomicBioStats *a)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
b->read = atomic64_read(&a->read);
|
|
Packit Service |
d40955 |
b->write = atomic64_read(&a->write);
|
|
Packit Service |
d40955 |
b->discard = atomic64_read(&a->discard);
|
|
Packit Service |
d40955 |
b->flush = atomic64_read(&a->flush);
|
|
Packit Service |
d40955 |
b->fua = atomic64_read(&a->fua);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static BioStats subtractBioStats(BioStats minuend, BioStats subtrahend)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (BioStats) {
|
|
Packit Service |
d40955 |
.read = minuend.read - subtrahend.read,
|
|
Packit Service |
d40955 |
.write = minuend.write - subtrahend.write,
|
|
Packit Service |
d40955 |
.discard = minuend.discard - subtrahend.discard,
|
|
Packit Service |
d40955 |
.flush = minuend.flush - subtrahend.flush,
|
|
Packit Service |
d40955 |
.fua = minuend.fua - subtrahend.fua,
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
void getKernelStats(KernelLayer *layer, KernelStatistics *stats)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
stats->version = STATISTICS_VERSION;
|
|
Packit Service |
d40955 |
stats->releaseVersion = CURRENT_RELEASE_VERSION_NUMBER;
|
|
Packit Service |
d40955 |
stats->instance = layer->instance;
|
|
Packit Service |
d40955 |
getLimiterValuesAtomically(&layer->requestLimiter,
|
|
Packit Service |
d40955 |
&stats->currentVIOsInProgress, &stats->maxVIOs);
|
|
Packit Service |
d40955 |
// albireoTimeoutReport gives the number of timeouts, and dedupeContextBusy
|
|
Packit Service |
d40955 |
// gives the number of queries not made because of earlier timeouts.
|
|
Packit Service |
d40955 |
stats->dedupeAdviceTimeouts = (getEventCount(&layer->albireoTimeoutReporter)
|
|
Packit Service |
d40955 |
+ atomic64_read(&layer->dedupeContextBusy));
|
|
Packit Service |
d40955 |
stats->flushOut = atomic64_read(&layer->flushOut);
|
|
Packit Service |
d40955 |
stats->logicalBlockSize = layer->deviceConfig->logicalBlockSize;
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosIn, &layer->biosIn);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosInPartial, &layer->biosInPartial);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosOut, &layer->biosOut);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosMeta, &layer->biosMeta);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosJournal, &layer->biosJournal);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosPageCache, &layer->biosPageCache);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosOutCompleted, &layer->biosOutCompleted);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosMetaCompleted, &layer->biosMetaCompleted);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosJournalCompleted, &layer->biosJournalCompleted);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosPageCacheCompleted,
|
|
Packit Service |
d40955 |
&layer->biosPageCacheCompleted);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosAcknowledged, &layer->biosAcknowledged);
|
|
Packit Service |
d40955 |
copyBioStat(&stats->biosAcknowledgedPartial,
|
|
Packit Service |
d40955 |
&layer->biosAcknowledgedPartial);
|
|
Packit Service |
d40955 |
stats->biosInProgress = subtractBioStats(stats->biosIn,
|
|
Packit Service |
d40955 |
stats->biosAcknowledged);
|
|
Packit Service |
d40955 |
stats->memoryUsage = getMemoryUsage();
|
|
Packit Service |
d40955 |
getIndexStatistics(layer->dedupeIndex, &stats->index);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static int statusKernelShow(struct seq_file *m, void *v)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
KernelLayer *layer = (KernelLayer *) m->private;
|
|
Packit Service |
d40955 |
KernelStatistics *stats;
|
|
Packit Service |
d40955 |
size_t len = sizeof(KernelStatistics);
|
|
Packit Service |
d40955 |
RegisteredThread allocatingThread, instanceThread;
|
|
Packit Service |
d40955 |
registerAllocatingThread(&allocatingThread, NULL);
|
|
Packit Service |
d40955 |
registerThreadDevice(&instanceThread, layer);
|
|
Packit Service |
d40955 |
int result = ALLOCATE(1, KernelStatistics, __func__, &stats);
|
|
Packit Service |
d40955 |
if (result == VDO_SUCCESS) {
|
|
Packit Service |
d40955 |
getKernelStats(layer, stats);
|
|
Packit Service |
d40955 |
seq_write(m, stats, len);
|
|
Packit Service |
d40955 |
FREE(stats);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
unregisterThreadDeviceID();
|
|
Packit Service |
d40955 |
unregisterAllocatingThread();
|
|
Packit Service |
d40955 |
return result;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
static int statusKernelOpen(struct inode *inode, struct file *file)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
|
Packit Service |
d40955 |
return single_open(file, statusKernelShow, PDE_DATA(inode));
|
|
Packit Service |
d40955 |
#else
|
|
Packit Service |
d40955 |
return single_open(file, statusKernelShow, PDE(inode)->data);
|
|
Packit Service |
d40955 |
#endif
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
static const struct file_operations vdoProcfsKernelOps = {
|
|
Packit Service |
d40955 |
.open = statusKernelOpen,
|
|
Packit Service |
d40955 |
.read = seq_read,
|
|
Packit Service |
d40955 |
.llseek = seq_lseek,
|
|
Packit Service |
d40955 |
.release = single_release,
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
int vdoInitProcfs()
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
const char *procfsName = getProcRoot();
|
|
Packit Service |
d40955 |
procfsRoot = proc_mkdir(procfsName, NULL);
|
|
Packit Service |
d40955 |
if (procfsRoot == NULL) {
|
|
Packit Service |
d40955 |
logWarning("Could not create proc filesystem root %s\n", procfsName);
|
|
Packit Service |
d40955 |
return -ENOMEM;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
return VDO_SUCCESS;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
void vdoDestroyProcfs()
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
remove_proc_entry(getProcRoot(), NULL);
|
|
Packit Service |
d40955 |
procfsRoot = NULL;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
int vdoCreateProcfsEntry(KernelLayer *layer, const char *name, void **private)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
int result = VDO_SUCCESS;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
if (procfsRoot != NULL) {
|
|
Packit Service |
d40955 |
struct proc_dir_entry *fsDir;
|
|
Packit Service |
d40955 |
fsDir = proc_mkdir(name, procfsRoot);
|
|
Packit Service |
d40955 |
if (fsDir == NULL) {
|
|
Packit Service |
d40955 |
result = -ENOMEM;
|
|
Packit Service |
d40955 |
} else {
|
|
Packit Service |
d40955 |
if (proc_create_data(getVDOStatisticsProcFile(), 0644, fsDir,
|
|
Packit Service |
d40955 |
&vdoProcfsDedupeOps, layer) == NULL) {
|
|
Packit Service |
d40955 |
result = -ENOMEM;
|
|
Packit Service |
d40955 |
} else if (proc_create_data(getKernelStatisticsProcFile(), 0644, fsDir,
|
|
Packit Service |
d40955 |
&vdoProcfsKernelOps, layer) == NULL) {
|
|
Packit Service |
d40955 |
result = -ENOMEM;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
if (result < 0) {
|
|
Packit Service |
d40955 |
vdoDestroyProcfsEntry(name, fsDir);
|
|
Packit Service |
d40955 |
} else {
|
|
Packit Service |
d40955 |
*private = fsDir;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
} else {
|
|
Packit Service |
d40955 |
logWarning("No proc filesystem root set, skipping %s\n", name);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
return result;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
void vdoDestroyProcfsEntry(const char *name, void *private)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (procfsRoot != NULL) {
|
|
Packit Service |
d40955 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
|
Packit Service |
d40955 |
remove_proc_subtree(name, procfsRoot);
|
|
Packit Service |
d40955 |
#else
|
|
Packit Service |
d40955 |
struct proc_dir_entry *fsDir = (struct proc_dir_entry *) private;
|
|
Packit Service |
d40955 |
remove_proc_entry(getVDOStatisticsProcFile(), fsDir);
|
|
Packit Service |
d40955 |
remove_proc_entry(getKernelStatisticsProcFile(), fsDir);
|
|
Packit Service |
d40955 |
remove_proc_entry(name, procfsRoot);
|
|
Packit Service |
d40955 |
#endif
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
}
|