Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'sysfs-devel'

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

+650 -2
+2
include/linux/sunrpc/clnt.h
··· 29 29 #include <linux/sunrpc/xprtmultipath.h> 30 30 31 31 struct rpc_inode; 32 + struct rpc_sysfs_client; 32 33 33 34 /* 34 35 * The high-level client handle ··· 72 71 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 73 72 struct dentry *cl_debugfs; /* debugfs directory */ 74 73 #endif 74 + struct rpc_sysfs_client *cl_sysfs; /* sysfs directory */ 75 75 /* cl_work is only needed after cl_xpi is no longer used, 76 76 * and that are of similar size 77 77 */
+7
include/linux/sunrpc/xprt.h
··· 53 53 54 54 struct rpc_task; 55 55 struct rpc_xprt; 56 + struct xprt_class; 56 57 struct seq_file; 57 58 struct svc_serv; 58 59 struct net; ··· 183 182 XPRT_TRANSPORT_LOCAL = 257, 184 183 }; 185 184 185 + struct rpc_sysfs_xprt; 186 186 struct rpc_xprt { 187 187 struct kref kref; /* Reference count */ 188 188 const struct rpc_xprt_ops *ops; /* transport methods */ 189 + unsigned int id; /* transport id */ 189 190 190 191 const struct rpc_timeout *timeout; /* timeout parms */ 191 192 struct sockaddr_storage addr; /* server address */ ··· 291 288 atomic_t inject_disconnect; 292 289 #endif 293 290 struct rcu_head rcu; 291 + const struct xprt_class *xprt_class; 292 + struct rpc_sysfs_xprt *xprt_sysfs; 294 293 }; 295 294 296 295 #if defined(CONFIG_SUNRPC_BACKCHANNEL) ··· 375 370 void xprt_free(struct rpc_xprt *); 376 371 void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task); 377 372 bool xprt_wake_up_backlog(struct rpc_xprt *xprt, struct rpc_rqst *req); 373 + void xprt_cleanup_ids(void); 378 374 379 375 static inline int 380 376 xprt_enable_swap(struct rpc_xprt *xprt) ··· 414 408 415 409 bool xprt_lock_connect(struct rpc_xprt *, struct rpc_task *, void *); 416 410 void xprt_unlock_connect(struct rpc_xprt *, void *); 411 + void xprt_release_write(struct rpc_xprt *, struct rpc_task *); 417 412 418 413 /* 419 414 * Reserved bit positions in xprt->state
+6
include/linux/sunrpc/xprtmultipath.h
··· 10 10 #define _NET_SUNRPC_XPRTMULTIPATH_H 11 11 12 12 struct rpc_xprt_iter_ops; 13 + struct rpc_sysfs_xprt_switch; 13 14 struct rpc_xprt_switch { 14 15 spinlock_t xps_lock; 15 16 struct kref xps_kref; 16 17 18 + unsigned int xps_id; 17 19 unsigned int xps_nxprts; 18 20 unsigned int xps_nactive; 19 21 atomic_long_t xps_queuelen; ··· 25 23 26 24 const struct rpc_xprt_iter_ops *xps_iter_ops; 27 25 26 + struct rpc_sysfs_xprt_switch *xps_sysfs; 28 27 struct rcu_head xps_rcu; 29 28 }; 30 29 ··· 74 71 75 72 extern bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps, 76 73 const struct sockaddr *sap); 74 + 75 + extern void xprt_multipath_cleanup_ids(void); 76 + 77 77 #endif
+1 -1
net/sunrpc/Makefile
··· 12 12 auth.o auth_null.o auth_unix.o \ 13 13 svc.o svcsock.o svcauth.o svcauth_unix.o \ 14 14 addr.o rpcb_clnt.o timer.o xdr.o \ 15 - sunrpc_syms.o cache.o rpc_pipe.o \ 15 + sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \ 16 16 svc_xprt.o \ 17 17 xprtmultipath.o 18 18 sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o
+5
net/sunrpc/clnt.c
··· 41 41 #include <trace/events/sunrpc.h> 42 42 43 43 #include "sunrpc.h" 44 + #include "sysfs.h" 44 45 #include "netns.h" 45 46 46 47 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) ··· 328 327 out: 329 328 if (pipefs_sb) 330 329 rpc_put_sb_net(net); 330 + rpc_sysfs_client_destroy(clnt); 331 331 rpc_clnt_debugfs_unregister(clnt); 332 332 return err; 333 333 } ··· 425 423 /* save the nodename */ 426 424 rpc_clnt_set_nodename(clnt, nodename); 427 425 426 + rpc_sysfs_client_setup(clnt, xps, rpc_net_ns(clnt)); 428 427 err = rpc_client_register(clnt, args->authflavor, args->client_name); 429 428 if (err) 430 429 goto out_no_path; ··· 736 733 737 734 rpc_unregister_client(clnt); 738 735 __rpc_clnt_remove_pipedir(clnt); 736 + rpc_sysfs_client_destroy(clnt); 739 737 rpc_clnt_debugfs_unregister(clnt); 740 738 741 739 /* ··· 883 879 * so they cannot be called in rpciod, so they are handled separately 884 880 * here. 885 881 */ 882 + rpc_sysfs_client_destroy(clnt); 886 883 rpc_clnt_debugfs_unregister(clnt); 887 884 rpc_free_clid(clnt); 888 885 rpc_clnt_remove_pipedir(clnt);
+10
net/sunrpc/sunrpc_syms.c
··· 24 24 #include <linux/sunrpc/xprtsock.h> 25 25 26 26 #include "sunrpc.h" 27 + #include "sysfs.h" 27 28 #include "netns.h" 28 29 29 30 unsigned int sunrpc_net_id; ··· 104 103 if (err) 105 104 goto out4; 106 105 106 + err = rpc_sysfs_init(); 107 + if (err) 108 + goto out5; 109 + 107 110 sunrpc_debugfs_init(); 108 111 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 109 112 rpc_register_sysctl(); ··· 116 111 init_socket_xprt(); /* clnt sock transport */ 117 112 return 0; 118 113 114 + out5: 115 + unregister_rpc_pipefs(); 119 116 out4: 120 117 unregister_pernet_subsys(&sunrpc_net_ops); 121 118 out3: ··· 131 124 static void __exit 132 125 cleanup_sunrpc(void) 133 126 { 127 + rpc_sysfs_exit(); 134 128 rpc_cleanup_clids(); 129 + xprt_cleanup_ids(); 130 + xprt_multipath_cleanup_ids(); 135 131 rpcauth_remove_module(); 136 132 cleanup_socket_xprt(); 137 133 svc_cleanup_xprt_sock();
+506
net/sunrpc/sysfs.c
··· 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 + 9 + #include "sysfs.h" 10 + 11 + struct xprt_addr { 12 + const char *addr; 13 + struct rcu_head rcu; 14 + }; 15 + 16 + static void free_xprt_addr(struct rcu_head *head) 17 + { 18 + struct xprt_addr *addr = container_of(head, struct xprt_addr, rcu); 19 + 20 + kfree(addr->addr); 21 + kfree(addr); 22 + } 23 + 24 + static struct kset *rpc_sunrpc_kset; 25 + static struct kobject *rpc_sunrpc_client_kobj, *rpc_sunrpc_xprt_switch_kobj; 26 + 27 + static void rpc_sysfs_object_release(struct kobject *kobj) 28 + { 29 + kfree(kobj); 30 + } 31 + 32 + static const struct kobj_ns_type_operations * 33 + rpc_sysfs_object_child_ns_type(struct kobject *kobj) 34 + { 35 + return &net_ns_type_operations; 36 + } 37 + 38 + static struct kobj_type rpc_sysfs_object_type = { 39 + .release = rpc_sysfs_object_release, 40 + .sysfs_ops = &kobj_sysfs_ops, 41 + .child_ns_type = rpc_sysfs_object_child_ns_type, 42 + }; 43 + 44 + static struct kobject *rpc_sysfs_object_alloc(const char *name, 45 + struct kset *kset, 46 + struct kobject *parent) 47 + { 48 + struct kobject *kobj; 49 + 50 + kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); 51 + if (kobj) { 52 + kobj->kset = kset; 53 + if (kobject_init_and_add(kobj, &rpc_sysfs_object_type, 54 + parent, "%s", name) == 0) 55 + return kobj; 56 + kobject_put(kobj); 57 + } 58 + return NULL; 59 + } 60 + 61 + static inline struct rpc_xprt * 62 + rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj) 63 + { 64 + struct rpc_sysfs_xprt *x = container_of(kobj, 65 + struct rpc_sysfs_xprt, kobject); 66 + 67 + return xprt_get(x->xprt); 68 + } 69 + 70 + static inline struct rpc_xprt_switch * 71 + rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj) 72 + { 73 + struct rpc_sysfs_xprt_switch *x = container_of(kobj, 74 + struct rpc_sysfs_xprt_switch, kobject); 75 + 76 + return xprt_switch_get(x->xprt_switch); 77 + } 78 + 79 + static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj, 80 + struct kobj_attribute *attr, 81 + char *buf) 82 + { 83 + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 84 + ssize_t ret; 85 + 86 + if (!xprt) 87 + return 0; 88 + ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]); 89 + xprt_put(xprt); 90 + return ret + 1; 91 + } 92 + 93 + static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj, 94 + struct kobj_attribute *attr, 95 + char *buf) 96 + { 97 + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 98 + ssize_t ret; 99 + 100 + if (!xprt) 101 + return 0; 102 + 103 + ret = sprintf(buf, "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n" 104 + "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n" 105 + "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n" 106 + "backlog_q_len=%u\n", xprt->last_used, xprt->cong, 107 + xprt->cwnd, xprt->max_reqs, xprt->min_reqs, 108 + xprt->num_reqs, xprt->binding.qlen, xprt->sending.qlen, 109 + xprt->pending.qlen, xprt->backlog.qlen); 110 + xprt_put(xprt); 111 + return ret + 1; 112 + } 113 + 114 + static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, 115 + struct kobj_attribute *attr, 116 + char *buf) 117 + { 118 + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 119 + ssize_t ret; 120 + int locked, connected, connecting, close_wait, bound, binding, 121 + closing, congested, cwnd_wait, write_space; 122 + 123 + if (!xprt) 124 + return 0; 125 + 126 + if (!xprt->state) { 127 + ret = sprintf(buf, "state=CLOSED\n"); 128 + } else { 129 + locked = test_bit(XPRT_LOCKED, &xprt->state); 130 + connected = test_bit(XPRT_CONNECTED, &xprt->state); 131 + connecting = test_bit(XPRT_CONNECTING, &xprt->state); 132 + close_wait = test_bit(XPRT_CLOSE_WAIT, &xprt->state); 133 + bound = test_bit(XPRT_BOUND, &xprt->state); 134 + binding = test_bit(XPRT_BINDING, &xprt->state); 135 + closing = test_bit(XPRT_CLOSING, &xprt->state); 136 + congested = test_bit(XPRT_CONGESTED, &xprt->state); 137 + cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state); 138 + write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state); 139 + 140 + ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s\n", 141 + locked ? "LOCKED" : "", 142 + connected ? "CONNECTED" : "", 143 + connecting ? "CONNECTING" : "", 144 + close_wait ? "CLOSE_WAIT" : "", 145 + bound ? "BOUND" : "", 146 + binding ? "BOUNDING" : "", 147 + closing ? "CLOSING" : "", 148 + congested ? "CONGESTED" : "", 149 + cwnd_wait ? "CWND_WAIT" : "", 150 + write_space ? "WRITE_SPACE" : ""); 151 + } 152 + 153 + xprt_put(xprt); 154 + return ret + 1; 155 + } 156 + 157 + static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj, 158 + struct kobj_attribute *attr, 159 + char *buf) 160 + { 161 + struct rpc_xprt_switch *xprt_switch = 162 + rpc_sysfs_xprt_switch_kobj_get_xprt(kobj); 163 + ssize_t ret; 164 + 165 + if (!xprt_switch) 166 + return 0; 167 + ret = sprintf(buf, "num_xprts=%u\nnum_active=%u\nqueue_len=%ld\n", 168 + xprt_switch->xps_nxprts, xprt_switch->xps_nactive, 169 + atomic_long_read(&xprt_switch->xps_queuelen)); 170 + xprt_switch_put(xprt_switch); 171 + return ret + 1; 172 + } 173 + 174 + static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj, 175 + struct kobj_attribute *attr, 176 + const char *buf, size_t count) 177 + { 178 + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); 179 + struct sockaddr *saddr; 180 + char *dst_addr; 181 + int port; 182 + struct xprt_addr *saved_addr; 183 + size_t buf_len; 184 + 185 + if (!xprt) 186 + return 0; 187 + if (!(xprt->xprt_class->ident == XPRT_TRANSPORT_TCP || 188 + xprt->xprt_class->ident == XPRT_TRANSPORT_RDMA)) { 189 + xprt_put(xprt); 190 + return -EOPNOTSUPP; 191 + } 192 + 193 + if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { 194 + count = -EINTR; 195 + goto out_put; 196 + } 197 + saddr = (struct sockaddr *)&xprt->addr; 198 + port = rpc_get_port(saddr); 199 + 200 + /* buf_len is the len until the first occurence of either 201 + * '\n' or '\0' 202 + */ 203 + buf_len = strcspn(buf, "\n"); 204 + 205 + dst_addr = kstrndup(buf, buf_len, GFP_KERNEL); 206 + if (!dst_addr) 207 + goto out_err; 208 + saved_addr = kzalloc(sizeof(*saved_addr), GFP_KERNEL); 209 + if (!saved_addr) 210 + goto out_err_free; 211 + saved_addr->addr = 212 + rcu_dereference_raw(xprt->address_strings[RPC_DISPLAY_ADDR]); 213 + rcu_assign_pointer(xprt->address_strings[RPC_DISPLAY_ADDR], dst_addr); 214 + call_rcu(&saved_addr->rcu, free_xprt_addr); 215 + xprt->addrlen = rpc_pton(xprt->xprt_net, buf, buf_len, saddr, 216 + sizeof(*saddr)); 217 + rpc_set_port(saddr, port); 218 + 219 + xprt_force_disconnect(xprt); 220 + out: 221 + xprt_release_write(xprt, NULL); 222 + out_put: 223 + xprt_put(xprt); 224 + return count; 225 + out_err_free: 226 + kfree(dst_addr); 227 + out_err: 228 + count = -ENOMEM; 229 + goto out; 230 + } 231 + 232 + int rpc_sysfs_init(void) 233 + { 234 + rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj); 235 + if (!rpc_sunrpc_kset) 236 + return -ENOMEM; 237 + rpc_sunrpc_client_kobj = 238 + rpc_sysfs_object_alloc("rpc-clients", rpc_sunrpc_kset, NULL); 239 + if (!rpc_sunrpc_client_kobj) 240 + goto err_client; 241 + rpc_sunrpc_xprt_switch_kobj = 242 + rpc_sysfs_object_alloc("xprt-switches", rpc_sunrpc_kset, NULL); 243 + if (!rpc_sunrpc_xprt_switch_kobj) 244 + goto err_switch; 245 + return 0; 246 + err_switch: 247 + kobject_put(rpc_sunrpc_client_kobj); 248 + rpc_sunrpc_client_kobj = NULL; 249 + err_client: 250 + kset_unregister(rpc_sunrpc_kset); 251 + rpc_sunrpc_kset = NULL; 252 + return -ENOMEM; 253 + } 254 + 255 + static void rpc_sysfs_client_release(struct kobject *kobj) 256 + { 257 + struct rpc_sysfs_client *c; 258 + 259 + c = container_of(kobj, struct rpc_sysfs_client, kobject); 260 + kfree(c); 261 + } 262 + 263 + static void rpc_sysfs_xprt_switch_release(struct kobject *kobj) 264 + { 265 + struct rpc_sysfs_xprt_switch *xprt_switch; 266 + 267 + xprt_switch = container_of(kobj, struct rpc_sysfs_xprt_switch, kobject); 268 + kfree(xprt_switch); 269 + } 270 + 271 + static void rpc_sysfs_xprt_release(struct kobject *kobj) 272 + { 273 + struct rpc_sysfs_xprt *xprt; 274 + 275 + xprt = container_of(kobj, struct rpc_sysfs_xprt, kobject); 276 + kfree(xprt); 277 + } 278 + 279 + static const void *rpc_sysfs_client_namespace(struct kobject *kobj) 280 + { 281 + return container_of(kobj, struct rpc_sysfs_client, kobject)->net; 282 + } 283 + 284 + static const void *rpc_sysfs_xprt_switch_namespace(struct kobject *kobj) 285 + { 286 + return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net; 287 + } 288 + 289 + static const void *rpc_sysfs_xprt_namespace(struct kobject *kobj) 290 + { 291 + return container_of(kobj, struct rpc_sysfs_xprt, 292 + kobject)->xprt->xprt_net; 293 + } 294 + 295 + static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr, 296 + 0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store); 297 + 298 + static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info, 299 + 0444, rpc_sysfs_xprt_info_show, NULL); 300 + 301 + static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state, 302 + 0644, rpc_sysfs_xprt_state_show, NULL); 303 + 304 + static struct attribute *rpc_sysfs_xprt_attrs[] = { 305 + &rpc_sysfs_xprt_dstaddr.attr, 306 + &rpc_sysfs_xprt_info.attr, 307 + &rpc_sysfs_xprt_change_state.attr, 308 + NULL, 309 + }; 310 + 311 + static struct kobj_attribute rpc_sysfs_xprt_switch_info = 312 + __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL); 313 + 314 + static struct attribute *rpc_sysfs_xprt_switch_attrs[] = { 315 + &rpc_sysfs_xprt_switch_info.attr, 316 + NULL, 317 + }; 318 + 319 + static struct kobj_type rpc_sysfs_client_type = { 320 + .release = rpc_sysfs_client_release, 321 + .sysfs_ops = &kobj_sysfs_ops, 322 + .namespace = rpc_sysfs_client_namespace, 323 + }; 324 + 325 + static struct kobj_type rpc_sysfs_xprt_switch_type = { 326 + .release = rpc_sysfs_xprt_switch_release, 327 + .default_attrs = rpc_sysfs_xprt_switch_attrs, 328 + .sysfs_ops = &kobj_sysfs_ops, 329 + .namespace = rpc_sysfs_xprt_switch_namespace, 330 + }; 331 + 332 + static struct kobj_type rpc_sysfs_xprt_type = { 333 + .release = rpc_sysfs_xprt_release, 334 + .default_attrs = rpc_sysfs_xprt_attrs, 335 + .sysfs_ops = &kobj_sysfs_ops, 336 + .namespace = rpc_sysfs_xprt_namespace, 337 + }; 338 + 339 + void rpc_sysfs_exit(void) 340 + { 341 + kobject_put(rpc_sunrpc_client_kobj); 342 + kobject_put(rpc_sunrpc_xprt_switch_kobj); 343 + kset_unregister(rpc_sunrpc_kset); 344 + } 345 + 346 + static struct rpc_sysfs_client *rpc_sysfs_client_alloc(struct kobject *parent, 347 + struct net *net, 348 + int clid) 349 + { 350 + struct rpc_sysfs_client *p; 351 + 352 + p = kzalloc(sizeof(*p), GFP_KERNEL); 353 + if (p) { 354 + p->net = net; 355 + p->kobject.kset = rpc_sunrpc_kset; 356 + if (kobject_init_and_add(&p->kobject, &rpc_sysfs_client_type, 357 + parent, "clnt-%d", clid) == 0) 358 + return p; 359 + kobject_put(&p->kobject); 360 + } 361 + return NULL; 362 + } 363 + 364 + static struct rpc_sysfs_xprt_switch * 365 + rpc_sysfs_xprt_switch_alloc(struct kobject *parent, 366 + struct rpc_xprt_switch *xprt_switch, 367 + struct net *net, 368 + gfp_t gfp_flags) 369 + { 370 + struct rpc_sysfs_xprt_switch *p; 371 + 372 + p = kzalloc(sizeof(*p), gfp_flags); 373 + if (p) { 374 + p->net = net; 375 + p->kobject.kset = rpc_sunrpc_kset; 376 + if (kobject_init_and_add(&p->kobject, 377 + &rpc_sysfs_xprt_switch_type, 378 + parent, "switch-%d", 379 + xprt_switch->xps_id) == 0) 380 + return p; 381 + kobject_put(&p->kobject); 382 + } 383 + return NULL; 384 + } 385 + 386 + static struct rpc_sysfs_xprt *rpc_sysfs_xprt_alloc(struct kobject *parent, 387 + struct rpc_xprt *xprt, 388 + gfp_t gfp_flags) 389 + { 390 + struct rpc_sysfs_xprt *p; 391 + 392 + p = kzalloc(sizeof(*p), gfp_flags); 393 + if (!p) 394 + goto out; 395 + p->kobject.kset = rpc_sunrpc_kset; 396 + if (kobject_init_and_add(&p->kobject, &rpc_sysfs_xprt_type, 397 + parent, "xprt-%d-%s", xprt->id, 398 + xprt->address_strings[RPC_DISPLAY_PROTO]) == 0) 399 + return p; 400 + kobject_put(&p->kobject); 401 + out: 402 + return NULL; 403 + } 404 + 405 + void rpc_sysfs_client_setup(struct rpc_clnt *clnt, 406 + struct rpc_xprt_switch *xprt_switch, 407 + struct net *net) 408 + { 409 + struct rpc_sysfs_client *rpc_client; 410 + 411 + rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj, 412 + net, clnt->cl_clid); 413 + if (rpc_client) { 414 + char name[] = "switch"; 415 + struct rpc_sysfs_xprt_switch *xswitch = 416 + (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; 417 + int ret; 418 + 419 + clnt->cl_sysfs = rpc_client; 420 + rpc_client->clnt = clnt; 421 + rpc_client->xprt_switch = xprt_switch; 422 + kobject_uevent(&rpc_client->kobject, KOBJ_ADD); 423 + ret = sysfs_create_link_nowarn(&rpc_client->kobject, 424 + &xswitch->kobject, name); 425 + if (ret) 426 + pr_warn("can't create link to %s in sysfs (%d)\n", 427 + name, ret); 428 + } 429 + } 430 + 431 + void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, 432 + struct rpc_xprt *xprt, 433 + gfp_t gfp_flags) 434 + { 435 + struct rpc_sysfs_xprt_switch *rpc_xprt_switch; 436 + struct net *net; 437 + 438 + if (xprt_switch->xps_net) 439 + net = xprt_switch->xps_net; 440 + else 441 + net = xprt->xprt_net; 442 + rpc_xprt_switch = 443 + rpc_sysfs_xprt_switch_alloc(rpc_sunrpc_xprt_switch_kobj, 444 + xprt_switch, net, gfp_flags); 445 + if (rpc_xprt_switch) { 446 + xprt_switch->xps_sysfs = rpc_xprt_switch; 447 + rpc_xprt_switch->xprt_switch = xprt_switch; 448 + rpc_xprt_switch->xprt = xprt; 449 + kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); 450 + } 451 + } 452 + 453 + void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch, 454 + struct rpc_xprt *xprt, 455 + gfp_t gfp_flags) 456 + { 457 + struct rpc_sysfs_xprt *rpc_xprt; 458 + struct rpc_sysfs_xprt_switch *switch_obj = 459 + (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; 460 + 461 + rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags); 462 + if (rpc_xprt) { 463 + xprt->xprt_sysfs = rpc_xprt; 464 + rpc_xprt->xprt = xprt; 465 + kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD); 466 + } 467 + } 468 + 469 + void rpc_sysfs_client_destroy(struct rpc_clnt *clnt) 470 + { 471 + struct rpc_sysfs_client *rpc_client = clnt->cl_sysfs; 472 + 473 + if (rpc_client) { 474 + char name[] = "switch"; 475 + 476 + sysfs_remove_link(&rpc_client->kobject, name); 477 + kobject_uevent(&rpc_client->kobject, KOBJ_REMOVE); 478 + kobject_del(&rpc_client->kobject); 479 + kobject_put(&rpc_client->kobject); 480 + clnt->cl_sysfs = NULL; 481 + } 482 + } 483 + 484 + void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt_switch) 485 + { 486 + struct rpc_sysfs_xprt_switch *rpc_xprt_switch = xprt_switch->xps_sysfs; 487 + 488 + if (rpc_xprt_switch) { 489 + kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_REMOVE); 490 + kobject_del(&rpc_xprt_switch->kobject); 491 + kobject_put(&rpc_xprt_switch->kobject); 492 + xprt_switch->xps_sysfs = NULL; 493 + } 494 + } 495 + 496 + void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt) 497 + { 498 + struct rpc_sysfs_xprt *rpc_xprt = xprt->xprt_sysfs; 499 + 500 + if (rpc_xprt) { 501 + kobject_uevent(&rpc_xprt->kobject, KOBJ_REMOVE); 502 + kobject_del(&rpc_xprt->kobject); 503 + kobject_put(&rpc_xprt->kobject); 504 + xprt->xprt_sysfs = NULL; 505 + } 506 + }
+41
net/sunrpc/sysfs.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com> 4 + */ 5 + #ifndef __SUNRPC_SYSFS_H 6 + #define __SUNRPC_SYSFS_H 7 + 8 + struct rpc_sysfs_client { 9 + struct kobject kobject; 10 + struct net *net; 11 + struct rpc_clnt *clnt; 12 + struct rpc_xprt_switch *xprt_switch; 13 + }; 14 + 15 + struct rpc_sysfs_xprt_switch { 16 + struct kobject kobject; 17 + struct net *net; 18 + struct rpc_xprt_switch *xprt_switch; 19 + struct rpc_xprt *xprt; 20 + }; 21 + 22 + struct rpc_sysfs_xprt { 23 + struct kobject kobject; 24 + struct rpc_xprt *xprt; 25 + }; 26 + 27 + int rpc_sysfs_init(void); 28 + void rpc_sysfs_exit(void); 29 + 30 + void rpc_sysfs_client_setup(struct rpc_clnt *clnt, 31 + struct rpc_xprt_switch *xprt_switch, 32 + struct net *net); 33 + void rpc_sysfs_client_destroy(struct rpc_clnt *clnt); 34 + void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, 35 + struct rpc_xprt *xprt, gfp_t gfp_flags); 36 + void rpc_sysfs_xprt_switch_destroy(struct rpc_xprt_switch *xprt); 37 + void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch, 38 + struct rpc_xprt *xprt, gfp_t gfp_flags); 39 + void rpc_sysfs_xprt_destroy(struct rpc_xprt *xprt); 40 + 41 + #endif
+29 -1
net/sunrpc/xprt.c
··· 55 55 #include <trace/events/sunrpc.h> 56 56 57 57 #include "sunrpc.h" 58 + #include "sysfs.h" 58 59 59 60 /* 60 61 * Local variables ··· 444 443 } 445 444 EXPORT_SYMBOL_GPL(xprt_release_xprt_cong); 446 445 447 - static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) 446 + void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) 448 447 { 449 448 if (xprt->snd_task != task) 450 449 return; ··· 1747 1746 } 1748 1747 } 1749 1748 1749 + static DEFINE_IDA(rpc_xprt_ids); 1750 + 1751 + void xprt_cleanup_ids(void) 1752 + { 1753 + ida_destroy(&rpc_xprt_ids); 1754 + } 1755 + 1756 + static int xprt_alloc_id(struct rpc_xprt *xprt) 1757 + { 1758 + int id; 1759 + 1760 + id = ida_simple_get(&rpc_xprt_ids, 0, 0, GFP_KERNEL); 1761 + if (id < 0) 1762 + return id; 1763 + 1764 + xprt->id = id; 1765 + return 0; 1766 + } 1767 + 1768 + static void xprt_free_id(struct rpc_xprt *xprt) 1769 + { 1770 + ida_simple_remove(&rpc_xprt_ids, xprt->id); 1771 + } 1772 + 1750 1773 struct rpc_xprt *xprt_alloc(struct net *net, size_t size, 1751 1774 unsigned int num_prealloc, 1752 1775 unsigned int max_alloc) ··· 1783 1758 if (xprt == NULL) 1784 1759 goto out; 1785 1760 1761 + xprt_alloc_id(xprt); 1786 1762 xprt_init(xprt, net); 1787 1763 1788 1764 for (i = 0; i < num_prealloc; i++) { ··· 1812 1786 { 1813 1787 put_net(xprt->xprt_net); 1814 1788 xprt_free_all_slots(xprt); 1789 + xprt_free_id(xprt); 1790 + rpc_sysfs_xprt_destroy(xprt); 1815 1791 kfree_rcu(xprt, rcu); 1816 1792 } 1817 1793 EXPORT_SYMBOL_GPL(xprt_free);
+32
net/sunrpc/xprtmultipath.c
··· 19 19 #include <linux/sunrpc/addr.h> 20 20 #include <linux/sunrpc/xprtmultipath.h> 21 21 22 + #include "sysfs.h" 23 + 22 24 typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct rpc_xprt_switch *xps, 23 25 const struct rpc_xprt *cur); 24 26 ··· 57 55 if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) 58 56 xprt_switch_add_xprt_locked(xps, xprt); 59 57 spin_unlock(&xps->xps_lock); 58 + rpc_sysfs_xprt_setup(xps, xprt, GFP_KERNEL); 60 59 } 61 60 62 61 static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, ··· 89 86 xprt_put(xprt); 90 87 } 91 88 89 + static DEFINE_IDA(rpc_xprtswitch_ids); 90 + 91 + void xprt_multipath_cleanup_ids(void) 92 + { 93 + ida_destroy(&rpc_xprtswitch_ids); 94 + } 95 + 96 + static int xprt_switch_alloc_id(struct rpc_xprt_switch *xps, gfp_t gfp_flags) 97 + { 98 + int id; 99 + 100 + id = ida_simple_get(&rpc_xprtswitch_ids, 0, 0, gfp_flags); 101 + if (id < 0) 102 + return id; 103 + 104 + xps->xps_id = id; 105 + return 0; 106 + } 107 + 108 + static void xprt_switch_free_id(struct rpc_xprt_switch *xps) 109 + { 110 + ida_simple_remove(&rpc_xprtswitch_ids, xps->xps_id); 111 + } 112 + 92 113 /** 93 114 * xprt_switch_alloc - Allocate a new struct rpc_xprt_switch 94 115 * @xprt: pointer to struct rpc_xprt ··· 130 103 if (xps != NULL) { 131 104 spin_lock_init(&xps->xps_lock); 132 105 kref_init(&xps->xps_kref); 106 + xprt_switch_alloc_id(xps, gfp_flags); 133 107 xps->xps_nxprts = xps->xps_nactive = 0; 134 108 atomic_long_set(&xps->xps_queuelen, 0); 135 109 xps->xps_net = NULL; 136 110 INIT_LIST_HEAD(&xps->xps_xprt_list); 137 111 xps->xps_iter_ops = &rpc_xprt_iter_singular; 112 + rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); 138 113 xprt_switch_add_xprt_locked(xps, xprt); 114 + rpc_sysfs_xprt_setup(xps, xprt, gfp_flags); 139 115 } 140 116 141 117 return xps; ··· 166 136 struct rpc_xprt_switch, xps_kref); 167 137 168 138 xprt_switch_free_entries(xps); 139 + rpc_sysfs_xprt_switch_destroy(xps); 140 + xprt_switch_free_id(xps); 169 141 kfree_rcu(xps, xps_rcu); 170 142 } 171 143
+2
net/sunrpc/xprtrdma/transport.c
··· 73 73 unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; 74 74 unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRWR; 75 75 int xprt_rdma_pad_optimize; 76 + static struct xprt_class xprt_rdma; 76 77 77 78 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 78 79 ··· 350 349 /* Ensure xprt->addr holds valid server TCP (not RDMA) 351 350 * address, for any side protocols which peek at it */ 352 351 xprt->prot = IPPROTO_TCP; 352 + xprt->xprt_class = &xprt_rdma; 353 353 xprt->addrlen = args->addrlen; 354 354 memcpy(&xprt->addr, sap, xprt->addrlen); 355 355
+9
net/sunrpc/xprtsock.c
··· 91 91 92 92 static struct ctl_table_header *sunrpc_table_header; 93 93 94 + static struct xprt_class xs_local_transport; 95 + static struct xprt_class xs_udp_transport; 96 + static struct xprt_class xs_tcp_transport; 97 + static struct xprt_class xs_bc_tcp_transport; 98 + 94 99 /* 95 100 * FIXME: changing the UDP slot table size should also resize the UDP 96 101 * socket buffers for existing UDP transports ··· 2785 2780 transport = container_of(xprt, struct sock_xprt, xprt); 2786 2781 2787 2782 xprt->prot = 0; 2783 + xprt->xprt_class = &xs_local_transport; 2788 2784 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; 2789 2785 2790 2786 xprt->bind_timeout = XS_BIND_TO; ··· 2855 2849 transport = container_of(xprt, struct sock_xprt, xprt); 2856 2850 2857 2851 xprt->prot = IPPROTO_UDP; 2852 + xprt->xprt_class = &xs_udp_transport; 2858 2853 /* XXX: header size can vary due to auth type, IPv6, etc. */ 2859 2854 xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); 2860 2855 ··· 2936 2929 transport = container_of(xprt, struct sock_xprt, xprt); 2937 2930 2938 2931 xprt->prot = IPPROTO_TCP; 2932 + xprt->xprt_class = &xs_tcp_transport; 2939 2933 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; 2940 2934 2941 2935 xprt->bind_timeout = XS_BIND_TO; ··· 3010 3002 transport = container_of(xprt, struct sock_xprt, xprt); 3011 3003 3012 3004 xprt->prot = IPPROTO_TCP; 3005 + xprt->xprt_class = &xs_bc_tcp_transport; 3013 3006 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; 3014 3007 xprt->timeout = &xs_tcp_default_timeout; 3015 3008