|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
75d76b |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
75d76b |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
75d76b |
* of the License, or (at your option) any later version.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
75d76b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
75d76b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
75d76b |
* GNU General Public License for more details.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
75d76b |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
75d76b |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
75d76b |
* 02110-1301, USA.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/sysfs.c#5 $
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "sysfs.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include <linux/module.h>
|
|
Packit Service |
75d76b |
#include <linux/version.h>
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "dedupeIndex.h"
|
|
Packit Service |
75d76b |
#include "dmvdo.h"
|
|
Packit Service |
75d76b |
#include "logger.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
extern int defaultMaxRequestsActive;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
typedef struct vdoAttribute {
|
|
Packit Service |
75d76b |
struct attribute attr;
|
|
Packit Service |
75d76b |
ssize_t (*show)(struct kvdoDevice *d, struct attribute *attr, char *buf);
|
|
Packit Service |
75d76b |
ssize_t (*store)(struct kvdoDevice *d, const char *value, size_t count);
|
|
Packit Service |
75d76b |
// Location of value, if .show == showInt or showUInt or showBool.
|
|
Packit Service |
75d76b |
void *valuePtr;
|
|
Packit Service |
75d76b |
} VDOAttribute;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static char *statusStrings[] = {
|
|
Packit Service |
75d76b |
"UNINITIALIZED",
|
|
Packit Service |
75d76b |
"READY",
|
|
Packit Service |
75d76b |
"SHUTTING DOWN",
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoStatusShow(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return sprintf(buf, "%s\n", statusStrings[device->status]);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoLogLevelShow(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return sprintf(buf, "%s\n", priorityToString(getLogLevel()));
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoLogLevelStore(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
const char *buf, size_t n)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
static char internalBuf[11];
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
if (n > 10) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
memset(internalBuf, '\000', sizeof(internalBuf));
|
|
Packit Service |
75d76b |
memcpy(internalBuf, buf, n);
|
|
Packit Service |
75d76b |
if (internalBuf[n - 1] == '\n') {
|
|
Packit Service |
75d76b |
internalBuf[n - 1] = '\000';
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
setLogLevel(stringToPriority(internalBuf));
|
|
Packit Service |
75d76b |
return n;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t scanInt(const char *buf,
|
|
Packit Service |
75d76b |
size_t n,
|
|
Packit Service |
75d76b |
int *valuePtr,
|
|
Packit Service |
75d76b |
int minimum,
|
|
Packit Service |
75d76b |
int maximum)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
if (n > 12) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
unsigned int value;
|
|
Packit Service |
75d76b |
if (sscanf(buf, "%d", &value) != 1) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
if (value < minimum) {
|
|
Packit Service |
75d76b |
value = minimum;
|
|
Packit Service |
75d76b |
} else if (value > maximum) {
|
|
Packit Service |
75d76b |
value = maximum;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
*valuePtr = value;
|
|
Packit Service |
75d76b |
return n;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t showInt(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
VDOAttribute *vdoAttr = container_of(attr, VDOAttribute, attr);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
return sprintf(buf, "%d\n", *(int *)vdoAttr->valuePtr);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t scanUInt(const char *buf,
|
|
Packit Service |
75d76b |
size_t n,
|
|
Packit Service |
75d76b |
unsigned int *valuePtr,
|
|
Packit Service |
75d76b |
unsigned int minimum,
|
|
Packit Service |
75d76b |
unsigned int maximum)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
if (n > 12) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
unsigned int value;
|
|
Packit Service |
75d76b |
if (sscanf(buf, "%u", &value) != 1) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
if (value < minimum) {
|
|
Packit Service |
75d76b |
value = minimum;
|
|
Packit Service |
75d76b |
} else if (value > maximum) {
|
|
Packit Service |
75d76b |
value = maximum;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
*valuePtr = value;
|
|
Packit Service |
75d76b |
return n;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t showUInt(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
VDOAttribute *vdoAttr = container_of(attr, VDOAttribute, attr);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
return sprintf(buf, "%u\n", *(unsigned int *)vdoAttr->valuePtr);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t scanBool(const char *buf, size_t n, bool *valuePtr)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
unsigned int intValue = 0;
|
|
Packit Service |
75d76b |
n = scanUInt(buf, n, &intValue, 0, 1);
|
|
Packit Service |
75d76b |
if (n > 0) {
|
|
Packit Service |
75d76b |
*valuePtr = (intValue != 0);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return n;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t showBool(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
VDOAttribute *vdoAttr = container_of(attr, VDOAttribute, attr);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
return sprintf(buf, "%u\n", *(bool *)vdoAttr->valuePtr ? 1 : 0);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoTraceRecordingStore(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
const char *buf,
|
|
Packit Service |
75d76b |
size_t n)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return scanBool(buf, n, &traceRecording);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoMaxReqActiveStore(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
const char *buf,
|
|
Packit Service |
75d76b |
size_t n)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* The base code has some hardcoded assumptions about the maximum
|
|
Packit Service |
75d76b |
* number of requests that can be in progress. Maybe someday we'll
|
|
Packit Service |
75d76b |
* do calculations with the actual number; for now, just make sure
|
|
Packit Service |
75d76b |
* the assumption holds.
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
return scanInt(buf, n, &defaultMaxRequestsActive, 1, MAXIMUM_USER_VIOS);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoAlbireoTimeoutIntervalStore(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
const char *buf,
|
|
Packit Service |
75d76b |
size_t n)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
unsigned int value;
|
|
Packit Service |
75d76b |
ssize_t result = scanUInt(buf, n, &value, 0, UINT_MAX);
|
|
Packit Service |
75d76b |
if (result > 0) {
|
|
Packit Service |
75d76b |
setAlbireoTimeoutInterval(value);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoMinAlbireoTimerIntervalStore(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
const char *buf,
|
|
Packit Service |
75d76b |
size_t n)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
unsigned int value;
|
|
Packit Service |
75d76b |
ssize_t result = scanUInt(buf, n, &value, 0, UINT_MAX);
|
|
Packit Service |
75d76b |
if (result > 0) {
|
|
Packit Service |
75d76b |
setMinAlbireoTimerInterval(value);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoVersionShow(struct kvdoDevice *device,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return sprintf(buf, "%s\n", CURRENT_VERSION);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoAttrShow(struct kobject *kobj,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
char *buf)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
VDOAttribute *vdoAttr = container_of(attr, VDOAttribute, attr);
|
|
Packit Service |
75d76b |
if (vdoAttr->show == NULL) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
struct kvdoDevice *device = container_of(kobj, struct kvdoDevice, kobj);
|
|
Packit Service |
75d76b |
return (*vdoAttr->show)(device, attr, buf);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static ssize_t vdoAttrStore(struct kobject *kobj,
|
|
Packit Service |
75d76b |
struct attribute *attr,
|
|
Packit Service |
75d76b |
const char *buf,
|
|
Packit Service |
75d76b |
size_t length)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
VDOAttribute *vdoAttr = container_of(attr, VDOAttribute, attr);
|
|
Packit Service |
75d76b |
if (vdoAttr->store == NULL) {
|
|
Packit Service |
75d76b |
return -EINVAL;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
struct kvdoDevice *device = container_of(kobj, struct kvdoDevice, kobj);
|
|
Packit Service |
75d76b |
return (*vdoAttr->store)(device, buf, length);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoStatusAttr = {
|
|
Packit Service |
75d76b |
.attr = { .name = "status", .mode = 0444, },
|
|
Packit Service |
75d76b |
.show = vdoStatusShow,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoLogLevelAttr = {
|
|
Packit Service |
75d76b |
.attr = {.name = "log_level", .mode = 0644, },
|
|
Packit Service |
75d76b |
.show = vdoLogLevelShow,
|
|
Packit Service |
75d76b |
.store = vdoLogLevelStore,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoMaxReqActiveAttr = {
|
|
Packit Service |
75d76b |
.attr = {.name = "max_requests_active", .mode = 0644, },
|
|
Packit Service |
75d76b |
.show = showInt,
|
|
Packit Service |
75d76b |
.store = vdoMaxReqActiveStore,
|
|
Packit Service |
75d76b |
.valuePtr = &defaultMaxRequestsActive,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoAlbireoTimeoutInterval = {
|
|
Packit Service |
75d76b |
.attr = {.name = "deduplication_timeout_interval", .mode = 0644, },
|
|
Packit Service |
75d76b |
.show = showUInt,
|
|
Packit Service |
75d76b |
.store = vdoAlbireoTimeoutIntervalStore,
|
|
Packit Service |
75d76b |
.valuePtr = &albireoTimeoutInterval,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoMinAlbireoTimerInterval = {
|
|
Packit Service |
75d76b |
.attr = {.name = "min_deduplication_timer_interval", .mode = 0644, },
|
|
Packit Service |
75d76b |
.show = showUInt,
|
|
Packit Service |
75d76b |
.store = vdoMinAlbireoTimerIntervalStore,
|
|
Packit Service |
75d76b |
.valuePtr = &minAlbireoTimerInterval,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoTraceRecording = {
|
|
Packit Service |
75d76b |
.attr = {.name = "trace_recording", .mode = 0644, },
|
|
Packit Service |
75d76b |
.show = showBool,
|
|
Packit Service |
75d76b |
.store = vdoTraceRecordingStore,
|
|
Packit Service |
75d76b |
.valuePtr = &traceRecording,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static VDOAttribute vdoVersionAttr = {
|
|
Packit Service |
75d76b |
.attr = { .name = "version", .mode = 0444, },
|
|
Packit Service |
75d76b |
.show = vdoVersionShow,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static struct attribute *defaultAttrs[] = {
|
|
Packit Service |
75d76b |
&vdoStatusAttr.attr,
|
|
Packit Service |
75d76b |
&vdoLogLevelAttr.attr,
|
|
Packit Service |
75d76b |
&vdoMaxReqActiveAttr.attr,
|
|
Packit Service |
75d76b |
&vdoAlbireoTimeoutInterval.attr,
|
|
Packit Service |
75d76b |
&vdoMinAlbireoTimerInterval.attr,
|
|
Packit Service |
75d76b |
&vdoTraceRecording.attr,
|
|
Packit Service |
75d76b |
&vdoVersionAttr.attr,
|
|
Packit Service |
75d76b |
NULL
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static struct sysfs_ops vdoSysfsOps = {
|
|
Packit Service |
75d76b |
.show = vdoAttrShow,
|
|
Packit Service |
75d76b |
.store = vdoAttrStore,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
static void vdoRelease(struct kobject *kobj)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
struct kobj_type vdo_ktype = {
|
|
Packit Service |
75d76b |
.release = vdoRelease,
|
|
Packit Service |
75d76b |
.sysfs_ops = &vdoSysfsOps,
|
|
Packit Service |
75d76b |
.default_attrs = defaultAttrs,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
int vdoInitSysfs(struct kobject *deviceObject)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
kobject_init(deviceObject, &vdo_ktype);
|
|
Packit Service |
75d76b |
int result = kobject_add(deviceObject, NULL, THIS_MODULE->name);
|
|
Packit Service |
75d76b |
if (result < 0) {
|
|
Packit Service |
75d76b |
logError("kobject_add failed with status %d", -result);
|
|
Packit Service |
75d76b |
kobject_put(deviceObject);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
logDebug("added sysfs objects");
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
void vdoPutSysfs(struct kobject *deviceObject)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
kobject_put(deviceObject);
|
|
Packit Service |
75d76b |
}
|