Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linuxkpi/3.15/include/linux/sysfs.h
- This file was added.
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | |||||
* Copyright (c) 2010 Isilon Systems, Inc. | |||||
* Copyright (c) 2010 iX Systems, Inc. | |||||
* Copyright (c) 2010 Panasas, Inc. | |||||
* Copyright (c) 2013, 2014 Mellanox Technologies, Ltd. | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice unmodified, this list of conditions, and the following | |||||
* disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#ifndef _LINUX_SYSFS_H_ | |||||
#define _LINUX_SYSFS_H_ | |||||
#include <sys/sysctl.h> | |||||
struct attribute { | |||||
const char *name; | |||||
struct module *owner; | |||||
mode_t mode; | |||||
}; | |||||
struct sysfs_ops { | |||||
ssize_t (*show)(struct kobject *, struct attribute *, char *); | |||||
ssize_t (*store)(struct kobject *, struct attribute *, const char *, | |||||
size_t); | |||||
}; | |||||
struct attribute_group { | |||||
const char *name; | |||||
mode_t (*is_visible)(struct kobject *, | |||||
struct attribute *, int); | |||||
struct attribute **attrs; | |||||
}; | |||||
#define __ATTR(_name, _mode, _show, _store) { \ | |||||
.attr = { .name = __stringify(_name), .mode = _mode }, \ | |||||
.show = _show, .store = _store, \ | |||||
} | |||||
#define __ATTR_RO(_name) { \ | |||||
.attr = { .name = __stringify(_name), .mode = 0444 }, \ | |||||
.show = _name##_show, \ | |||||
} | |||||
#define __ATTR_NULL { .attr = { .name = NULL } } | |||||
/* | |||||
* Handle our generic '\0' terminated 'C' string. | |||||
* Two cases: | |||||
* a variable string: point arg1 at it, arg2 is max length. | |||||
* a constant string: point arg1 at it, arg2 is zero. | |||||
*/ | |||||
static inline int | |||||
sysctl_handle_attr(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct kobject *kobj; | |||||
struct attribute *attr; | |||||
const struct sysfs_ops *ops; | |||||
char *buf; | |||||
int error; | |||||
ssize_t len; | |||||
kobj = arg1; | |||||
attr = (struct attribute *)arg2; | |||||
if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL) | |||||
return (ENODEV); | |||||
buf = (char *)get_zeroed_page(GFP_KERNEL); | |||||
if (buf == NULL) | |||||
return (ENOMEM); | |||||
ops = kobj->ktype->sysfs_ops; | |||||
if (ops->show) { | |||||
len = ops->show(kobj, attr, buf); | |||||
/* | |||||
* It's valid to not have a 'show' so just return an | |||||
* empty string. | |||||
*/ | |||||
if (len < 0) { | |||||
error = -len; | |||||
if (error != EIO) | |||||
goto out; | |||||
buf[0] = '\0'; | |||||
} else if (len) { | |||||
len--; | |||||
if (len >= PAGE_SIZE) | |||||
len = PAGE_SIZE - 1; | |||||
/* Trim trailing newline. */ | |||||
buf[len] = '\0'; | |||||
} | |||||
} | |||||
/* Leave one trailing byte to append a newline. */ | |||||
error = sysctl_handle_string(oidp, buf, PAGE_SIZE - 1, req); | |||||
if (error != 0 || req->newptr == NULL || ops->store == NULL) | |||||
goto out; | |||||
len = strlcat(buf, "\n", PAGE_SIZE); | |||||
KASSERT(len < PAGE_SIZE, ("new attribute truncated")); | |||||
len = ops->store(kobj, attr, buf, len); | |||||
if (len < 0) | |||||
error = -len; | |||||
out: | |||||
free_page((unsigned long)buf); | |||||
return (error); | |||||
} | |||||
static inline int | |||||
sysfs_create_file(struct kobject *kobj, const struct attribute *attr) | |||||
{ | |||||
sysctl_add_oid(NULL, SYSCTL_CHILDREN(kobj->oidp), OID_AUTO, | |||||
attr->name, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, kobj, | |||||
(uintptr_t)attr, sysctl_handle_attr, "A", ""); | |||||
return (0); | |||||
} | |||||
static inline void | |||||
sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) | |||||
{ | |||||
if (kobj->oidp) | |||||
sysctl_remove_name(kobj->oidp, attr->name, 1, 1); | |||||
} | |||||
static inline void | |||||
sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp) | |||||
{ | |||||
if (kobj->oidp) | |||||
sysctl_remove_name(kobj->oidp, grp->name, 1, 1); | |||||
} | |||||
static inline int | |||||
sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) | |||||
{ | |||||
struct attribute **attr; | |||||
struct sysctl_oid *oidp; | |||||
oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(kobj->oidp), | |||||
OID_AUTO, grp->name, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, grp->name); | |||||
for (attr = grp->attrs; *attr != NULL; attr++) { | |||||
sysctl_add_oid(NULL, SYSCTL_CHILDREN(oidp), OID_AUTO, | |||||
(*attr)->name, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, | |||||
kobj, (uintptr_t)*attr, sysctl_handle_attr, "A", ""); | |||||
} | |||||
return (0); | |||||
} | |||||
static inline int | |||||
sysfs_create_dir(struct kobject *kobj) | |||||
{ | |||||
kobj->oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(kobj->parent->oidp), | |||||
OID_AUTO, kobj->name, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, kobj->name); | |||||
return (0); | |||||
} | |||||
static inline void | |||||
sysfs_remove_dir(struct kobject *kobj) | |||||
{ | |||||
if (kobj->oidp == NULL) | |||||
return; | |||||
sysctl_remove_oid(kobj->oidp, 1, 1); | |||||
} | |||||
#define sysfs_attr_init(attr) do {} while(0) | |||||
#endif /* _LINUX_SYSFS_H_ */ |