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:
Zach Brown
2017-12-18 16:51:04 -08:00
committed by Mark Fasheh
parent 9ed34f8892
commit e354fd18b1
6 changed files with 186 additions and 22 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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) {

View File

@@ -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
View 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
View 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