0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <linux/kobject.h>
0008 #include <linux/sysfs.h>
0009 #include <linux/fs.h>
0010 #include <linux/slab.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/string.h>
0013 #include <linux/nfs_fs.h>
0014 #include <linux/rcupdate.h>
0015
0016 #include "nfs4_fs.h"
0017 #include "netns.h"
0018 #include "sysfs.h"
0019
0020 struct kobject *nfs_client_kobj;
0021 static struct kset *nfs_client_kset;
0022
0023 static void nfs_netns_object_release(struct kobject *kobj)
0024 {
0025 kfree(kobj);
0026 }
0027
0028 static const struct kobj_ns_type_operations *nfs_netns_object_child_ns_type(
0029 struct kobject *kobj)
0030 {
0031 return &net_ns_type_operations;
0032 }
0033
0034 static struct kobj_type nfs_netns_object_type = {
0035 .release = nfs_netns_object_release,
0036 .sysfs_ops = &kobj_sysfs_ops,
0037 .child_ns_type = nfs_netns_object_child_ns_type,
0038 };
0039
0040 static struct kobject *nfs_netns_object_alloc(const char *name,
0041 struct kset *kset, struct kobject *parent)
0042 {
0043 struct kobject *kobj;
0044
0045 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
0046 if (kobj) {
0047 kobj->kset = kset;
0048 if (kobject_init_and_add(kobj, &nfs_netns_object_type,
0049 parent, "%s", name) == 0)
0050 return kobj;
0051 kobject_put(kobj);
0052 }
0053 return NULL;
0054 }
0055
0056 int nfs_sysfs_init(void)
0057 {
0058 nfs_client_kset = kset_create_and_add("nfs", NULL, fs_kobj);
0059 if (!nfs_client_kset)
0060 return -ENOMEM;
0061 nfs_client_kobj = nfs_netns_object_alloc("net", nfs_client_kset, NULL);
0062 if (!nfs_client_kobj) {
0063 kset_unregister(nfs_client_kset);
0064 nfs_client_kset = NULL;
0065 return -ENOMEM;
0066 }
0067 return 0;
0068 }
0069
0070 void nfs_sysfs_exit(void)
0071 {
0072 kobject_put(nfs_client_kobj);
0073 kset_unregister(nfs_client_kset);
0074 }
0075
0076 static ssize_t nfs_netns_identifier_show(struct kobject *kobj,
0077 struct kobj_attribute *attr, char *buf)
0078 {
0079 struct nfs_netns_client *c = container_of(kobj,
0080 struct nfs_netns_client,
0081 kobject);
0082 ssize_t ret;
0083
0084 rcu_read_lock();
0085 ret = scnprintf(buf, PAGE_SIZE, "%s\n", rcu_dereference(c->identifier));
0086 rcu_read_unlock();
0087 return ret;
0088 }
0089
0090
0091 static size_t nfs_string_strip(const char *c, size_t len)
0092 {
0093 while (len > 0 && c[len-1] == '\n')
0094 --len;
0095 return len;
0096 }
0097
0098 static ssize_t nfs_netns_identifier_store(struct kobject *kobj,
0099 struct kobj_attribute *attr,
0100 const char *buf, size_t count)
0101 {
0102 struct nfs_netns_client *c = container_of(kobj,
0103 struct nfs_netns_client,
0104 kobject);
0105 const char *old;
0106 char *p;
0107 size_t len;
0108
0109 len = nfs_string_strip(buf, min_t(size_t, count, CONTAINER_ID_MAXLEN));
0110 if (!len)
0111 return 0;
0112 p = kmemdup_nul(buf, len, GFP_KERNEL);
0113 if (!p)
0114 return -ENOMEM;
0115 old = rcu_dereference_protected(xchg(&c->identifier, (char __rcu *)p), 1);
0116 if (old) {
0117 synchronize_rcu();
0118 kfree(old);
0119 }
0120 return count;
0121 }
0122
0123 static void nfs_netns_client_release(struct kobject *kobj)
0124 {
0125 struct nfs_netns_client *c = container_of(kobj,
0126 struct nfs_netns_client,
0127 kobject);
0128
0129 kfree(rcu_dereference_raw(c->identifier));
0130 kfree(c);
0131 }
0132
0133 static const void *nfs_netns_client_namespace(struct kobject *kobj)
0134 {
0135 return container_of(kobj, struct nfs_netns_client, kobject)->net;
0136 }
0137
0138 static struct kobj_attribute nfs_netns_client_id = __ATTR(identifier,
0139 0644, nfs_netns_identifier_show, nfs_netns_identifier_store);
0140
0141 static struct attribute *nfs_netns_client_attrs[] = {
0142 &nfs_netns_client_id.attr,
0143 NULL,
0144 };
0145 ATTRIBUTE_GROUPS(nfs_netns_client);
0146
0147 static struct kobj_type nfs_netns_client_type = {
0148 .release = nfs_netns_client_release,
0149 .default_groups = nfs_netns_client_groups,
0150 .sysfs_ops = &kobj_sysfs_ops,
0151 .namespace = nfs_netns_client_namespace,
0152 };
0153
0154 static struct nfs_netns_client *nfs_netns_client_alloc(struct kobject *parent,
0155 struct net *net)
0156 {
0157 struct nfs_netns_client *p;
0158
0159 p = kzalloc(sizeof(*p), GFP_KERNEL);
0160 if (p) {
0161 p->net = net;
0162 p->kobject.kset = nfs_client_kset;
0163 if (kobject_init_and_add(&p->kobject, &nfs_netns_client_type,
0164 parent, "nfs_client") == 0)
0165 return p;
0166 kobject_put(&p->kobject);
0167 }
0168 return NULL;
0169 }
0170
0171 void nfs_netns_sysfs_setup(struct nfs_net *netns, struct net *net)
0172 {
0173 struct nfs_netns_client *clp;
0174
0175 clp = nfs_netns_client_alloc(nfs_client_kobj, net);
0176 if (clp) {
0177 netns->nfs_client = clp;
0178 kobject_uevent(&clp->kobject, KOBJ_ADD);
0179 }
0180 }
0181
0182 void nfs_netns_sysfs_destroy(struct nfs_net *netns)
0183 {
0184 struct nfs_netns_client *clp = netns->nfs_client;
0185
0186 if (clp) {
0187 kobject_uevent(&clp->kobject, KOBJ_REMOVE);
0188 kobject_del(&clp->kobject);
0189 kobject_put(&clp->kobject);
0190 netns->nfs_client = NULL;
0191 }
0192 }