diff options
author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-06-28 11:10:39 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-07-06 14:54:52 -0400 |
commit | 28ade856c0f724b1d74d7d683ec2dc0e98de60ae (patch) | |
tree | 3e11f9bfaf379cd3320d643acbff6491aaaaa9f4 | |
parent | 02a2779f223e9f77c114b0c64ca246b01c1dc563 (diff) | |
parent | bf11fbdb20b385157b046ea7781f04d0c62554a3 (diff) |
Merge branch 'containers'
-rw-r--r-- | fs/nfs/Makefile | 3 | ||||
-rw-r--r-- | fs/nfs/client.c | 17 | ||||
-rw-r--r-- | fs/nfs/inode.c | 14 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/netns.h | 3 | ||||
-rw-r--r-- | fs/nfs/sysfs.c | 187 | ||||
-rw-r--r-- | fs/nfs/sysfs.h | 25 |
7 files changed, 242 insertions, 9 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index c587e3c4c6a6..34cdeaecccf6 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -8,7 +8,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o | |||
8 | CFLAGS_nfstrace.o += -I$(src) | 8 | CFLAGS_nfstrace.o += -I$(src) |
9 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ | 9 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ |
10 | io.o direct.o pagelist.o read.o symlink.o unlink.o \ | 10 | io.o direct.o pagelist.o read.o symlink.o unlink.o \ |
11 | write.o namespace.o mount_clnt.o nfstrace.o export.o | 11 | write.o namespace.o mount_clnt.o nfstrace.o \ |
12 | export.o sysfs.o | ||
12 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | 13 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o |
13 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 14 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
14 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 15 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index d7e4f0848e28..6e7aeb543f6a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "pnfs.h" | 49 | #include "pnfs.h" |
50 | #include "nfs.h" | 50 | #include "nfs.h" |
51 | #include "netns.h" | 51 | #include "netns.h" |
52 | #include "sysfs.h" | ||
52 | 53 | ||
53 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 54 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
54 | 55 | ||
@@ -192,7 +193,7 @@ error_0: | |||
192 | EXPORT_SYMBOL_GPL(nfs_alloc_client); | 193 | EXPORT_SYMBOL_GPL(nfs_alloc_client); |
193 | 194 | ||
194 | #if IS_ENABLED(CONFIG_NFS_V4) | 195 | #if IS_ENABLED(CONFIG_NFS_V4) |
195 | void nfs_cleanup_cb_ident_idr(struct net *net) | 196 | static void nfs_cleanup_cb_ident_idr(struct net *net) |
196 | { | 197 | { |
197 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 198 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
198 | 199 | ||
@@ -214,7 +215,7 @@ static void pnfs_init_server(struct nfs_server *server) | |||
214 | } | 215 | } |
215 | 216 | ||
216 | #else | 217 | #else |
217 | void nfs_cleanup_cb_ident_idr(struct net *net) | 218 | static void nfs_cleanup_cb_ident_idr(struct net *net) |
218 | { | 219 | { |
219 | } | 220 | } |
220 | 221 | ||
@@ -1072,6 +1073,18 @@ void nfs_clients_init(struct net *net) | |||
1072 | #endif | 1073 | #endif |
1073 | spin_lock_init(&nn->nfs_client_lock); | 1074 | spin_lock_init(&nn->nfs_client_lock); |
1074 | nn->boot_time = ktime_get_real(); | 1075 | nn->boot_time = ktime_get_real(); |
1076 | |||
1077 | nfs_netns_sysfs_setup(nn, net); | ||
1078 | } | ||
1079 | |||
1080 | void nfs_clients_exit(struct net *net) | ||
1081 | { | ||
1082 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
1083 | |||
1084 | nfs_netns_sysfs_destroy(nn); | ||
1085 | nfs_cleanup_cb_ident_idr(net); | ||
1086 | WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); | ||
1087 | WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); | ||
1075 | } | 1088 | } |
1076 | 1089 | ||
1077 | #ifdef CONFIG_PROC_FS | 1090 | #ifdef CONFIG_PROC_FS |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index ea52c71534b5..8a1758200b57 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "pnfs.h" | 51 | #include "pnfs.h" |
52 | #include "nfs.h" | 52 | #include "nfs.h" |
53 | #include "netns.h" | 53 | #include "netns.h" |
54 | #include "sysfs.h" | ||
54 | 55 | ||
55 | #include "nfstrace.h" | 56 | #include "nfstrace.h" |
56 | 57 | ||
@@ -2167,12 +2168,8 @@ static int nfs_net_init(struct net *net) | |||
2167 | 2168 | ||
2168 | static void nfs_net_exit(struct net *net) | 2169 | static void nfs_net_exit(struct net *net) |
2169 | { | 2170 | { |
2170 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
2171 | |||
2172 | nfs_fs_proc_net_exit(net); | 2171 | nfs_fs_proc_net_exit(net); |
2173 | nfs_cleanup_cb_ident_idr(net); | 2172 | nfs_clients_exit(net); |
2174 | WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); | ||
2175 | WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); | ||
2176 | } | 2173 | } |
2177 | 2174 | ||
2178 | static struct pernet_operations nfs_net_ops = { | 2175 | static struct pernet_operations nfs_net_ops = { |
@@ -2189,6 +2186,10 @@ static int __init init_nfs_fs(void) | |||
2189 | { | 2186 | { |
2190 | int err; | 2187 | int err; |
2191 | 2188 | ||
2189 | err = nfs_sysfs_init(); | ||
2190 | if (err < 0) | ||
2191 | goto out10; | ||
2192 | |||
2192 | err = register_pernet_subsys(&nfs_net_ops); | 2193 | err = register_pernet_subsys(&nfs_net_ops); |
2193 | if (err < 0) | 2194 | if (err < 0) |
2194 | goto out9; | 2195 | goto out9; |
@@ -2252,6 +2253,8 @@ out7: | |||
2252 | out8: | 2253 | out8: |
2253 | unregister_pernet_subsys(&nfs_net_ops); | 2254 | unregister_pernet_subsys(&nfs_net_ops); |
2254 | out9: | 2255 | out9: |
2256 | nfs_sysfs_exit(); | ||
2257 | out10: | ||
2255 | return err; | 2258 | return err; |
2256 | } | 2259 | } |
2257 | 2260 | ||
@@ -2268,6 +2271,7 @@ static void __exit exit_nfs_fs(void) | |||
2268 | unregister_nfs_fs(); | 2271 | unregister_nfs_fs(); |
2269 | nfs_fs_proc_exit(); | 2272 | nfs_fs_proc_exit(); |
2270 | nfsiod_stop(); | 2273 | nfsiod_stop(); |
2274 | nfs_sysfs_exit(); | ||
2271 | } | 2275 | } |
2272 | 2276 | ||
2273 | /* Not quite true; I just maintain it */ | 2277 | /* Not quite true; I just maintain it */ |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 498fab72f70b..9e87265907b8 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -158,6 +158,7 @@ extern void nfs_umount(const struct nfs_mount_request *info); | |||
158 | /* client.c */ | 158 | /* client.c */ |
159 | extern const struct rpc_program nfs_program; | 159 | extern const struct rpc_program nfs_program; |
160 | extern void nfs_clients_init(struct net *net); | 160 | extern void nfs_clients_init(struct net *net); |
161 | extern void nfs_clients_exit(struct net *net); | ||
161 | extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *); | 162 | extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *); |
162 | int nfs_create_rpc_client(struct nfs_client *, const struct nfs_client_initdata *, rpc_authflavor_t); | 163 | int nfs_create_rpc_client(struct nfs_client *, const struct nfs_client_initdata *, rpc_authflavor_t); |
163 | struct nfs_client *nfs_get_client(const struct nfs_client_initdata *); | 164 | struct nfs_client *nfs_get_client(const struct nfs_client_initdata *); |
@@ -170,7 +171,6 @@ int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t, | |||
170 | struct nfs_server *nfs_alloc_server(void); | 171 | struct nfs_server *nfs_alloc_server(void); |
171 | void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *); | 172 | void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *); |
172 | 173 | ||
173 | extern void nfs_cleanup_cb_ident_idr(struct net *); | ||
174 | extern void nfs_put_client(struct nfs_client *); | 174 | extern void nfs_put_client(struct nfs_client *); |
175 | extern void nfs_free_client(struct nfs_client *); | 175 | extern void nfs_free_client(struct nfs_client *); |
176 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); | 176 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); |
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index fc9978c58265..c8374f74dce1 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h | |||
@@ -15,6 +15,8 @@ struct bl_dev_msg { | |||
15 | uint32_t major, minor; | 15 | uint32_t major, minor; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | struct nfs_netns_client; | ||
19 | |||
18 | struct nfs_net { | 20 | struct nfs_net { |
19 | struct cache_detail *nfs_dns_resolve; | 21 | struct cache_detail *nfs_dns_resolve; |
20 | struct rpc_pipe *bl_device_pipe; | 22 | struct rpc_pipe *bl_device_pipe; |
@@ -29,6 +31,7 @@ struct nfs_net { | |||
29 | unsigned short nfs_callback_tcpport6; | 31 | unsigned short nfs_callback_tcpport6; |
30 | int cb_users[NFS4_MAX_MINOR_VERSION + 1]; | 32 | int cb_users[NFS4_MAX_MINOR_VERSION + 1]; |
31 | #endif | 33 | #endif |
34 | struct nfs_netns_client *nfs_client; | ||
32 | spinlock_t nfs_client_lock; | 35 | spinlock_t nfs_client_lock; |
33 | ktime_t boot_time; | 36 | ktime_t boot_time; |
34 | #ifdef CONFIG_PROC_FS | 37 | #ifdef CONFIG_PROC_FS |
diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c new file mode 100644 index 000000000000..4f3390b20239 --- /dev/null +++ b/fs/nfs/sysfs.c | |||
@@ -0,0 +1,187 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (c) 2019 Hammerspace Inc | ||
4 | */ | ||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/kobject.h> | ||
8 | #include <linux/sysfs.h> | ||
9 | #include <linux/fs.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/nfs_fs.h> | ||
14 | #include <linux/rcupdate.h> | ||
15 | |||
16 | #include "nfs4_fs.h" | ||
17 | #include "netns.h" | ||
18 | #include "sysfs.h" | ||
19 | |||
20 | struct kobject *nfs_client_kobj; | ||
21 | static struct kset *nfs_client_kset; | ||
22 | |||
23 | static void nfs_netns_object_release(struct kobject *kobj) | ||
24 | { | ||
25 | kfree(kobj); | ||
26 | } | ||
27 | |||
28 | static const struct kobj_ns_type_operations *nfs_netns_object_child_ns_type( | ||
29 | struct kobject *kobj) | ||
30 | { | ||
31 | return &net_ns_type_operations; | ||
32 | } | ||
33 | |||
34 | static struct kobj_type nfs_netns_object_type = { | ||
35 | .release = nfs_netns_object_release, | ||
36 | .sysfs_ops = &kobj_sysfs_ops, | ||
37 | .child_ns_type = nfs_netns_object_child_ns_type, | ||
38 | }; | ||
39 | |||
40 | static struct kobject *nfs_netns_object_alloc(const char *name, | ||
41 | struct kset *kset, struct kobject *parent) | ||
42 | { | ||
43 | struct kobject *kobj; | ||
44 | |||
45 | kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); | ||
46 | if (kobj) { | ||
47 | kobj->kset = kset; | ||
48 | if (kobject_init_and_add(kobj, &nfs_netns_object_type, | ||
49 | parent, "%s", name) == 0) | ||
50 | return kobj; | ||
51 | kobject_put(kobj); | ||
52 | } | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | int nfs_sysfs_init(void) | ||
57 | { | ||
58 | nfs_client_kset = kset_create_and_add("nfs", NULL, fs_kobj); | ||
59 | if (!nfs_client_kset) | ||
60 | return -ENOMEM; | ||
61 | nfs_client_kobj = nfs_netns_object_alloc("net", nfs_client_kset, NULL); | ||
62 | if (!nfs_client_kobj) { | ||
63 | kset_unregister(nfs_client_kset); | ||
64 | nfs_client_kset = NULL; | ||
65 | return -ENOMEM; | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | void nfs_sysfs_exit(void) | ||
71 | { | ||
72 | kobject_put(nfs_client_kobj); | ||
73 | kset_unregister(nfs_client_kset); | ||
74 | } | ||
75 | |||
76 | static ssize_t nfs_netns_identifier_show(struct kobject *kobj, | ||
77 | struct kobj_attribute *attr, char *buf) | ||
78 | { | ||
79 | struct nfs_netns_client *c = container_of(kobj, | ||
80 | struct nfs_netns_client, | ||
81 | kobject); | ||
82 | return scnprintf(buf, PAGE_SIZE, "%s\n", c->identifier); | ||
83 | } | ||
84 | |||
85 | /* Strip trailing '\n' */ | ||
86 | static size_t nfs_string_strip(const char *c, size_t len) | ||
87 | { | ||
88 | while (len > 0 && c[len-1] == '\n') | ||
89 | --len; | ||
90 | return len; | ||
91 | } | ||
92 | |||
93 | static ssize_t nfs_netns_identifier_store(struct kobject *kobj, | ||
94 | struct kobj_attribute *attr, | ||
95 | const char *buf, size_t count) | ||
96 | { | ||
97 | struct nfs_netns_client *c = container_of(kobj, | ||
98 | struct nfs_netns_client, | ||
99 | kobject); | ||
100 | const char *old; | ||
101 | char *p; | ||
102 | size_t len; | ||
103 | |||
104 | len = nfs_string_strip(buf, min_t(size_t, count, CONTAINER_ID_MAXLEN)); | ||
105 | if (!len) | ||
106 | return 0; | ||
107 | p = kmemdup_nul(buf, len, GFP_KERNEL); | ||
108 | if (!p) | ||
109 | return -ENOMEM; | ||
110 | old = xchg(&c->identifier, p); | ||
111 | if (old) { | ||
112 | synchronize_rcu(); | ||
113 | kfree(old); | ||
114 | } | ||
115 | return count; | ||
116 | } | ||
117 | |||
118 | static void nfs_netns_client_release(struct kobject *kobj) | ||
119 | { | ||
120 | struct nfs_netns_client *c = container_of(kobj, | ||
121 | struct nfs_netns_client, | ||
122 | kobject); | ||
123 | |||
124 | if (c->identifier) | ||
125 | kfree(c->identifier); | ||
126 | kfree(c); | ||
127 | } | ||
128 | |||
129 | static const void *nfs_netns_client_namespace(struct kobject *kobj) | ||
130 | { | ||
131 | return container_of(kobj, struct nfs_netns_client, kobject)->net; | ||
132 | } | ||
133 | |||
134 | static struct kobj_attribute nfs_netns_client_id = __ATTR(identifier, | ||
135 | 0644, nfs_netns_identifier_show, nfs_netns_identifier_store); | ||
136 | |||
137 | static struct attribute *nfs_netns_client_attrs[] = { | ||
138 | &nfs_netns_client_id.attr, | ||
139 | NULL, | ||
140 | }; | ||
141 | |||
142 | static struct kobj_type nfs_netns_client_type = { | ||
143 | .release = nfs_netns_client_release, | ||
144 | .default_attrs = nfs_netns_client_attrs, | ||
145 | .sysfs_ops = &kobj_sysfs_ops, | ||
146 | .namespace = nfs_netns_client_namespace, | ||
147 | }; | ||
148 | |||
149 | static struct nfs_netns_client *nfs_netns_client_alloc(struct kobject *parent, | ||
150 | struct net *net) | ||
151 | { | ||
152 | struct nfs_netns_client *p; | ||
153 | |||
154 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
155 | if (p) { | ||
156 | p->net = net; | ||
157 | p->kobject.kset = nfs_client_kset; | ||
158 | if (kobject_init_and_add(&p->kobject, &nfs_netns_client_type, | ||
159 | parent, "nfs_client") == 0) | ||
160 | return p; | ||
161 | kobject_put(&p->kobject); | ||
162 | } | ||
163 | return NULL; | ||
164 | } | ||
165 | |||
166 | void nfs_netns_sysfs_setup(struct nfs_net *netns, struct net *net) | ||
167 | { | ||
168 | struct nfs_netns_client *clp; | ||
169 | |||
170 | clp = nfs_netns_client_alloc(nfs_client_kobj, net); | ||
171 | if (clp) { | ||
172 | netns->nfs_client = clp; | ||
173 | kobject_uevent(&clp->kobject, KOBJ_ADD); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | void nfs_netns_sysfs_destroy(struct nfs_net *netns) | ||
178 | { | ||
179 | struct nfs_netns_client *clp = netns->nfs_client; | ||
180 | |||
181 | if (clp) { | ||
182 | kobject_uevent(&clp->kobject, KOBJ_REMOVE); | ||
183 | kobject_del(&clp->kobject); | ||
184 | kobject_put(&clp->kobject); | ||
185 | netns->nfs_client = NULL; | ||
186 | } | ||
187 | } | ||
diff --git a/fs/nfs/sysfs.h b/fs/nfs/sysfs.h new file mode 100644 index 000000000000..f1b27411dcc0 --- /dev/null +++ b/fs/nfs/sysfs.h | |||
@@ -0,0 +1,25 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (c) 2019 Hammerspace Inc | ||
4 | */ | ||
5 | |||
6 | #ifndef __NFS_SYSFS_H | ||
7 | #define __NFS_SYSFS_H | ||
8 | |||
9 | #define CONTAINER_ID_MAXLEN (64) | ||
10 | |||
11 | struct nfs_netns_client { | ||
12 | struct kobject kobject; | ||
13 | struct net *net; | ||
14 | const char *identifier; | ||
15 | }; | ||
16 | |||
17 | extern struct kobject *nfs_client_kobj; | ||
18 | |||
19 | extern int nfs_sysfs_init(void); | ||
20 | extern void nfs_sysfs_exit(void); | ||
21 | |||
22 | void nfs_netns_sysfs_setup(struct nfs_net *netns, struct net *net); | ||
23 | void nfs_netns_sysfs_destroy(struct nfs_net *netns); | ||
24 | |||
25 | #endif | ||