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 #include <linux/lockd/lockd.h> 16 17 #include "internal.h" 18 #include "nfs4_fs.h" 19 #include "netns.h" 20 #include "sysfs.h" 21 22 static struct kset *nfs_kset; 23 24 static void nfs_kset_release(struct kobject *kobj) 25 { 26 struct kset *kset = container_of(kobj, struct kset, kobj); 27 kfree(kset); 28 } 29 30 static const struct kobj_ns_type_operations *nfs_netns_object_child_ns_type( 31 const struct kobject *kobj) 32 { 33 return &net_ns_type_operations; 34 } 35 36 static struct kobj_type nfs_kset_type = { 37 .release = nfs_kset_release, 38 .sysfs_ops = &kobj_sysfs_ops, 39 .child_ns_type = nfs_netns_object_child_ns_type, 40 }; 41 42 int nfs_sysfs_init(void) 43 { 44 int ret; 45 46 nfs_kset = kzalloc(sizeof(*nfs_kset), GFP_KERNEL); 47 if (!nfs_kset) 48 return -ENOMEM; 49 50 ret = kobject_set_name(&nfs_kset->kobj, "nfs"); 51 if (ret) { 52 kfree(nfs_kset); 53 return ret; 54 } 55 56 nfs_kset->kobj.parent = fs_kobj; 57 nfs_kset->kobj.ktype = &nfs_kset_type; 58 nfs_kset->kobj.kset = NULL; 59 60 ret = kset_register(nfs_kset); 61 if (ret) { 62 kfree(nfs_kset); 63 return ret; 64 } 65 66 return 0; 67 } 68 69 void nfs_sysfs_exit(void) 70 { 71 kset_unregister(nfs_kset); 72 } 73 74 static ssize_t nfs_netns_identifier_show(struct kobject *kobj, 75 struct kobj_attribute *attr, char *buf) 76 { 77 struct nfs_netns_client *c = container_of(kobj, 78 struct nfs_netns_client, 79 kobject); 80 ssize_t ret; 81 82 rcu_read_lock(); 83 ret = sysfs_emit(buf, "%s\n", rcu_dereference(c->identifier)); 84 rcu_read_unlock(); 85 return ret; 86 } 87 88 /* Strip trailing '\n' */ 89 static size_t nfs_string_strip(const char *c, size_t len) 90 { 91 while (len > 0 && c[len-1] == '\n') 92 --len; 93 return len; 94 } 95 96 static ssize_t nfs_netns_identifier_store(struct kobject *kobj, 97 struct kobj_attribute *attr, 98 const char *buf, size_t count) 99 { 100 struct nfs_netns_client *c = container_of(kobj, 101 struct nfs_netns_client, 102 kobject); 103 const char *old; 104 char *p; 105 size_t len; 106 107 len = nfs_string_strip(buf, min_t(size_t, count, CONTAINER_ID_MAXLEN)); 108 if (!len) 109 return 0; 110 p = kmemdup_nul(buf, len, GFP_KERNEL); 111 if (!p) 112 return -ENOMEM; 113 old = rcu_dereference_protected(xchg(&c->identifier, (char __rcu *)p), 1); 114 if (old) { 115 synchronize_rcu(); 116 kfree(old); 117 } 118 return count; 119 } 120 121 static void nfs_netns_client_release(struct kobject *kobj) 122 { 123 struct nfs_netns_client *c = container_of(kobj, 124 struct nfs_netns_client, 125 kobject); 126 127 kfree(rcu_dereference_raw(c->identifier)); 128 } 129 130 static const void *nfs_netns_client_namespace(const struct kobject *kobj) 131 { 132 return container_of(kobj, struct nfs_netns_client, kobject)->net; 133 } 134 135 static struct kobj_attribute nfs_netns_client_id = __ATTR(identifier, 136 0644, nfs_netns_identifier_show, nfs_netns_identifier_store); 137 138 static struct attribute *nfs_netns_client_attrs[] = { 139 &nfs_netns_client_id.attr, 140 NULL, 141 }; 142 ATTRIBUTE_GROUPS(nfs_netns_client); 143 144 static struct kobj_type nfs_netns_client_type = { 145 .release = nfs_netns_client_release, 146 .default_groups = nfs_netns_client_groups, 147 .sysfs_ops = &kobj_sysfs_ops, 148 .namespace = nfs_netns_client_namespace, 149 }; 150 151 static void nfs_netns_object_release(struct kobject *kobj) 152 { 153 struct nfs_netns_client *c = container_of(kobj, 154 struct nfs_netns_client, 155 nfs_net_kobj); 156 kfree(c); 157 } 158 159 static const void *nfs_netns_namespace(const struct kobject *kobj) 160 { 161 return container_of(kobj, struct nfs_netns_client, nfs_net_kobj)->net; 162 } 163 164 static struct kobj_type nfs_netns_object_type = { 165 .release = nfs_netns_object_release, 166 .sysfs_ops = &kobj_sysfs_ops, 167 .namespace = nfs_netns_namespace, 168 }; 169 170 static struct nfs_netns_client *nfs_netns_client_alloc(struct kobject *parent, 171 struct net *net) 172 { 173 struct nfs_netns_client *p; 174 175 p = kzalloc(sizeof(*p), GFP_KERNEL); 176 if (p) { 177 p->net = net; 178 p->kobject.kset = nfs_kset; 179 p->nfs_net_kobj.kset = nfs_kset; 180 181 if (kobject_init_and_add(&p->nfs_net_kobj, &nfs_netns_object_type, 182 parent, "net") != 0) { 183 kobject_put(&p->nfs_net_kobj); 184 return NULL; 185 } 186 187 if (kobject_init_and_add(&p->kobject, &nfs_netns_client_type, 188 &p->nfs_net_kobj, "nfs_client") == 0) 189 return p; 190 191 kobject_put(&p->kobject); 192 kobject_put(&p->nfs_net_kobj); 193 } 194 return NULL; 195 } 196 197 void nfs_netns_sysfs_setup(struct nfs_net *netns, struct net *net) 198 { 199 struct nfs_netns_client *clp; 200 201 clp = nfs_netns_client_alloc(&nfs_kset->kobj, net); 202 if (clp) { 203 netns->nfs_client = clp; 204 kobject_uevent(&clp->kobject, KOBJ_ADD); 205 } 206 } 207 208 void nfs_netns_sysfs_destroy(struct nfs_net *netns) 209 { 210 struct nfs_netns_client *clp = netns->nfs_client; 211 212 if (clp) { 213 kobject_uevent(&clp->kobject, KOBJ_REMOVE); 214 kobject_del(&clp->kobject); 215 kobject_put(&clp->kobject); 216 kobject_del(&clp->nfs_net_kobj); 217 kobject_put(&clp->nfs_net_kobj); 218 netns->nfs_client = NULL; 219 } 220 } 221 222 static bool shutdown_match_client(const struct rpc_task *task, const void *data) 223 { 224 return true; 225 } 226 227 static void shutdown_client(struct rpc_clnt *clnt) 228 { 229 clnt->cl_shutdown = 1; 230 rpc_cancel_tasks(clnt, -EIO, shutdown_match_client, NULL); 231 } 232 233 /* 234 * Shut down the nfs_client only once all the superblocks 235 * have been shut down. 236 */ 237 static void shutdown_nfs_client(struct nfs_client *clp) 238 { 239 struct nfs_server *server; 240 rcu_read_lock(); 241 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { 242 if (!(server->flags & NFS_MOUNT_SHUTDOWN)) { 243 rcu_read_unlock(); 244 return; 245 } 246 } 247 rcu_read_unlock(); 248 nfs_mark_client_ready(clp, -EIO); 249 shutdown_client(clp->cl_rpcclient); 250 } 251 252 static ssize_t 253 shutdown_show(struct kobject *kobj, struct kobj_attribute *attr, 254 char *buf) 255 { 256 struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); 257 bool shutdown = server->flags & NFS_MOUNT_SHUTDOWN; 258 return sysfs_emit(buf, "%d\n", shutdown); 259 } 260 261 static ssize_t 262 shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, 263 const char *buf, size_t count) 264 { 265 struct nfs_server *server; 266 int ret, val; 267 268 server = container_of(kobj, struct nfs_server, kobj); 269 270 ret = kstrtoint(buf, 0, &val); 271 if (ret) 272 return ret; 273 274 if (val != 1) 275 return -EINVAL; 276 277 /* already shut down? */ 278 if (server->flags & NFS_MOUNT_SHUTDOWN) 279 goto out; 280 281 server->flags |= NFS_MOUNT_SHUTDOWN; 282 shutdown_client(server->client); 283 284 if (!IS_ERR(server->client_acl)) 285 shutdown_client(server->client_acl); 286 287 if (server->nlm_host) 288 shutdown_client(server->nlm_host->h_rpcclnt); 289 out: 290 shutdown_nfs_client(server->nfs_client); 291 return count; 292 } 293 294 static struct kobj_attribute nfs_sysfs_attr_shutdown = __ATTR_RW(shutdown); 295 296 #if IS_ENABLED(CONFIG_NFS_V4_1) 297 static ssize_t 298 implid_domain_show(struct kobject *kobj, struct kobj_attribute *attr, 299 char *buf) 300 { 301 struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); 302 struct nfs41_impl_id *impl_id = server->nfs_client->cl_implid; 303 304 if (!impl_id || strlen(impl_id->domain) == 0) 305 return 0; //sysfs_emit(buf, ""); 306 return sysfs_emit(buf, "%s\n", impl_id->domain); 307 } 308 309 static struct kobj_attribute nfs_sysfs_attr_implid_domain = __ATTR_RO(implid_domain); 310 311 312 static ssize_t 313 implid_name_show(struct kobject *kobj, struct kobj_attribute *attr, 314 char *buf) 315 { 316 struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); 317 struct nfs41_impl_id *impl_id = server->nfs_client->cl_implid; 318 319 if (!impl_id || strlen(impl_id->name) == 0) 320 return 0; //sysfs_emit(buf, ""); 321 return sysfs_emit(buf, "%s\n", impl_id->name); 322 } 323 324 static struct kobj_attribute nfs_sysfs_attr_implid_name = __ATTR_RO(implid_name); 325 326 #endif /* IS_ENABLED(CONFIG_NFS_V4_1) */ 327 328 #define RPC_CLIENT_NAME_SIZE 64 329 330 void nfs_sysfs_link_rpc_client(struct nfs_server *server, 331 struct rpc_clnt *clnt, const char *uniq) 332 { 333 char name[RPC_CLIENT_NAME_SIZE]; 334 int ret; 335 336 strscpy(name, clnt->cl_program->name, sizeof(name)); 337 strncat(name, uniq ? uniq : "", sizeof(name) - strlen(name) - 1); 338 strncat(name, "_client", sizeof(name) - strlen(name) - 1); 339 340 ret = sysfs_create_link_nowarn(&server->kobj, 341 &clnt->cl_sysfs->kobject, name); 342 if (ret < 0) 343 pr_warn("NFS: can't create link to %s in sysfs (%d)\n", 344 name, ret); 345 } 346 EXPORT_SYMBOL_GPL(nfs_sysfs_link_rpc_client); 347 348 static void nfs_sysfs_sb_release(struct kobject *kobj) 349 { 350 /* no-op: why? see lib/kobject.c kobject_cleanup() */ 351 } 352 353 static const void *nfs_netns_server_namespace(const struct kobject *kobj) 354 { 355 return container_of(kobj, struct nfs_server, kobj)->nfs_client->cl_net; 356 } 357 358 static struct kobj_type nfs_sb_ktype = { 359 .release = nfs_sysfs_sb_release, 360 .sysfs_ops = &kobj_sysfs_ops, 361 .namespace = nfs_netns_server_namespace, 362 .child_ns_type = nfs_netns_object_child_ns_type, 363 }; 364 365 #if IS_ENABLED(CONFIG_NFS_V4_1) 366 static void nfs_sysfs_add_nfsv41_server(struct nfs_server *server) 367 { 368 int ret; 369 370 if (!server->nfs_client->cl_implid) 371 return; 372 373 ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_implid_domain.attr, 374 nfs_netns_server_namespace(&server->kobj)); 375 if (ret < 0) 376 pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", 377 server->s_sysfs_id, ret); 378 379 ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_implid_name.attr, 380 nfs_netns_server_namespace(&server->kobj)); 381 if (ret < 0) 382 pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", 383 server->s_sysfs_id, ret); 384 } 385 #else /* CONFIG_NFS_V4_1 */ 386 static inline void nfs_sysfs_add_nfsv41_server(struct nfs_server *server) 387 { 388 } 389 #endif /* CONFIG_NFS_V4_1 */ 390 391 #if IS_ENABLED(CONFIG_NFS_LOCALIO) 392 393 static ssize_t 394 localio_show(struct kobject *kobj, struct kobj_attribute *attr, 395 char *buf) 396 { 397 struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); 398 bool localio = nfs_server_is_local(server->nfs_client); 399 return sysfs_emit(buf, "%d\n", localio); 400 } 401 402 static struct kobj_attribute nfs_sysfs_attr_localio = __ATTR_RO(localio); 403 404 static void nfs_sysfs_add_nfs_localio_server(struct nfs_server *server) 405 { 406 int ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_localio.attr, 407 nfs_netns_server_namespace(&server->kobj)); 408 if (ret < 0) 409 pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", 410 server->s_sysfs_id, ret); 411 } 412 #else 413 static inline void nfs_sysfs_add_nfs_localio_server(struct nfs_server *server) 414 { 415 } 416 #endif /* IS_ENABLED(CONFIG_NFS_LOCALIO) */ 417 418 void nfs_sysfs_add_server(struct nfs_server *server) 419 { 420 int ret; 421 422 ret = kobject_init_and_add(&server->kobj, &nfs_sb_ktype, 423 &nfs_kset->kobj, "server-%d", server->s_sysfs_id); 424 if (ret < 0) { 425 pr_warn("NFS: nfs sysfs add server-%d failed (%d)\n", 426 server->s_sysfs_id, ret); 427 return; 428 } 429 ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_shutdown.attr, 430 nfs_netns_server_namespace(&server->kobj)); 431 if (ret < 0) 432 pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", 433 server->s_sysfs_id, ret); 434 435 nfs_sysfs_add_nfsv41_server(server); 436 nfs_sysfs_add_nfs_localio_server(server); 437 } 438 EXPORT_SYMBOL_GPL(nfs_sysfs_add_server); 439 440 void nfs_sysfs_move_server_to_sb(struct super_block *s) 441 { 442 struct nfs_server *server = s->s_fs_info; 443 int ret; 444 445 ret = kobject_rename(&server->kobj, s->s_id); 446 if (ret < 0) 447 pr_warn("NFS: rename sysfs %s failed (%d)\n", 448 server->kobj.name, ret); 449 } 450 451 void nfs_sysfs_move_sb_to_server(struct nfs_server *server) 452 { 453 const char *s; 454 int ret = -ENOMEM; 455 456 s = kasprintf(GFP_KERNEL, "server-%d", server->s_sysfs_id); 457 if (s) { 458 ret = kobject_rename(&server->kobj, s); 459 kfree(s); 460 } 461 if (ret < 0) 462 pr_warn("NFS: rename sysfs %s failed (%d)\n", 463 server->kobj.name, ret); 464 } 465 466 /* unlink, not dec-ref */ 467 void nfs_sysfs_remove_server(struct nfs_server *server) 468 { 469 kobject_del(&server->kobj); 470 } 471