sysfs.c 21 KB

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