// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2019 Hammerspace Inc
 */

#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/nfs_fs.h>
#include <linux/rcupdate.h>

#include "nfs4_fs.h"
#include "netns.h"
#include "sysfs.h"

struct kobject *nfs_client_kobj;
static struct kset *nfs_kset;

static void nfs_netns_object_release(struct kobject *kobj)
{
	kfree(kobj);
}

static const struct kobj_ns_type_operations *nfs_netns_object_child_ns_type(
		struct kobject *kobj)
{
	return &net_ns_type_operations;
}

static struct kobj_type nfs_netns_object_type = {
	.release = nfs_netns_object_release,
	.sysfs_ops = &kobj_sysfs_ops,
	.child_ns_type = nfs_netns_object_child_ns_type,
};

static struct kobject *nfs_netns_object_alloc(const char *name,
		struct kset *kset, struct kobject *parent)
{
	struct kobject *kobj;

	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
	if (kobj) {
		kobj->kset = kset;
		if (kobject_init_and_add(kobj, &nfs_netns_object_type,
					parent, "%s", name) == 0)
			return kobj;
		kobject_put(kobj);
	}
	return NULL;
}

int nfs_sysfs_init(void)
{
	nfs_kset = kset_create_and_add("nfs", NULL, fs_kobj);
	if (!nfs_kset)
		return -ENOMEM;
	nfs_client_kobj = nfs_netns_object_alloc("net", nfs_kset, NULL);
	if  (!nfs_client_kobj) {
		kset_unregister(nfs_kset);
		nfs_kset = NULL;
		return -ENOMEM;
	}
	return 0;
}

void nfs_sysfs_exit(void)
{
	kobject_put(nfs_client_kobj);
	kset_unregister(nfs_kset);
}

static ssize_t nfs_netns_identifier_show(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	struct nfs_netns_client *c = container_of(kobj,
			struct nfs_netns_client,
			kobject);
	ssize_t ret;

	rcu_read_lock();
	ret = scnprintf(buf, PAGE_SIZE, "%s\n", rcu_dereference(c->identifier));
	rcu_read_unlock();
	return ret;
}

/* Strip trailing '\n' */
static size_t nfs_string_strip(const char *c, size_t len)
{
	while (len > 0 && c[len-1] == '\n')
		--len;
	return len;
}

static ssize_t nfs_netns_identifier_store(struct kobject *kobj,
		struct kobj_attribute *attr,
		const char *buf, size_t count)
{
	struct nfs_netns_client *c = container_of(kobj,
			struct nfs_netns_client,
			kobject);
	const char *old;
	char *p;
	size_t len;

	len = nfs_string_strip(buf, min_t(size_t, count, CONTAINER_ID_MAXLEN));
	if (!len)
		return 0;
	p = kmemdup_nul(buf, len, GFP_KERNEL);
	if (!p)
		return -ENOMEM;
	old = rcu_dereference_protected(xchg(&c->identifier, (char __rcu *)p), 1);
	if (old) {
		synchronize_rcu();
		kfree(old);
	}
	return count;
}

static void nfs_netns_client_release(struct kobject *kobj)
{
	struct nfs_netns_client *c = container_of(kobj,
			struct nfs_netns_client,
			kobject);

	kfree(rcu_dereference_raw(c->identifier));
	kfree(c);
}

static const void *nfs_netns_client_namespace(struct kobject *kobj)
{
	return container_of(kobj, struct nfs_netns_client, kobject)->net;
}

static struct kobj_attribute nfs_netns_client_id = __ATTR(identifier,
		0644, nfs_netns_identifier_show, nfs_netns_identifier_store);

static struct attribute *nfs_netns_client_attrs[] = {
	&nfs_netns_client_id.attr,
	NULL,
};
ATTRIBUTE_GROUPS(nfs_netns_client);

static struct kobj_type nfs_netns_client_type = {
	.release = nfs_netns_client_release,
	.default_groups = nfs_netns_client_groups,
	.sysfs_ops = &kobj_sysfs_ops,
	.namespace = nfs_netns_client_namespace,
};

static struct nfs_netns_client *nfs_netns_client_alloc(struct kobject *parent,
		struct net *net)
{
	struct nfs_netns_client *p;

	p = kzalloc(sizeof(*p), GFP_KERNEL);
	if (p) {
		p->net = net;
		p->kobject.kset = nfs_kset;
		if (kobject_init_and_add(&p->kobject, &nfs_netns_client_type,
					parent, "nfs_client") == 0)
			return p;
		kobject_put(&p->kobject);
	}
	return NULL;
}

void nfs_netns_sysfs_setup(struct nfs_net *netns, struct net *net)
{
	struct nfs_netns_client *clp;

	clp = nfs_netns_client_alloc(nfs_client_kobj, net);
	if (clp) {
		netns->nfs_client = clp;
		kobject_uevent(&clp->kobject, KOBJ_ADD);
	}
}

void nfs_netns_sysfs_destroy(struct nfs_net *netns)
{
	struct nfs_netns_client *clp = netns->nfs_client;

	if (clp) {
		kobject_uevent(&clp->kobject, KOBJ_REMOVE);
		kobject_del(&clp->kobject);
		kobject_put(&clp->kobject);
		netns->nfs_client = NULL;
	}
}
