mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-06 12:06:26 +00:00
scoutfs: add sysfs.c, fsid file
I wanted to add a sysfs file that exports the fsid for the mount of a given device. But our use of sysfs was confusing and spread through super.c and counters.c. This moves the core of our sysfs use to sysfs.c. Instead of defining the per-mount dir as a kset we define it as an object with attributes which gives us a place to add an fsid attribute. counters still have their own whack of sysfs implementation. We'll let it keep it for now but we could move it into sysfs.c. It's just counter interation around the insane sysfs obj/attr/type nonsense. For now it just needs to know to add its counters dir as a child of the per-mount dir instead of adding it to the kset. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -8,8 +8,8 @@ CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include
|
||||
scoutfs-y += alloc.o bio.o btree.o client.o compact.o counters.o data.o dir.o \
|
||||
dlmglue.o file.o kvec.o inode.o ioctl.o item.o key.o lock.o \
|
||||
manifest.o msg.o options.o per_task.o seg.o server.o \
|
||||
scoutfs_trace.o sock.o sort_priv.o stackglue.o super.o trans.o \
|
||||
triggers.o xattr.o
|
||||
scoutfs_trace.o sock.o sort_priv.o stackglue.o super.o sysfs.o \
|
||||
trans.o triggers.o xattr.o
|
||||
|
||||
#
|
||||
# The raw types aren't available in userspace headers. Make sure all
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/percpu_counter.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "sysfs.h"
|
||||
#include "counters.h"
|
||||
|
||||
/*
|
||||
@@ -85,10 +86,9 @@ int scoutfs_setup_counters(struct super_block *sb)
|
||||
goto out;
|
||||
}
|
||||
|
||||
counters->kobj.kset = sbi->kset;
|
||||
init_completion(&counters->comp);
|
||||
ret = kobject_init_and_add(&counters->kobj, &scoutfs_counters_ktype,
|
||||
NULL, "counters");
|
||||
scoutfs_sysfs_sb_dir(sb), "counters");
|
||||
out:
|
||||
if (ret) {
|
||||
/* tear down partial to avoid destroying null kobjs */
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
#include "client.h"
|
||||
#include "server.h"
|
||||
#include "options.h"
|
||||
#include "sysfs.h"
|
||||
#include "scoutfs_trace.h"
|
||||
|
||||
static struct kset *scoutfs_kset;
|
||||
static struct dentry *scoutfs_debugfs_root;
|
||||
|
||||
/*
|
||||
@@ -129,8 +129,7 @@ static void scoutfs_put_super(struct super_block *sb)
|
||||
scoutfs_destroy_triggers(sb);
|
||||
debugfs_remove(sbi->debug_root);
|
||||
scoutfs_destroy_counters(sb);
|
||||
if (sbi->kset)
|
||||
kset_unregister(sbi->kset);
|
||||
scoutfs_destroy_sysfs(sb);
|
||||
kfree(sbi);
|
||||
|
||||
sb->s_fs_info = NULL;
|
||||
@@ -310,12 +309,6 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
INIT_DELAYED_WORK(&sbi->trans_write_work, scoutfs_trans_write_func);
|
||||
init_waitqueue_head(&sbi->trans_write_wq);
|
||||
|
||||
/* XXX can have multiple mounts of a device, need mount id */
|
||||
sbi->kset = kset_create_and_add(sb->s_id, NULL, &scoutfs_kset->kobj);
|
||||
if (!sbi->kset) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_parse_options(sb, data, &opts);
|
||||
if (ret)
|
||||
@@ -323,7 +316,8 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
|
||||
sbi->opts = opts;
|
||||
|
||||
ret = scoutfs_setup_counters(sb) ?:
|
||||
ret = scoutfs_setup_sysfs(sb) ?:
|
||||
scoutfs_setup_counters(sb) ?:
|
||||
scoutfs_read_supers(sb, &SCOUTFS_SB(sb)->super) ?:
|
||||
scoutfs_debugfs_setup(sb) ?:
|
||||
scoutfs_setup_triggers(sb) ?:
|
||||
@@ -398,8 +392,7 @@ static void teardown_module(void)
|
||||
debugfs_remove(scoutfs_debugfs_root);
|
||||
scoutfs_dir_exit();
|
||||
scoutfs_inode_exit();
|
||||
if (scoutfs_kset)
|
||||
kset_unregister(scoutfs_kset);
|
||||
scoutfs_sysfs_exit();
|
||||
}
|
||||
|
||||
static int __init scoutfs_module_init(void)
|
||||
@@ -421,9 +414,9 @@ static int __init scoutfs_module_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
scoutfs_kset = kset_create_and_add("scoutfs", NULL, fs_kobj);
|
||||
if (!scoutfs_kset)
|
||||
return -ENOMEM;
|
||||
ret = scoutfs_sysfs_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
scoutfs_debugfs_root = debugfs_create_dir("scoutfs", NULL);
|
||||
if (!scoutfs_debugfs_root) {
|
||||
|
||||
@@ -20,6 +20,7 @@ struct client_info;
|
||||
struct server_info;
|
||||
struct inode_sb_info;
|
||||
struct btree_info;
|
||||
struct sysfs_info;
|
||||
|
||||
struct scoutfs_sb_info {
|
||||
struct super_block *sb;
|
||||
@@ -57,9 +58,7 @@ struct scoutfs_sb_info {
|
||||
struct lock_info *lock_info;
|
||||
struct client_info *client_info;
|
||||
struct server_info *server_info;
|
||||
|
||||
/* $sysfs/fs/scoutfs/$id/ */
|
||||
struct kset *kset;
|
||||
struct sysfs_info *sfsinfo;
|
||||
|
||||
struct scoutfs_counters *counters;
|
||||
struct scoutfs_triggers *triggers;
|
||||
|
||||
160
kmod/src/sysfs.c
Normal file
160
kmod/src/sysfs.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Versity Software, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
static struct kset *scoutfs_kset;
|
||||
|
||||
struct sysfs_info {
|
||||
struct super_block *sb;
|
||||
struct kobject sb_id_kobj;
|
||||
struct completion sb_id_comp;
|
||||
};
|
||||
|
||||
#define KOBJ_TO_SB(kobj, which) \
|
||||
container_of(kobj, struct sysfs_info, which)->sb
|
||||
|
||||
struct attr_funcs {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf);
|
||||
};
|
||||
|
||||
#define ATTR_FUNCS_RO(_name) \
|
||||
static struct attr_funcs _name##_attr_funcs = __ATTR_RO(_name)
|
||||
|
||||
static ssize_t fsid_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct super_block *sb = KOBJ_TO_SB(kobj, sb_id_kobj);
|
||||
struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llx\n", le64_to_cpu(super->hdr.fsid));
|
||||
}
|
||||
ATTR_FUNCS_RO(fsid);
|
||||
|
||||
/*
|
||||
* ops are defined per type, not per attribute. To have attributes with
|
||||
* different types that want different funcs we wrap them with a struct
|
||||
* that has per-type funcs.
|
||||
*/
|
||||
static ssize_t attr_funcs_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct attr_funcs *af = container_of(attr, struct attr_funcs, attr);
|
||||
|
||||
return af->show(kobj, attr, buf);
|
||||
}
|
||||
|
||||
#define KTYPE(_name) \
|
||||
static void _name##_release(struct kobject *kobj) \
|
||||
{ \
|
||||
struct sysfs_info *sfsinfo; \
|
||||
\
|
||||
sfsinfo = container_of(kobj, struct sysfs_info, _name##_kobj);\
|
||||
\
|
||||
complete(&sfsinfo->_name##_comp); \
|
||||
} \
|
||||
static const struct sysfs_ops _name##_sysfs_ops = { \
|
||||
.show = attr_funcs_show, \
|
||||
}; \
|
||||
\
|
||||
static struct kobj_type _name##_ktype = { \
|
||||
.default_attrs = _name##_attrs, \
|
||||
.sysfs_ops = &_name##_sysfs_ops, \
|
||||
.release = _name##_release, \
|
||||
};
|
||||
|
||||
|
||||
static struct attribute *sb_id_attrs[] = {
|
||||
&fsid_attr_funcs.attr,
|
||||
NULL,
|
||||
};
|
||||
KTYPE(sb_id);
|
||||
|
||||
struct kobject *scoutfs_sysfs_sb_dir(struct super_block *sb)
|
||||
{
|
||||
struct sysfs_info *sfsinfo = SCOUTFS_SB(sb)->sfsinfo;
|
||||
|
||||
return &sfsinfo->sb_id_kobj;
|
||||
}
|
||||
|
||||
static void kobj_del_put_wait(struct kobject *kobj, struct completion *comp)
|
||||
{
|
||||
kobject_del(kobj);
|
||||
kobject_put(kobj);
|
||||
wait_for_completion(comp);
|
||||
}
|
||||
|
||||
#define shutdown_kobj(sfinfo, _name) \
|
||||
kobj_del_put_wait(&sfsinfo->_name##_kobj, &sfsinfo->_name##_comp)
|
||||
|
||||
/*
|
||||
* Only the return from kobj_init_and_add() tells us if the kobj needs
|
||||
* to be cleaned up or not. This must manually clean up the kobjs and
|
||||
* only leave full cleanup to _destroy_.
|
||||
*/
|
||||
int scoutfs_setup_sysfs(struct super_block *sb)
|
||||
{
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct sysfs_info *sfsinfo;
|
||||
int ret;
|
||||
|
||||
sfsinfo = kzalloc(sizeof(struct sysfs_info), GFP_KERNEL);
|
||||
if (!sfsinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
sfsinfo->sb = sb;
|
||||
sbi->sfsinfo = sfsinfo;
|
||||
|
||||
/* XXX can have multiple mounts of a device, need mount id */
|
||||
init_completion(&sfsinfo->sb_id_comp);
|
||||
ret = kobject_init_and_add(&sfsinfo->sb_id_kobj, &sb_id_ktype,
|
||||
&scoutfs_kset->kobj, "%s", sb->s_id);
|
||||
if (ret)
|
||||
kfree(sfsinfo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scoutfs_destroy_sysfs(struct super_block *sb)
|
||||
{
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct sysfs_info *sfsinfo = sbi->sfsinfo;
|
||||
|
||||
if (sfsinfo) {
|
||||
shutdown_kobj(sfsinfo, sb_id);
|
||||
|
||||
kfree(sfsinfo);
|
||||
sbi->sfsinfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int __init scoutfs_sysfs_init(void)
|
||||
{
|
||||
scoutfs_kset = kset_create_and_add("scoutfs", NULL, fs_kobj);
|
||||
if (!scoutfs_kset)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit scoutfs_sysfs_exit(void)
|
||||
{
|
||||
if (scoutfs_kset)
|
||||
kset_unregister(scoutfs_kset);
|
||||
}
|
||||
12
kmod/src/sysfs.h
Normal file
12
kmod/src/sysfs.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _SCOUTFS_SYSFS_H_
|
||||
#define _SCOUTFS_SYSFS_H_
|
||||
|
||||
struct kobject *scoutfs_sysfs_sb_dir(struct super_block *sb);
|
||||
|
||||
int scoutfs_setup_sysfs(struct super_block *sb);
|
||||
void scoutfs_destroy_sysfs(struct super_block *sb);
|
||||
|
||||
int __init scoutfs_sysfs_init(void);
|
||||
void __exit scoutfs_sysfs_exit(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user