/*
* Copyright (c) 2020 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/poolSysfs.c#1 $
*/
#include "poolSysfs.h"
#include "memoryAlloc.h"
#include "vdo.h"
#include "dedupeIndex.h"
typedef struct poolAttribute {
struct attribute attr;
ssize_t (*show)(KernelLayer *layer, char *buf);
ssize_t (*store)(KernelLayer *layer, const char *value, size_t count);
} PoolAttribute;
/**********************************************************************/
static ssize_t vdoPoolAttrShow(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
PoolAttribute *poolAttr = container_of(attr, PoolAttribute, attr);
if (poolAttr->show == NULL) {
return -EINVAL;
}
KernelLayer *layer = container_of(kobj, KernelLayer, kobj);
return poolAttr->show(layer, buf);
}
/**********************************************************************/
static ssize_t vdoPoolAttrStore(struct kobject *kobj,
struct attribute *attr,
const char *buf,
size_t length)
{
PoolAttribute *poolAttr = container_of(attr, PoolAttribute, attr);
if (poolAttr->store == NULL) {
return -EINVAL;
}
KernelLayer *layer = container_of(kobj, KernelLayer, kobj);
return poolAttr->store(layer, buf, length);
}
static struct sysfs_ops vdoPoolSysfsOps = {
.show = vdoPoolAttrShow,
.store = vdoPoolAttrStore,
};
/**********************************************************************/
static ssize_t poolCompressingShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%s\n", (getKVDOCompressing(&layer->kvdo) ? "1" : "0"));
}
/**********************************************************************/
static ssize_t poolDiscardsActiveShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->discardLimiter.active);
}
/**********************************************************************/
static ssize_t poolDiscardsLimitShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->discardLimiter.limit);
}
/**********************************************************************/
static ssize_t poolDiscardsLimitStore(KernelLayer *layer,
const char *buf,
size_t length)
{
unsigned int value;
if ((length > 12) || (sscanf(buf, "%u", &value) != 1) || (value < 1)) {
return -EINVAL;
}
layer->discardLimiter.limit = value;
return length;
}
/**********************************************************************/
static ssize_t poolDiscardsMaximumShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->discardLimiter.maximum);
}
/**********************************************************************/
static ssize_t poolInstanceShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%u\n", layer->instance);
}
/**********************************************************************/
static ssize_t poolRequestsActiveShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->requestLimiter.active);
}
/**********************************************************************/
static ssize_t poolRequestsLimitShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->requestLimiter.limit);
}
/**********************************************************************/
static ssize_t poolRequestsMaximumShow(KernelLayer *layer, char *buf)
{
return sprintf(buf, "%" PRIu32 "\n", layer->requestLimiter.maximum);
}
/**********************************************************************/
static void vdoPoolRelease(struct kobject *kobj)
{
KernelLayer *layer = container_of(kobj, KernelLayer, kobj);
freeVDO(&layer->kvdo.vdo);
FREE(layer);
}
static PoolAttribute vdoPoolCompressingAttr = {
.attr = { .name = "compressing", .mode = 0444, },
.show = poolCompressingShow,
};
static PoolAttribute vdoPoolDiscardsActiveAttr = {
.attr = { .name = "discards_active", .mode = 0444, },
.show = poolDiscardsActiveShow,
};
static PoolAttribute vdoPoolDiscardsLimitAttr = {
.attr = { .name = "discards_limit", .mode = 0644, },
.show = poolDiscardsLimitShow,
.store = poolDiscardsLimitStore,
};
static PoolAttribute vdoPoolDiscardsMaximumAttr = {
.attr = { .name = "discards_maximum", .mode = 0444, },
.show = poolDiscardsMaximumShow,
};
static PoolAttribute vdoPoolInstanceAttr = {
.attr = { .name = "instance", .mode = 0444, },
.show = poolInstanceShow,
};
static PoolAttribute vdoPoolRequestsActiveAttr = {
.attr = { .name = "requests_active", .mode = 0444, },
.show = poolRequestsActiveShow,
};
static PoolAttribute vdoPoolRequestsLimitAttr = {
.attr = { .name = "requests_limit", .mode = 0444, },
.show = poolRequestsLimitShow,
};
static PoolAttribute vdoPoolRequestsMaximumAttr = {
.attr = { .name = "requests_maximum", .mode = 0444, },
.show = poolRequestsMaximumShow,
};
static struct attribute *poolAttrs[] = {
&vdoPoolCompressingAttr.attr,
&vdoPoolDiscardsActiveAttr.attr,
&vdoPoolDiscardsLimitAttr.attr,
&vdoPoolDiscardsMaximumAttr.attr,
&vdoPoolInstanceAttr.attr,
&vdoPoolRequestsActiveAttr.attr,
&vdoPoolRequestsLimitAttr.attr,
&vdoPoolRequestsMaximumAttr.attr,
NULL,
};
struct kobj_type kernelLayerKobjType = {
.release = vdoPoolRelease,
.sysfs_ops = &vdoPoolSysfsOps,
.default_attrs = poolAttrs,
};
/**********************************************************************/
static void workQueueDirectoryRelease(struct kobject *kobj)
{
/*
* The workQueueDirectory holds an implicit reference to its parent,
* the kernelLayer object (->kobj), so even if there are some
* external references held to the workQueueDirectory when work
* queue shutdown calls kobject_put on the kernelLayer object, the
* kernelLayer object won't actually be released and won't free the
* KernelLayer storage until the workQueueDirectory object is
* released first.
*
* So, we don't need to do any additional explicit management here.
*
* (But we aren't allowed to use a NULL function pointer to indicate
* a no-op.)
*/
}
/**********************************************************************/
static struct attribute *noAttrs[] = {
NULL,
};
static struct sysfs_ops noSysfsOps = {
// These should never be reachable since there are no attributes.
.show = NULL,
.store = NULL,
};
struct kobj_type workQueueDirectoryKobjType = {
.release = workQueueDirectoryRelease,
.sysfs_ops = &noSysfsOps,
.default_attrs = noAttrs,
};