1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com> 4 */ 5 #include <linux/sunrpc/clnt.h> 6 #include <linux/kobject.h> 7 #include <linux/sunrpc/addr.h> 8 #include <linux/sunrpc/xprtsock.h> 9 #include <net/net_namespace.h> 10 11 #include "sysfs.h" 12 13 struct xprt_addr { 14 const char *addr; 15 struct rcu_head rcu; 16 }; 17 18 static void free_xprt_addr(struct rcu_head *head) 19 { 20 struct xprt_addr *addr = container_of(head, struct xprt_addr, rcu); 21 22 kfree(addr->addr); 23 kfree(addr); 24 } 25 26 static struct kset *rpc_sunrpc_kset; 27 static struct kobject *rpc_sunrpc_client_kobj, *rpc_sunrpc_xprt_switch_kobj; 28 29 static void rpc_sysfs_object_release(struct kobject *kobj) 30 { 31 kfree(kobj); 32 } 33 34 static const struct kobj_ns_type_operations * 35 rpc_sysfs_object_child_ns_type(const struct kobject *kobj) 36 { 37 return &net_ns_type_operations; 38 } 39 40 static const struct kobj_type rpc_sysfs_object_type = { 41 .release = rpc_sysfs_object_release, 42 .sysfs_ops = &kobj_sysfs_ops, 43 .child_ns_type = rpc_sysfs_object_child_ns_type, 44 }; 45 46 static struct kobject *rpc_sysfs_object_alloc(const char *name, 47 struct kset *kset, 48 struct kobject *parent) 49 { 50 struct kobject *kobj; 51 52 kobj = kzalloc_obj(*kobj); 53 if (kobj) { 54 kobj->kset = kset; 55 if (kobject_init_and_add(kobj, &rpc_sysfs_object_type, 56 parent, "%s", name) == 0) 57 return kobj; 58 kobject_put(kobj); 59 } 60 return NULL; 61 } 62 63 static inline struct rpc_clnt * 64 rpc_sysfs_client_kobj_get_clnt(struct kobject *kobj) 65 { 66 struct rpc_sysfs_client *c = container_of(kobj, 67 struct rpc_sysfs_client, kobject); 68 struct rpc_clnt *ret = c->clnt; 69 70 return refcount_inc_not_zero(&ret->cl_count) ? ret : NULL; 71 } 72 73 static inline struct rpc_xprt * 74 rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj) 75 { 76 struct rpc_sysfs_xprt *x = container_of(kobj, 77 struct rpc_sysfs_xprt, kobject); 78 79 return xprt_get(x->xprt); 80 } 81 82 static inline struct rpc_xprt_switch * 83 rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject *kobj) 84 { 85 struct rpc_sysfs_xprt *x = container_of(kobj, 86 struct rpc_sysfs_xprt, kobject); 87 88 return xprt_switch_get(x->xprt_switch); 89 } 90 91 static inline struct rpc_xprt_switch * 92 rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj) 93 { 94 struct rpc_sysfs_xprt_switch *x = container_of(kobj, 95 struct rpc_sysfs_xprt_switch, kobject); 96 97 return xprt_switch_get(x->xprt_switch); 98 } 99 100 static ssize_t rpc_sysfs_clnt_version_show(struct kobject *kobj, 101 struct kobj_attribute *attr, 102 char *buf) 103 { 104 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); 105 ssize_t ret; 106 107 if (!clnt) 108 return sprintf(buf, "<closed>\n"); 109 110 ret = sprintf(buf, "%u", clnt->cl_vers); 111 refcount_dec(&clnt->cl_count); 112 return ret; 113 } 114 115 static ssize_t rpc_sysfs_clnt_program_show(struct kobject *kobj, 116 struct kobj_attribute *attr, 117 char *buf) 118 { 119 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); 120 ssize_t ret; 121 122 if (!clnt) 123 return sprintf(buf, "<closed>\n"); 124 125 ret = sprintf(buf, "%s", clnt->cl_program->name); 126 refcount_dec(&clnt->cl_count); 127 return ret; 128 } 129 130 static ssize_t rpc_sysfs_clnt_max_connect_show(struct kobject *kobj, 131 struct kobj_attribute *attr, 132 char *buf) 133 { 134 struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); 135 ssize_t ret; 136 137 if (!clnt) 138 return sprintf(buf, "<closed>\n"); 139 140 ret = sprintf(buf, "%u\n", clnt->cl_max_connect); 141 refcount_dec(&clnt->cl_count); 142 return ret; 143 } 144 145 static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj, 146 struct kobj_attribute *attr, 147 char *buf) 148 { 149 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 150 ssize_t ret; 151 152 if (!xprt) { 153 ret = sprintf(buf, "<closed>\n"); 154 goto out; 155 } 156 ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]); 157 xprt_put(xprt); 158 out: 159 return ret; 160 } 161 162 static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj, 163 struct kobj_attribute *attr, 164 char *buf) 165 { 166 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 167 size_t buflen = PAGE_SIZE; 168 ssize_t ret; 169 170 if (!xprt || !xprt_connected(xprt)) { 171 ret = sprintf(buf, "<closed>\n"); 172 } else if (xprt->ops->get_srcaddr) { 173 ret = xprt->ops->get_srcaddr(xprt, buf, buflen); 174 if (ret > 0) { 175 if (ret < buflen - 1) { 176 buf[ret] = '\n'; 177 ret++; 178 buf[ret] = '\0'; 179 } 180 } else 181 ret = sprintf(buf, "<closed>\n"); 182 } else 183 ret = sprintf(buf, "<not a socket>\n"); 184 xprt_put(xprt); 185 return ret; 186 } 187 188 static const char *xprtsec_strings[] = { 189 [RPC_XPRTSEC_NONE] = "none", 190 [RPC_XPRTSEC_TLS_ANON] = "tls-anon", 191 [RPC_XPRTSEC_TLS_X509] = "tls-x509", 192 }; 193 194 static ssize_t rpc_sysfs_xprt_xprtsec_show(struct kobject *kobj, 195 struct kobj_attribute *attr, 196 char *buf) 197 { 198 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 199 ssize_t ret; 200 201 if (!xprt) { 202 ret = sprintf(buf, "<closed>\n"); 203 goto out; 204 } 205 206 ret = sprintf(buf, "%s\n", xprtsec_strings[xprt->xprtsec.policy]); 207 xprt_put(xprt); 208 out: 209 return ret; 210 211 } 212 213 static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj, 214 struct kobj_attribute *attr, char *buf) 215 { 216 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 217 unsigned short srcport = 0; 218 size_t buflen = PAGE_SIZE; 219 ssize_t ret; 220 221 if (!xprt || !xprt_connected(xprt)) { 222 ret = sprintf(buf, "<closed>\n"); 223 goto out; 224 } 225 226 if (xprt->ops->get_srcport) 227 srcport = xprt->ops->get_srcport(xprt); 228 229 ret = snprintf(buf, buflen, 230 "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n" 231 "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n" 232 "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n" 233 "backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n" 234 "tasks_queuelen=%ld\ndst_port=%s\n", 235 xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs, 236 xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen, 237 xprt->sending.qlen, xprt->pending.qlen, 238 xprt->backlog.qlen, xprt->main, srcport, 239 atomic_long_read(&xprt->queuelen), 240 xprt->address_strings[RPC_DISPLAY_PORT]); 241 out: 242 xprt_put(xprt); 243 return ret; 244 } 245 246 static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, 247 struct kobj_attribute *attr, 248 char *buf) 249 { 250 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 251 ssize_t ret; 252 int locked, connected, connecting, close_wait, bound, binding, 253 closing, congested, cwnd_wait, write_space, offline, remove; 254 255 if (!(xprt && xprt->state)) { 256 ret = sprintf(buf, "state=CLOSED\n"); 257 } else { 258 locked = test_bit(XPRT_LOCKED, &xprt->state); 259 connected = test_bit(XPRT_CONNECTED, &xprt->state); 260 connecting = test_bit(XPRT_CONNECTING, &xprt->state); 261 close_wait = test_bit(XPRT_CLOSE_WAIT, &xprt->state); 262 bound = test_bit(XPRT_BOUND, &xprt->state); 263 binding = test_bit(XPRT_BINDING, &xprt->state); 264 closing = test_bit(XPRT_CLOSING, &xprt->state); 265 congested = test_bit(XPRT_CONGESTED, &xprt->state); 266 cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state); 267 write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state); 268 offline = test_bit(XPRT_OFFLINE, &xprt->state); 269 remove = test_bit(XPRT_REMOVE, &xprt->state); 270 271 ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s %s %s\n", 272 locked ? "LOCKED" : "", 273 connected ? "CONNECTED" : "", 274 connecting ? "CONNECTING" : "", 275 close_wait ? "CLOSE_WAIT" : "", 276 bound ? "BOUND" : "", 277 binding ? "BOUNDING" : "", 278 closing ? "CLOSING" : "", 279 congested ? "CONGESTED" : "", 280 cwnd_wait ? "CWND_WAIT" : "", 281 write_space ? "WRITE_SPACE" : "", 282 offline ? "OFFLINE" : "", 283 remove ? "REMOVE" : ""); 284 } 285 286 xprt_put(xprt); 287 return ret; 288 } 289 290 static ssize_t rpc_sysfs_xprt_del_xprt_show(struct kobject *kobj, 291 struct kobj_attribute *attr, 292 char *buf) 293 { 294 return sprintf(buf, "# delete this xprt\n"); 295 } 296 297 298 static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj, 299 struct kobj_attribute *attr, 300 char *buf) 301 { 302 struct rpc_xprt_switch *xprt_switch = 303 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj); 304 ssize_t ret; 305 306 if (!xprt_switch) 307 return 0; 308 ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\n" 309 "num_unique_destaddr=%u\nqueue_len=%ld\n", 310 xprt_switch->xps_nxprts, xprt_switch->xps_nactive, 311 xprt_switch->xps_nunique_destaddr_xprts, 312 atomic_long_read(&xprt_switch->xps_queuelen)); 313 xprt_switch_put(xprt_switch); 314 return ret; 315 } 316 317 static ssize_t rpc_sysfs_xprt_switch_add_xprt_show(struct kobject *kobj, 318 struct kobj_attribute *attr, 319 char *buf) 320 { 321 return sprintf(buf, "# add one xprt to this xprt_switch\n"); 322 } 323 324 static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj, 325 struct kobj_attribute *attr, 326 const char *buf, size_t count) 327 { 328 struct rpc_xprt_switch *xprt_switch = 329 rpc_sysfs_xprt_switch_kobj_get_xprt(kobj); 330 struct xprt_create xprt_create_args; 331 struct rpc_xprt *xprt, *new; 332 333 if (!xprt_switch) 334 return 0; 335 336 xprt = rpc_xprt_switch_get_main_xprt(xprt_switch); 337 if (!xprt) 338 goto out; 339 340 xprt_create_args.ident = xprt->xprt_class->ident; 341 xprt_create_args.net = xprt->xprt_net; 342 xprt_create_args.dstaddr = (struct sockaddr *)&xprt->addr; 343 xprt_create_args.addrlen = xprt->addrlen; 344 xprt_create_args.servername = xprt->servername; 345 xprt_create_args.bc_xprt = xprt->bc_xprt; 346 xprt_create_args.xprtsec = xprt->xprtsec; 347 xprt_create_args.connect_timeout = xprt->connect_timeout; 348 xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout; 349 350 new = xprt_create_transport(&xprt_create_args); 351 if (IS_ERR_OR_NULL(new)) { 352 count = PTR_ERR(new); 353 goto out_put_xprt; 354 } 355 356 rpc_xprt_switch_add_xprt(xprt_switch, new); 357 xprt_put(new); 358 359 out_put_xprt: 360 xprt_put(xprt); 361 out: 362 xprt_switch_put(xprt_switch); 363 return count; 364 } 365 366 static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj, 367 struct kobj_attribute *attr, 368 const char *buf, size_t count) 369 { 370 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 371 struct sockaddr *saddr; 372 char *dst_addr; 373 int port; 374 struct xprt_addr *saved_addr; 375 size_t buf_len; 376 377 if (!xprt) 378 return 0; 379 if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP || 380 xprt->xprt_class->ident == XPRT_TRANSPORT_TCP_TLS || 381 xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) { 382 xprt_put(xprt); 383 return -EOPNOTSUPP; 384 } 385 386 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { 387 count = -EINTR; 388 goto out_put; 389 } 390 saddr = (struct sockaddr *)&xprt->addr; 391 port = rpc_get_port(saddr); 392 393 /* buf_len is the len until the first occurrence of either 394 * '\n' or '\0' 395 */ 396 buf_len = strcspn(buf, "\n"); 397 398 dst_addr = kstrndup(buf, buf_len, GFP_KERNEL); 399 if (!dst_addr) 400 goto out_err; 401 saved_addr = kzalloc_obj(*saved_addr); 402 if (!saved_addr) 403 goto out_err_free; 404 saved_addr->addr = 405 rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]); 406 rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr); 407 call_rcu(&saved_addr->rcu, free_xprt_addr); 408 xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr, 409 sizeof(*saddr)); 410 rpc_set_port(saddr, port); 411 412 xprt_force_disconnect(xprt); 413 out: 414 xprt_release_write(xprt, NULL); 415 out_put: 416 xprt_put(xprt); 417 return count; 418 out_err_free: 419 kfree(dst_addr); 420 out_err: 421 count = -ENOMEM; 422 goto out; 423 } 424 425 static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj, 426 struct kobj_attribute *attr, 427 const char *buf, size_t count) 428 { 429 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 430 int offline = 0, online = 0, remove = 0; 431 struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj); 432 433 if (!xprt || !xps) { 434 count = 0; 435 goto out_put; 436 } 437 438 if (!strncmp(buf, "offline", 7)) 439 offline = 1; 440 else if (!strncmp(buf, "online", 6)) 441 online = 1; 442 else if (!strncmp(buf, "remove", 6)) 443 remove = 1; 444 else { 445 count = -EINVAL; 446 goto out_put; 447 } 448 449 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { 450 count = -EINTR; 451 goto out_put; 452 } 453 if (xprt->main) { 454 count = -EINVAL; 455 goto release_tasks; 456 } 457 if (offline) { 458 xprt_set_offline_locked(xprt, xps); 459 } else if (online) { 460 xprt_set_online_locked(xprt, xps); 461 } else if (remove) { 462 if (test_bit(XPRT_OFFLINE, &xprt->state)) 463 xprt_delete_locked(xprt, xps); 464 else 465 count = -EINVAL; 466 } 467 468 release_tasks: 469 xprt_release_write(xprt, NULL); 470 out_put: 471 xprt_put(xprt); 472 xprt_switch_put(xps); 473 return count; 474 } 475 476 static ssize_t rpc_sysfs_xprt_del_xprt(struct kobject *kobj, 477 struct kobj_attribute *attr, 478 const char *buf, size_t count) 479 { 480 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 481 struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj); 482 483 if (!xprt || !xps) { 484 count = 0; 485 goto out; 486 } 487 488 if (xprt->main) { 489 count = -EINVAL; 490 goto release_tasks; 491 } 492 493 if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { 494 count = -EINTR; 495 goto out_put; 496 } 497 498 xprt_set_offline_locked(xprt, xps); 499 xprt_delete_locked(xprt, xps); 500 501 release_tasks: 502 xprt_release_write(xprt, NULL); 503 out_put: 504 xprt_put(xprt); 505 xprt_switch_put(xps); 506 out: 507 return count; 508 } 509 510 int rpc_sysfs_init(void) 511 { 512 rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj); 513 if (!rpc_sunrpc_kset) 514 return -ENOMEM; 515 rpc_sunrpc_client_kobj = 516 rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL); 517 if (!rpc_sunrpc_client_kobj) 518 goto err_client; 519 rpc_sunrpc_xprt_switch_kobj = 520 rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL); 521 if (!rpc_sunrpc_xprt_switch_kobj) 522 goto err_switch; 523 return 0; 524 err_switch: 525 kobject_put(rpc_sunrpc_client_kobj); 526 rpc_sunrpc_client_kobj = NULL; 527 err_client: 528 kset_unregister(rpc_sunrpc_kset); 529 rpc_sunrpc_kset = NULL; 530 return -ENOMEM; 531 } 532 533 static void rpc_sysfs_client_release(struct kobject *kobj) 534 { 535 struct rpc_sysfs_client *c; 536 537 c = container_of(kobj, struct rpc_sysfs_client, kobject); 538 kfree(c); 539 } 540 541 static void rpc_sysfs_xprt_switch_release(struct kobject *kobj) 542 { 543 struct rpc_sysfs_xprt_switch *xprt_switch; 544 545 xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject); 546 kfree(xprt_switch); 547 } 548 549 static void rpc_sysfs_xprt_release(struct kobject *kobj) 550 { 551 struct rpc_sysfs_xprt *xprt; 552 553 xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject); 554 kfree(xprt); 555 } 556 557 static const struct ns_common *rpc_sysfs_client_namespace(const struct kobject *kobj) 558 { 559 return to_ns_common(container_of(kobj, struct rpc_sysfs_client, 560 kobject)->net); 561 } 562 563 static const struct ns_common *rpc_sysfs_xprt_switch_namespace(const struct kobject *kobj) 564 { 565 return to_ns_common(container_of(kobj, struct rpc_sysfs_xprt_switch, 566 kobject)->net); 567 } 568 569 static const struct ns_common *rpc_sysfs_xprt_namespace(const struct kobject *kobj) 570 { 571 return to_ns_common(container_of(kobj, struct rpc_sysfs_xprt, 572 kobject)->xprt->xprt_net); 573 } 574 575 static struct kobj_attribute rpc_sysfs_clnt_version = __ATTR(rpc_version, 576 0444, rpc_sysfs_clnt_version_show, NULL); 577 578 static struct kobj_attribute rpc_sysfs_clnt_program = __ATTR(program, 579 0444, rpc_sysfs_clnt_program_show, NULL); 580 581 static struct kobj_attribute rpc_sysfs_clnt_max_connect = __ATTR(max_connect, 582 0444, rpc_sysfs_clnt_max_connect_show, NULL); 583 584 static struct attribute *rpc_sysfs_rpc_clnt_attrs[] = { 585 &rpc_sysfs_clnt_version.attr, 586 &rpc_sysfs_clnt_program.attr, 587 &rpc_sysfs_clnt_max_connect.attr, 588 NULL, 589 }; 590 ATTRIBUTE_GROUPS(rpc_sysfs_rpc_clnt); 591 592 static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr, 593 0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store); 594 595 static struct kobj_attribute rpc_sysfs_xprt_srcaddr = __ATTR(srcaddr, 596 0644, rpc_sysfs_xprt_srcaddr_show, NULL); 597 598 static struct kobj_attribute rpc_sysfs_xprt_xprtsec = __ATTR(xprtsec, 599 0644, rpc_sysfs_xprt_xprtsec_show, NULL); 600 601 static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info, 602 0444, rpc_sysfs_xprt_info_show, NULL); 603 604 static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state, 605 0644, rpc_sysfs_xprt_state_show, rpc_sysfs_xprt_state_change); 606 607 static struct kobj_attribute rpc_sysfs_xprt_del = __ATTR(del_xprt, 608 0644, rpc_sysfs_xprt_del_xprt_show, rpc_sysfs_xprt_del_xprt); 609 610 static struct attribute *rpc_sysfs_xprt_attrs[] = { 611 &rpc_sysfs_xprt_dstaddr.attr, 612 &rpc_sysfs_xprt_srcaddr.attr, 613 &rpc_sysfs_xprt_xprtsec.attr, 614 &rpc_sysfs_xprt_info.attr, 615 &rpc_sysfs_xprt_change_state.attr, 616 &rpc_sysfs_xprt_del.attr, 617 NULL, 618 }; 619 ATTRIBUTE_GROUPS(rpc_sysfs_xprt); 620 621 static struct kobj_attribute rpc_sysfs_xprt_switch_info = 622 __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL); 623 624 static struct kobj_attribute rpc_sysfs_xprt_switch_add_xprt = 625 __ATTR(add_xprt, 0644, rpc_sysfs_xprt_switch_add_xprt_show, 626 rpc_sysfs_xprt_switch_add_xprt_store); 627 628 static struct attribute *rpc_sysfs_xprt_switch_attrs[] = { 629 &rpc_sysfs_xprt_switch_info.attr, 630 &rpc_sysfs_xprt_switch_add_xprt.attr, 631 NULL, 632 }; 633 ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch); 634 635 static const struct kobj_type rpc_sysfs_client_type = { 636 .release = rpc_sysfs_client_release, 637 .default_groups = rpc_sysfs_rpc_clnt_groups, 638 .sysfs_ops = &kobj_sysfs_ops, 639 .namespace = rpc_sysfs_client_namespace, 640 }; 641 642 static const struct kobj_type rpc_sysfs_xprt_switch_type = { 643 .release = rpc_sysfs_xprt_switch_release, 644 .default_groups = rpc_sysfs_xprt_switch_groups, 645 .sysfs_ops = &kobj_sysfs_ops, 646 .namespace = rpc_sysfs_xprt_switch_namespace, 647 }; 648 649 static const struct kobj_type rpc_sysfs_xprt_type = { 650 .release = rpc_sysfs_xprt_release, 651 .default_groups = rpc_sysfs_xprt_groups, 652 .sysfs_ops = &kobj_sysfs_ops, 653 .namespace = rpc_sysfs_xprt_namespace, 654 }; 655 656 void rpc_sysfs_exit(void) 657 { 658 kobject_put(rpc_sunrpc_client_kobj); 659 kobject_put(rpc_sunrpc_xprt_switch_kobj); 660 kset_unregister(rpc_sunrpc_kset); 661 } 662 663 static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent, 664 struct net *net, 665 int clid) 666 { 667 struct rpc_sysfs_client *p; 668 669 p = kzalloc_obj(*p); 670 if (p) { 671 p->net = net; 672 p->kobject.kset = rpc_sunrpc_kset; 673 if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type, 674 parent, "clnt-%d", clid) == 0) 675 return p; 676 kobject_put(&p->kobject); 677 } 678 return NULL; 679 } 680 681 static struct rpc_sysfs_xprt_switch * 682 rpc_sysfs_xprt_switch_alloc(struct kobject *parent, 683 struct rpc_xprt_switch *xprt_switch, 684 struct net *net, 685 gfp_t gfp_flags) 686 { 687 struct rpc_sysfs_xprt_switch *p; 688 689 p = kzalloc_obj(*p, gfp_flags); 690 if (p) { 691 p->net = net; 692 p->kobject.kset = rpc_sunrpc_kset; 693 if (kobject_init_and_add(&p->kobject, 694 &rpc_sysfs_xprt_switch_type, 695 parent, "switch-%d", 696 xprt_switch->xps_id) == 0) 697 return p; 698 kobject_put(&p->kobject); 699 } 700 return NULL; 701 } 702 703 static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent, 704 struct rpc_xprt *xprt, 705 gfp_t gfp_flags) 706 { 707 struct rpc_sysfs_xprt *p; 708 709 p = kzalloc_obj(*p, gfp_flags); 710 if (!p) 711 goto out; 712 p->kobject.kset = rpc_sunrpc_kset; 713 if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type, 714 parent, "xprt-%d-%s", xprt->id, 715 xprt->address_strings[RPC_DISPLAY_PROTO]) == 0) 716 return p; 717 kobject_put(&p->kobject); 718 out: 719 return NULL; 720 } 721 722 void rpc_sysfs_client_setup(struct rpc_clnt *clnt, 723 struct rpc_xprt_switch *xprt_switch, 724 struct net *net) 725 { 726 struct rpc_sysfs_client *rpc_client; 727 struct rpc_sysfs_xprt_switch *xswitch = 728 (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; 729 730 if (!xswitch) 731 return; 732 733 rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj, 734 net, clnt->cl_clid); 735 if (rpc_client) { 736 char name[] = "switch"; 737 int ret; 738 739 clnt->cl_sysfs = rpc_client; 740 rpc_client->clnt = clnt; 741 rpc_client->xprt_switch = xprt_switch; 742 kobject_uevent(&rpc_client->kobject, KOBJ_ADD); 743 ret = sysfs_create_link_nowarn(&rpc_client->kobject, 744 &xswitch->kobject, name); 745 if (ret) 746 pr_warn("can't create link to %s in sysfs (%d)\n", 747 name, ret); 748 } 749 } 750 751 void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, 752 struct rpc_xprt *xprt, 753 gfp_t gfp_flags) 754 { 755 struct rpc_sysfs_xprt_switch *rpc_xprt_switch; 756 struct net *net; 757 758 if (xprt_switch->xps_net) 759 net = xprt_switch->xps_net; 760 else 761 net = xprt->xprt_net; 762 rpc_xprt_switch = 763 rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj, 764 xprt_switch, net, gfp_flags); 765 if (rpc_xprt_switch) { 766 xprt_switch->xps_sysfs = rpc_xprt_switch; 767 rpc_xprt_switch->xprt_switch = xprt_switch; 768 rpc_xprt_switch->xprt = xprt; 769 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); 770 } else { 771 xprt_switch->xps_sysfs = NULL; 772 } 773 } 774 775 void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch, 776 struct rpc_xprt *xprt, 777 gfp_t gfp_flags) 778 { 779 struct rpc_sysfs_xprt *rpc_xprt; 780 struct rpc_sysfs_xprt_switch *switch_obj = 781 (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; 782 783 if (!switch_obj) 784 return; 785 786 rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags); 787 if (rpc_xprt) { 788 xprt->xprt_sysfs = rpc_xprt; 789 rpc_xprt->xprt = xprt; 790 rpc_xprt->xprt_switch = xprt_switch; 791 kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD); 792 } 793 } 794 795 void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) 796 { 797 struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; 798 799 if (rpc_client) { 800 char name[] = "switch"; 801 802 sysfs_remove_link(&rpc_client->kobject, name); 803 kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE); 804 kobject_del(&rpc_client->kobject); 805 kobject_put(&rpc_client->kobject); 806 clnt->cl_sysfs = NULL; 807 } 808 } 809 810 void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch) 811 { 812 struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs; 813 814 if (rpc_xprt_switch) { 815 kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE); 816 kobject_del(&rpc_xprt_switch->kobject); 817 kobject_put(&rpc_xprt_switch->kobject); 818 xprt_switch->xps_sysfs = NULL; 819 } 820 } 821 822 void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt) 823 { 824 struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs; 825 826 if (rpc_xprt) { 827 kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE); 828 kobject_del(&rpc_xprt->kobject); 829 kobject_put(&rpc_xprt->kobject); 830 xprt->xprt_sysfs = NULL; 831 } 832 } 833