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