nfs4session.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * fs/nfs/nfs4session.c
  4. *
  5. * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com>
  6. *
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/errno.h>
  10. #include <linux/string.h>
  11. #include <linux/printk.h>
  12. #include <linux/slab.h>
  13. #include <linux/sunrpc/sched.h>
  14. #include <linux/sunrpc/bc_xprt.h>
  15. #include <linux/nfs.h>
  16. #include <linux/nfs4.h>
  17. #include <linux/nfs_fs.h>
  18. #include <linux/module.h>
  19. #include "nfs4_fs.h"
  20. #include "internal.h"
  21. #include "nfs4session.h"
  22. #include "callback.h"
  23. #define NFSDBG_FACILITY NFSDBG_STATE
  24. static void nfs4_init_slot_table(struct nfs4_slot_table *tbl, const char *queue)
  25. {
  26. tbl->highest_used_slotid = NFS4_NO_SLOT;
  27. spin_lock_init(&tbl->slot_tbl_lock);
  28. rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, queue);
  29. init_waitqueue_head(&tbl->slot_waitq);
  30. init_completion(&tbl->complete);
  31. }
  32. /*
  33. * nfs4_shrink_slot_table - free retired slots from the slot table
  34. */
  35. static void nfs4_shrink_slot_table(struct nfs4_slot_table *tbl, u32 newsize)
  36. {
  37. struct nfs4_slot **p;
  38. if (newsize >= tbl->max_slots)
  39. return;
  40. p = &tbl->slots;
  41. while (newsize--)
  42. p = &(*p)->next;
  43. while (*p) {
  44. struct nfs4_slot *slot = *p;
  45. *p = slot->next;
  46. kfree(slot);
  47. tbl->max_slots--;
  48. }
  49. }
  50. /**
  51. * nfs4_slot_tbl_drain_complete - wake waiters when drain is complete
  52. * @tbl: controlling slot table
  53. *
  54. */
  55. void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl)
  56. {
  57. if (nfs4_slot_tbl_draining(tbl))
  58. complete(&tbl->complete);
  59. }
  60. /*
  61. * nfs4_free_slot - free a slot and efficiently update slot table.
  62. *
  63. * freeing a slot is trivially done by clearing its respective bit
  64. * in the bitmap.
  65. * If the freed slotid equals highest_used_slotid we want to update it
  66. * so that the server would be able to size down the slot table if needed,
  67. * otherwise we know that the highest_used_slotid is still in use.
  68. * When updating highest_used_slotid there may be "holes" in the bitmap
  69. * so we need to scan down from highest_used_slotid to 0 looking for the now
  70. * highest slotid in use.
  71. * If none found, highest_used_slotid is set to NFS4_NO_SLOT.
  72. *
  73. * Must be called while holding tbl->slot_tbl_lock
  74. */
  75. void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
  76. {
  77. u32 slotid = slot->slot_nr;
  78. /* clear used bit in bitmap */
  79. __clear_bit(slotid, tbl->used_slots);
  80. /* update highest_used_slotid when it is freed */
  81. if (slotid == tbl->highest_used_slotid) {
  82. u32 new_max = find_last_bit(tbl->used_slots, slotid);
  83. if (new_max < slotid)
  84. tbl->highest_used_slotid = new_max;
  85. else {
  86. tbl->highest_used_slotid = NFS4_NO_SLOT;
  87. nfs4_slot_tbl_drain_complete(tbl);
  88. }
  89. }
  90. dprintk("%s: slotid %u highest_used_slotid %u\n", __func__,
  91. slotid, tbl->highest_used_slotid);
  92. }
  93. static struct nfs4_slot *nfs4_new_slot(struct nfs4_slot_table *tbl,
  94. u32 slotid, u32 seq_init, gfp_t gfp_mask)
  95. {
  96. struct nfs4_slot *slot;
  97. slot = kzalloc_obj(*slot, gfp_mask);
  98. if (slot) {
  99. slot->table = tbl;
  100. slot->slot_nr = slotid;
  101. slot->seq_nr = seq_init;
  102. slot->seq_nr_highest_sent = seq_init;
  103. slot->seq_nr_last_acked = seq_init - 1;
  104. }
  105. return slot;
  106. }
  107. static struct nfs4_slot *nfs4_find_or_create_slot(struct nfs4_slot_table *tbl,
  108. u32 slotid, u32 seq_init, gfp_t gfp_mask)
  109. {
  110. struct nfs4_slot **p, *slot;
  111. p = &tbl->slots;
  112. for (;;) {
  113. if (*p == NULL) {
  114. *p = nfs4_new_slot(tbl, tbl->max_slots,
  115. seq_init, gfp_mask);
  116. if (*p == NULL)
  117. break;
  118. tbl->max_slots++;
  119. }
  120. slot = *p;
  121. if (slot->slot_nr == slotid)
  122. return slot;
  123. p = &slot->next;
  124. }
  125. return ERR_PTR(-ENOMEM);
  126. }
  127. static void nfs4_lock_slot(struct nfs4_slot_table *tbl,
  128. struct nfs4_slot *slot)
  129. {
  130. u32 slotid = slot->slot_nr;
  131. __set_bit(slotid, tbl->used_slots);
  132. if (slotid > tbl->highest_used_slotid ||
  133. tbl->highest_used_slotid == NFS4_NO_SLOT)
  134. tbl->highest_used_slotid = slotid;
  135. slot->generation = tbl->generation;
  136. }
  137. /*
  138. * nfs4_try_to_lock_slot - Given a slot try to allocate it
  139. *
  140. * Note: must be called with the slot_tbl_lock held.
  141. */
  142. bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
  143. {
  144. if (nfs4_test_locked_slot(tbl, slot->slot_nr))
  145. return false;
  146. nfs4_lock_slot(tbl, slot);
  147. return true;
  148. }
  149. /*
  150. * nfs4_lookup_slot - Find a slot but don't allocate it
  151. *
  152. * Note: must be called with the slot_tbl_lock held.
  153. */
  154. struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid)
  155. {
  156. if (slotid <= tbl->max_slotid)
  157. return nfs4_find_or_create_slot(tbl, slotid, 0, GFP_NOWAIT);
  158. return ERR_PTR(-E2BIG);
  159. }
  160. static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
  161. u32 *seq_nr)
  162. __must_hold(&tbl->slot_tbl_lock)
  163. {
  164. struct nfs4_slot *slot;
  165. int ret;
  166. slot = nfs4_lookup_slot(tbl, slotid);
  167. ret = PTR_ERR_OR_ZERO(slot);
  168. if (!ret)
  169. *seq_nr = slot->seq_nr;
  170. return ret;
  171. }
  172. /*
  173. * nfs4_slot_seqid_in_use - test if a slot sequence id is still in use
  174. *
  175. * Given a slot table, slot id and sequence number, determine if the
  176. * RPC call in question is still in flight. This function is mainly
  177. * intended for use by the callback channel.
  178. */
  179. static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl,
  180. u32 slotid, u32 seq_nr)
  181. {
  182. u32 cur_seq = 0;
  183. bool ret = false;
  184. spin_lock(&tbl->slot_tbl_lock);
  185. if (nfs4_slot_get_seqid(tbl, slotid, &cur_seq) == 0 &&
  186. cur_seq == seq_nr && test_bit(slotid, tbl->used_slots))
  187. ret = true;
  188. spin_unlock(&tbl->slot_tbl_lock);
  189. return ret;
  190. }
  191. /*
  192. * nfs4_slot_wait_on_seqid - wait until a slot sequence id is complete
  193. *
  194. * Given a slot table, slot id and sequence number, wait until the
  195. * corresponding RPC call completes. This function is mainly
  196. * intended for use by the callback channel.
  197. */
  198. int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
  199. u32 slotid, u32 seq_nr,
  200. unsigned long timeout)
  201. {
  202. if (wait_event_timeout(tbl->slot_waitq,
  203. !nfs4_slot_seqid_in_use(tbl, slotid, seq_nr),
  204. timeout) == 0)
  205. return -ETIMEDOUT;
  206. return 0;
  207. }
  208. /*
  209. * nfs4_alloc_slot - efficiently look for a free slot
  210. *
  211. * nfs4_alloc_slot looks for an unset bit in the used_slots bitmap.
  212. * If found, we mark the slot as used, update the highest_used_slotid,
  213. * and respectively set up the sequence operation args.
  214. *
  215. * Note: must be called with under the slot_tbl_lock.
  216. */
  217. struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
  218. {
  219. struct nfs4_slot *ret = ERR_PTR(-EBUSY);
  220. u32 slotid;
  221. dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n",
  222. __func__, tbl->used_slots[0], tbl->highest_used_slotid,
  223. tbl->max_slotid + 1);
  224. slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slotid + 1);
  225. if (slotid <= tbl->max_slotid) {
  226. ret = nfs4_find_or_create_slot(tbl, slotid, 1, GFP_NOWAIT);
  227. if (!IS_ERR(ret))
  228. nfs4_lock_slot(tbl, ret);
  229. }
  230. dprintk("<-- %s used_slots=%04lx highest_used=%u slotid=%u\n",
  231. __func__, tbl->used_slots[0], tbl->highest_used_slotid,
  232. !IS_ERR(ret) ? ret->slot_nr : NFS4_NO_SLOT);
  233. return ret;
  234. }
  235. static int nfs4_grow_slot_table(struct nfs4_slot_table *tbl,
  236. u32 max_reqs, u32 ivalue)
  237. {
  238. if (max_reqs <= tbl->max_slots)
  239. return 0;
  240. if (!IS_ERR(nfs4_find_or_create_slot(tbl, max_reqs - 1, ivalue, GFP_NOFS)))
  241. return 0;
  242. return -ENOMEM;
  243. }
  244. static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl,
  245. u32 server_highest_slotid,
  246. u32 ivalue)
  247. {
  248. struct nfs4_slot **p;
  249. nfs4_shrink_slot_table(tbl, server_highest_slotid + 1);
  250. p = &tbl->slots;
  251. while (*p) {
  252. (*p)->seq_nr = ivalue;
  253. (*p)->seq_nr_highest_sent = ivalue;
  254. (*p)->seq_nr_last_acked = ivalue - 1;
  255. p = &(*p)->next;
  256. }
  257. tbl->highest_used_slotid = NFS4_NO_SLOT;
  258. tbl->target_highest_slotid = server_highest_slotid;
  259. tbl->server_highest_slotid = server_highest_slotid;
  260. tbl->d_target_highest_slotid = 0;
  261. tbl->d2_target_highest_slotid = 0;
  262. tbl->max_slotid = server_highest_slotid;
  263. }
  264. /*
  265. * (re)Initialise a slot table
  266. */
  267. static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl,
  268. u32 max_reqs, u32 ivalue)
  269. {
  270. int ret;
  271. dprintk("--> %s: max_reqs=%u, tbl->max_slots %u\n", __func__,
  272. max_reqs, tbl->max_slots);
  273. if (max_reqs > NFS4_MAX_SLOT_TABLE)
  274. max_reqs = NFS4_MAX_SLOT_TABLE;
  275. ret = nfs4_grow_slot_table(tbl, max_reqs, ivalue);
  276. if (ret)
  277. goto out;
  278. spin_lock(&tbl->slot_tbl_lock);
  279. nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue);
  280. spin_unlock(&tbl->slot_tbl_lock);
  281. dprintk("%s: tbl=%p slots=%p max_slots=%u\n", __func__,
  282. tbl, tbl->slots, tbl->max_slots);
  283. out:
  284. dprintk("<-- %s: return %d\n", __func__, ret);
  285. return ret;
  286. }
  287. /*
  288. * nfs4_release_slot_table - release all slot table entries
  289. */
  290. static void nfs4_release_slot_table(struct nfs4_slot_table *tbl)
  291. {
  292. nfs4_shrink_slot_table(tbl, 0);
  293. }
  294. /**
  295. * nfs4_shutdown_slot_table - release resources attached to a slot table
  296. * @tbl: slot table to shut down
  297. *
  298. */
  299. void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl)
  300. {
  301. nfs4_release_slot_table(tbl);
  302. rpc_destroy_wait_queue(&tbl->slot_tbl_waitq);
  303. }
  304. /**
  305. * nfs4_setup_slot_table - prepare a stand-alone slot table for use
  306. * @tbl: slot table to set up
  307. * @max_reqs: maximum number of requests allowed
  308. * @queue: name to give RPC wait queue
  309. *
  310. * Returns zero on success, or a negative errno.
  311. */
  312. int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, unsigned int max_reqs,
  313. const char *queue)
  314. {
  315. nfs4_init_slot_table(tbl, queue);
  316. return nfs4_realloc_slot_table(tbl, max_reqs, 0);
  317. }
  318. static bool nfs41_assign_slot(struct rpc_task *task, void *pslot)
  319. {
  320. struct nfs4_sequence_args *args = task->tk_msg.rpc_argp;
  321. struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;
  322. struct nfs4_slot *slot = pslot;
  323. struct nfs4_slot_table *tbl = slot->table;
  324. if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
  325. return false;
  326. slot->generation = tbl->generation;
  327. args->sa_slot = slot;
  328. res->sr_timestamp = jiffies;
  329. res->sr_slot = slot;
  330. res->sr_status_flags = 0;
  331. res->sr_status = 1;
  332. return true;
  333. }
  334. static bool __nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl,
  335. struct nfs4_slot *slot)
  336. {
  337. if (rpc_wake_up_first(&tbl->slot_tbl_waitq, nfs41_assign_slot, slot))
  338. return true;
  339. return false;
  340. }
  341. bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl,
  342. struct nfs4_slot *slot)
  343. {
  344. if (slot->slot_nr > tbl->max_slotid)
  345. return false;
  346. return __nfs41_wake_and_assign_slot(tbl, slot);
  347. }
  348. static bool nfs41_try_wake_next_slot_table_entry(struct nfs4_slot_table *tbl)
  349. {
  350. struct nfs4_slot *slot = nfs4_alloc_slot(tbl);
  351. if (!IS_ERR(slot)) {
  352. bool ret = __nfs41_wake_and_assign_slot(tbl, slot);
  353. if (ret)
  354. return ret;
  355. nfs4_free_slot(tbl, slot);
  356. }
  357. return false;
  358. }
  359. void nfs41_wake_slot_table(struct nfs4_slot_table *tbl)
  360. {
  361. for (;;) {
  362. if (!nfs41_try_wake_next_slot_table_entry(tbl))
  363. break;
  364. }
  365. }
  366. static void nfs41_set_max_slotid_locked(struct nfs4_slot_table *tbl,
  367. u32 target_highest_slotid)
  368. {
  369. u32 max_slotid;
  370. max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, target_highest_slotid);
  371. if (max_slotid > tbl->server_highest_slotid)
  372. max_slotid = tbl->server_highest_slotid;
  373. if (max_slotid > tbl->target_highest_slotid)
  374. max_slotid = tbl->target_highest_slotid;
  375. tbl->max_slotid = max_slotid;
  376. nfs41_wake_slot_table(tbl);
  377. }
  378. /* Update the client's idea of target_highest_slotid */
  379. static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl,
  380. u32 target_highest_slotid)
  381. {
  382. if (tbl->target_highest_slotid == target_highest_slotid)
  383. return;
  384. tbl->target_highest_slotid = target_highest_slotid;
  385. tbl->generation++;
  386. }
  387. void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
  388. u32 target_highest_slotid)
  389. {
  390. spin_lock(&tbl->slot_tbl_lock);
  391. nfs41_set_target_slotid_locked(tbl, target_highest_slotid);
  392. tbl->d_target_highest_slotid = 0;
  393. tbl->d2_target_highest_slotid = 0;
  394. nfs41_set_max_slotid_locked(tbl, target_highest_slotid);
  395. spin_unlock(&tbl->slot_tbl_lock);
  396. }
  397. static void nfs41_set_server_slotid_locked(struct nfs4_slot_table *tbl,
  398. u32 highest_slotid)
  399. {
  400. if (tbl->server_highest_slotid == highest_slotid)
  401. return;
  402. if (tbl->highest_used_slotid > highest_slotid)
  403. return;
  404. /* Deallocate slots */
  405. nfs4_shrink_slot_table(tbl, highest_slotid + 1);
  406. tbl->server_highest_slotid = highest_slotid;
  407. }
  408. static s32 nfs41_derivative_target_slotid(s32 s1, s32 s2)
  409. {
  410. s1 -= s2;
  411. if (s1 == 0)
  412. return 0;
  413. if (s1 < 0)
  414. return (s1 - 1) >> 1;
  415. return (s1 + 1) >> 1;
  416. }
  417. static int nfs41_sign_s32(s32 s1)
  418. {
  419. if (s1 > 0)
  420. return 1;
  421. if (s1 < 0)
  422. return -1;
  423. return 0;
  424. }
  425. static bool nfs41_same_sign_or_zero_s32(s32 s1, s32 s2)
  426. {
  427. if (!s1 || !s2)
  428. return true;
  429. return nfs41_sign_s32(s1) == nfs41_sign_s32(s2);
  430. }
  431. /* Try to eliminate outliers by checking for sharp changes in the
  432. * derivatives and second derivatives
  433. */
  434. static bool nfs41_is_outlier_target_slotid(struct nfs4_slot_table *tbl,
  435. u32 new_target)
  436. {
  437. s32 d_target, d2_target;
  438. bool ret = true;
  439. d_target = nfs41_derivative_target_slotid(new_target,
  440. tbl->target_highest_slotid);
  441. d2_target = nfs41_derivative_target_slotid(d_target,
  442. tbl->d_target_highest_slotid);
  443. /* Is first derivative same sign? */
  444. if (nfs41_same_sign_or_zero_s32(d_target, tbl->d_target_highest_slotid))
  445. ret = false;
  446. /* Is second derivative same sign? */
  447. if (nfs41_same_sign_or_zero_s32(d2_target, tbl->d2_target_highest_slotid))
  448. ret = false;
  449. tbl->d_target_highest_slotid = d_target;
  450. tbl->d2_target_highest_slotid = d2_target;
  451. return ret;
  452. }
  453. void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
  454. struct nfs4_slot *slot,
  455. struct nfs4_sequence_res *res)
  456. {
  457. u32 target_highest_slotid = min(res->sr_target_highest_slotid,
  458. NFS4_MAX_SLOTID);
  459. u32 highest_slotid = min(res->sr_highest_slotid, NFS4_MAX_SLOTID);
  460. spin_lock(&tbl->slot_tbl_lock);
  461. if (!nfs41_is_outlier_target_slotid(tbl, target_highest_slotid))
  462. nfs41_set_target_slotid_locked(tbl, target_highest_slotid);
  463. if (tbl->generation == slot->generation)
  464. nfs41_set_server_slotid_locked(tbl, highest_slotid);
  465. nfs41_set_max_slotid_locked(tbl, target_highest_slotid);
  466. spin_unlock(&tbl->slot_tbl_lock);
  467. }
  468. static void nfs4_release_session_slot_tables(struct nfs4_session *session)
  469. {
  470. nfs4_release_slot_table(&session->fc_slot_table);
  471. nfs4_release_slot_table(&session->bc_slot_table);
  472. }
  473. /*
  474. * Initialize or reset the forechannel and backchannel tables
  475. */
  476. int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
  477. {
  478. struct nfs4_slot_table *tbl;
  479. int status;
  480. dprintk("--> %s\n", __func__);
  481. /* Fore channel */
  482. tbl = &ses->fc_slot_table;
  483. tbl->session = ses;
  484. status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
  485. if (status || !(ses->flags & SESSION4_BACK_CHAN)) /* -ENOMEM */
  486. return status;
  487. /* Back channel */
  488. tbl = &ses->bc_slot_table;
  489. tbl->session = ses;
  490. status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
  491. if (status && tbl->slots == NULL)
  492. /* Fore and back channel share a connection so get
  493. * both slot tables or neither */
  494. nfs4_release_session_slot_tables(ses);
  495. return status;
  496. }
  497. struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
  498. {
  499. struct nfs4_session *session;
  500. session = kzalloc_obj(struct nfs4_session, GFP_NOFS);
  501. if (!session)
  502. return NULL;
  503. nfs4_init_slot_table(&session->fc_slot_table, "ForeChannel Slot table");
  504. nfs4_init_slot_table(&session->bc_slot_table, "BackChannel Slot table");
  505. session->session_state = 1<<NFS4_SESSION_INITING;
  506. session->clp = clp;
  507. return session;
  508. }
  509. static void nfs4_destroy_session_slot_tables(struct nfs4_session *session)
  510. {
  511. nfs4_shutdown_slot_table(&session->fc_slot_table);
  512. nfs4_shutdown_slot_table(&session->bc_slot_table);
  513. }
  514. void nfs4_destroy_session(struct nfs4_session *session)
  515. {
  516. struct rpc_xprt *xprt;
  517. const struct cred *cred;
  518. cred = nfs4_get_clid_cred(session->clp);
  519. nfs4_proc_destroy_session(session, cred);
  520. put_cred(cred);
  521. rcu_read_lock();
  522. xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt);
  523. rcu_read_unlock();
  524. dprintk("%s Destroy backchannel for xprt %p\n",
  525. __func__, xprt);
  526. xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
  527. nfs4_destroy_session_slot_tables(session);
  528. kfree(session);
  529. }
  530. /*
  531. * With sessions, the client is not marked ready until after a
  532. * successful EXCHANGE_ID and CREATE_SESSION.
  533. *
  534. * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
  535. * other versions of NFS can be tried.
  536. */
  537. static int nfs41_check_session_ready(struct nfs_client *clp)
  538. {
  539. int ret;
  540. if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
  541. ret = nfs4_client_recover_expired_lease(clp);
  542. if (ret)
  543. return ret;
  544. }
  545. if (clp->cl_cons_state < NFS_CS_READY)
  546. return -EPROTONOSUPPORT;
  547. smp_rmb();
  548. return 0;
  549. }
  550. int nfs4_init_session(struct nfs_client *clp)
  551. {
  552. if (!nfs4_has_session(clp))
  553. return 0;
  554. clear_bit(NFS4_SESSION_INITING, &clp->cl_session->session_state);
  555. return nfs41_check_session_ready(clp);
  556. }
  557. int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time)
  558. {
  559. struct nfs4_session *session = clp->cl_session;
  560. int ret;
  561. spin_lock(&clp->cl_lock);
  562. if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
  563. /*
  564. * Do not set NFS_CS_CHECK_LEASE_TIME instead set the
  565. * DS lease to be equal to the MDS lease.
  566. */
  567. clp->cl_lease_time = lease_time;
  568. clp->cl_last_renewal = jiffies;
  569. }
  570. spin_unlock(&clp->cl_lock);
  571. ret = nfs41_check_session_ready(clp);
  572. if (ret)
  573. return ret;
  574. /* Test for the DS role */
  575. if (!is_ds_client(clp))
  576. return -ENODEV;
  577. return 0;
  578. }
  579. EXPORT_SYMBOL_GPL(nfs4_init_ds_session);