1 /* 2 * Device operations for the pnfs nfs4 file layout driver. 3 * 4 * Copyright (c) 2002 5 * The Regents of the University of Michigan 6 * All Rights Reserved 7 * 8 * Dean Hildebrand <dhildebz@umich.edu> 9 * Garth Goodson <Garth.Goodson@netapp.com> 10 * 11 * Permission is granted to use, copy, create derivative works, and 12 * redistribute this software and such derivative works for any purpose, 13 * so long as the name of the University of Michigan is not used in 14 * any advertising or publicity pertaining to the use or distribution 15 * of this software without specific, written prior authorization. If 16 * the above copyright notice or any other identification of the 17 * University of Michigan is included in any copy of any portion of 18 * this software, then the disclaimer below must also be included. 19 * 20 * This software is provided as is, without representation or warranty 21 * of any kind either express or implied, including without limitation 22 * the implied warranties of merchantability, fitness for a particular 23 * purpose, or noninfringement. The Regents of the University of 24 * Michigan shall not be liable for any damages, including special, 25 * indirect, incidental, or consequential damages, with respect to any 26 * claim arising out of or in connection with the use of the software, 27 * even if it has been or is hereafter advised of the possibility of 28 * such damages. 29 */ 30 31 #include <linux/nfs_fs.h> 32 #include <linux/vmalloc.h> 33 #include <linux/module.h> 34 #include <linux/sunrpc/addr.h> 35 36 #include "../internal.h" 37 #include "../nfs4session.h" 38 #include "filelayout.h" 39 40 #define NFSDBG_FACILITY NFSDBG_PNFS_LD 41 42 static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO; 43 static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS; 44 45 /* 46 * Data server cache 47 * 48 * Data servers can be mapped to different device ids. 49 * nfs4_pnfs_ds reference counting 50 * - set to 1 on allocation 51 * - incremented when a device id maps a data server already in the cache. 52 * - decremented when deviceid is removed from the cache. 53 */ 54 static DEFINE_SPINLOCK(nfs4_ds_cache_lock); 55 static LIST_HEAD(nfs4_data_server_cache); 56 57 /* Debug routines */ 58 void 59 print_ds(struct nfs4_pnfs_ds *ds) 60 { 61 if (ds == NULL) { 62 printk("%s NULL device\n", __func__); 63 return; 64 } 65 printk(" ds %s\n" 66 " ref count %d\n" 67 " client %p\n" 68 " cl_exchange_flags %x\n", 69 ds->ds_remotestr, 70 atomic_read(&ds->ds_count), ds->ds_clp, 71 ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0); 72 } 73 74 static bool 75 same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2) 76 { 77 struct sockaddr_in *a, *b; 78 struct sockaddr_in6 *a6, *b6; 79 80 if (addr1->sa_family != addr2->sa_family) 81 return false; 82 83 switch (addr1->sa_family) { 84 case AF_INET: 85 a = (struct sockaddr_in *)addr1; 86 b = (struct sockaddr_in *)addr2; 87 88 if (a->sin_addr.s_addr == b->sin_addr.s_addr && 89 a->sin_port == b->sin_port) 90 return true; 91 break; 92 93 case AF_INET6: 94 a6 = (struct sockaddr_in6 *)addr1; 95 b6 = (struct sockaddr_in6 *)addr2; 96 97 /* LINKLOCAL addresses must have matching scope_id */ 98 if (ipv6_addr_src_scope(&a6->sin6_addr) == 99 IPV6_ADDR_SCOPE_LINKLOCAL && 100 a6->sin6_scope_id != b6->sin6_scope_id) 101 return false; 102 103 if (ipv6_addr_equal(&a6->sin6_addr, &b6->sin6_addr) && 104 a6->sin6_port == b6->sin6_port) 105 return true; 106 break; 107 108 default: 109 dprintk("%s: unhandled address family: %u\n", 110 __func__, addr1->sa_family); 111 return false; 112 } 113 114 return false; 115 } 116 117 static bool 118 _same_data_server_addrs_locked(const struct list_head *dsaddrs1, 119 const struct list_head *dsaddrs2) 120 { 121 struct nfs4_pnfs_ds_addr *da1, *da2; 122 123 /* step through both lists, comparing as we go */ 124 for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node), 125 da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node); 126 da1 != NULL && da2 != NULL; 127 da1 = list_entry(da1->da_node.next, typeof(*da1), da_node), 128 da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) { 129 if (!same_sockaddr((struct sockaddr *)&da1->da_addr, 130 (struct sockaddr *)&da2->da_addr)) 131 return false; 132 } 133 if (da1 == NULL && da2 == NULL) 134 return true; 135 136 return false; 137 } 138 139 /* 140 * Lookup DS by addresses. nfs4_ds_cache_lock is held 141 */ 142 static struct nfs4_pnfs_ds * 143 _data_server_lookup_locked(const struct list_head *dsaddrs) 144 { 145 struct nfs4_pnfs_ds *ds; 146 147 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) 148 if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) 149 return ds; 150 return NULL; 151 } 152 153 /* 154 * Create an rpc connection to the nfs4_pnfs_ds data server 155 * Currently only supports IPv4 and IPv6 addresses 156 */ 157 static int 158 nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds) 159 { 160 struct nfs_client *clp = ERR_PTR(-EIO); 161 struct nfs4_pnfs_ds_addr *da; 162 int status = 0; 163 164 dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, 165 mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor); 166 167 list_for_each_entry(da, &ds->ds_addrs, da_node) { 168 dprintk("%s: DS %s: trying address %s\n", 169 __func__, ds->ds_remotestr, da->da_remotestr); 170 171 clp = nfs4_set_ds_client(mds_srv->nfs_client, 172 (struct sockaddr *)&da->da_addr, 173 da->da_addrlen, IPPROTO_TCP, 174 dataserver_timeo, dataserver_retrans); 175 if (!IS_ERR(clp)) 176 break; 177 } 178 179 if (IS_ERR(clp)) { 180 status = PTR_ERR(clp); 181 goto out; 182 } 183 184 status = nfs4_init_ds_session(clp, mds_srv->nfs_client->cl_lease_time); 185 if (status) 186 goto out_put; 187 188 smp_wmb(); 189 ds->ds_clp = clp; 190 dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); 191 out: 192 return status; 193 out_put: 194 nfs_put_client(clp); 195 goto out; 196 } 197 198 static void 199 destroy_ds(struct nfs4_pnfs_ds *ds) 200 { 201 struct nfs4_pnfs_ds_addr *da; 202 203 dprintk("--> %s\n", __func__); 204 ifdebug(FACILITY) 205 print_ds(ds); 206 207 if (ds->ds_clp) 208 nfs_put_client(ds->ds_clp); 209 210 while (!list_empty(&ds->ds_addrs)) { 211 da = list_first_entry(&ds->ds_addrs, 212 struct nfs4_pnfs_ds_addr, 213 da_node); 214 list_del_init(&da->da_node); 215 kfree(da->da_remotestr); 216 kfree(da); 217 } 218 219 kfree(ds->ds_remotestr); 220 kfree(ds); 221 } 222 223 void 224 nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 225 { 226 struct nfs4_pnfs_ds *ds; 227 int i; 228 229 nfs4_print_deviceid(&dsaddr->id_node.deviceid); 230 231 for (i = 0; i < dsaddr->ds_num; i++) { 232 ds = dsaddr->ds_list[i]; 233 if (ds != NULL) { 234 if (atomic_dec_and_lock(&ds->ds_count, 235 &nfs4_ds_cache_lock)) { 236 list_del_init(&ds->ds_node); 237 spin_unlock(&nfs4_ds_cache_lock); 238 destroy_ds(ds); 239 } 240 } 241 } 242 kfree(dsaddr->stripe_indices); 243 kfree(dsaddr); 244 } 245 246 /* 247 * Create a string with a human readable address and port to avoid 248 * complicated setup around many dprinks. 249 */ 250 static char * 251 nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags) 252 { 253 struct nfs4_pnfs_ds_addr *da; 254 char *remotestr; 255 size_t len; 256 char *p; 257 258 len = 3; /* '{', '}' and eol */ 259 list_for_each_entry(da, dsaddrs, da_node) { 260 len += strlen(da->da_remotestr) + 1; /* string plus comma */ 261 } 262 263 remotestr = kzalloc(len, gfp_flags); 264 if (!remotestr) 265 return NULL; 266 267 p = remotestr; 268 *(p++) = '{'; 269 len--; 270 list_for_each_entry(da, dsaddrs, da_node) { 271 size_t ll = strlen(da->da_remotestr); 272 273 if (ll > len) 274 goto out_err; 275 276 memcpy(p, da->da_remotestr, ll); 277 p += ll; 278 len -= ll; 279 280 if (len < 1) 281 goto out_err; 282 (*p++) = ','; 283 len--; 284 } 285 if (len < 2) 286 goto out_err; 287 *(p++) = '}'; 288 *p = '\0'; 289 return remotestr; 290 out_err: 291 kfree(remotestr); 292 return NULL; 293 } 294 295 static struct nfs4_pnfs_ds * 296 nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) 297 { 298 struct nfs4_pnfs_ds *tmp_ds, *ds = NULL; 299 char *remotestr; 300 301 if (list_empty(dsaddrs)) { 302 dprintk("%s: no addresses defined\n", __func__); 303 goto out; 304 } 305 306 ds = kzalloc(sizeof(*ds), gfp_flags); 307 if (!ds) 308 goto out; 309 310 /* this is only used for debugging, so it's ok if its NULL */ 311 remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags); 312 313 spin_lock(&nfs4_ds_cache_lock); 314 tmp_ds = _data_server_lookup_locked(dsaddrs); 315 if (tmp_ds == NULL) { 316 INIT_LIST_HEAD(&ds->ds_addrs); 317 list_splice_init(dsaddrs, &ds->ds_addrs); 318 ds->ds_remotestr = remotestr; 319 atomic_set(&ds->ds_count, 1); 320 INIT_LIST_HEAD(&ds->ds_node); 321 ds->ds_clp = NULL; 322 list_add(&ds->ds_node, &nfs4_data_server_cache); 323 dprintk("%s add new data server %s\n", __func__, 324 ds->ds_remotestr); 325 } else { 326 kfree(remotestr); 327 kfree(ds); 328 atomic_inc(&tmp_ds->ds_count); 329 dprintk("%s data server %s found, inc'ed ds_count to %d\n", 330 __func__, tmp_ds->ds_remotestr, 331 atomic_read(&tmp_ds->ds_count)); 332 ds = tmp_ds; 333 } 334 spin_unlock(&nfs4_ds_cache_lock); 335 out: 336 return ds; 337 } 338 339 /* 340 * Currently only supports ipv4, ipv6 and one multi-path address. 341 */ 342 static struct nfs4_pnfs_ds_addr * 343 decode_ds_addr(struct net *net, struct xdr_stream *streamp, gfp_t gfp_flags) 344 { 345 struct nfs4_pnfs_ds_addr *da = NULL; 346 char *buf, *portstr; 347 __be16 port; 348 int nlen, rlen; 349 int tmp[2]; 350 __be32 *p; 351 char *netid, *match_netid; 352 size_t len, match_netid_len; 353 char *startsep = ""; 354 char *endsep = ""; 355 356 357 /* r_netid */ 358 p = xdr_inline_decode(streamp, 4); 359 if (unlikely(!p)) 360 goto out_err; 361 nlen = be32_to_cpup(p++); 362 363 p = xdr_inline_decode(streamp, nlen); 364 if (unlikely(!p)) 365 goto out_err; 366 367 netid = kmalloc(nlen+1, gfp_flags); 368 if (unlikely(!netid)) 369 goto out_err; 370 371 netid[nlen] = '\0'; 372 memcpy(netid, p, nlen); 373 374 /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */ 375 p = xdr_inline_decode(streamp, 4); 376 if (unlikely(!p)) 377 goto out_free_netid; 378 rlen = be32_to_cpup(p); 379 380 p = xdr_inline_decode(streamp, rlen); 381 if (unlikely(!p)) 382 goto out_free_netid; 383 384 /* port is ".ABC.DEF", 8 chars max */ 385 if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) { 386 dprintk("%s: Invalid address, length %d\n", __func__, 387 rlen); 388 goto out_free_netid; 389 } 390 buf = kmalloc(rlen + 1, gfp_flags); 391 if (!buf) { 392 dprintk("%s: Not enough memory\n", __func__); 393 goto out_free_netid; 394 } 395 buf[rlen] = '\0'; 396 memcpy(buf, p, rlen); 397 398 /* replace port '.' with '-' */ 399 portstr = strrchr(buf, '.'); 400 if (!portstr) { 401 dprintk("%s: Failed finding expected dot in port\n", 402 __func__); 403 goto out_free_buf; 404 } 405 *portstr = '-'; 406 407 /* find '.' between address and port */ 408 portstr = strrchr(buf, '.'); 409 if (!portstr) { 410 dprintk("%s: Failed finding expected dot between address and " 411 "port\n", __func__); 412 goto out_free_buf; 413 } 414 *portstr = '\0'; 415 416 da = kzalloc(sizeof(*da), gfp_flags); 417 if (unlikely(!da)) 418 goto out_free_buf; 419 420 INIT_LIST_HEAD(&da->da_node); 421 422 if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr, 423 sizeof(da->da_addr))) { 424 dprintk("%s: error parsing address %s\n", __func__, buf); 425 goto out_free_da; 426 } 427 428 portstr++; 429 sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]); 430 port = htons((tmp[0] << 8) | (tmp[1])); 431 432 switch (da->da_addr.ss_family) { 433 case AF_INET: 434 ((struct sockaddr_in *)&da->da_addr)->sin_port = port; 435 da->da_addrlen = sizeof(struct sockaddr_in); 436 match_netid = "tcp"; 437 match_netid_len = 3; 438 break; 439 440 case AF_INET6: 441 ((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port; 442 da->da_addrlen = sizeof(struct sockaddr_in6); 443 match_netid = "tcp6"; 444 match_netid_len = 4; 445 startsep = "["; 446 endsep = "]"; 447 break; 448 449 default: 450 dprintk("%s: unsupported address family: %u\n", 451 __func__, da->da_addr.ss_family); 452 goto out_free_da; 453 } 454 455 if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) { 456 dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n", 457 __func__, netid, match_netid); 458 goto out_free_da; 459 } 460 461 /* save human readable address */ 462 len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7; 463 da->da_remotestr = kzalloc(len, gfp_flags); 464 465 /* NULL is ok, only used for dprintk */ 466 if (da->da_remotestr) 467 snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep, 468 buf, endsep, ntohs(port)); 469 470 dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr); 471 kfree(buf); 472 kfree(netid); 473 return da; 474 475 out_free_da: 476 kfree(da); 477 out_free_buf: 478 dprintk("%s: Error parsing DS addr: %s\n", __func__, buf); 479 kfree(buf); 480 out_free_netid: 481 kfree(netid); 482 out_err: 483 return NULL; 484 } 485 486 /* Decode opaque device data and return the result */ 487 struct nfs4_file_layout_dsaddr * 488 nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, 489 gfp_t gfp_flags) 490 { 491 int i; 492 u32 cnt, num; 493 u8 *indexp; 494 __be32 *p; 495 u8 *stripe_indices; 496 u8 max_stripe_index; 497 struct nfs4_file_layout_dsaddr *dsaddr = NULL; 498 struct xdr_stream stream; 499 struct xdr_buf buf; 500 struct page *scratch; 501 struct list_head dsaddrs; 502 struct nfs4_pnfs_ds_addr *da; 503 504 /* set up xdr stream */ 505 scratch = alloc_page(gfp_flags); 506 if (!scratch) 507 goto out_err; 508 509 xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen); 510 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); 511 512 /* Get the stripe count (number of stripe index) */ 513 p = xdr_inline_decode(&stream, 4); 514 if (unlikely(!p)) 515 goto out_err_free_scratch; 516 517 cnt = be32_to_cpup(p); 518 dprintk("%s stripe count %d\n", __func__, cnt); 519 if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) { 520 printk(KERN_WARNING "NFS: %s: stripe count %d greater than " 521 "supported maximum %d\n", __func__, 522 cnt, NFS4_PNFS_MAX_STRIPE_CNT); 523 goto out_err_free_scratch; 524 } 525 526 /* read stripe indices */ 527 stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags); 528 if (!stripe_indices) 529 goto out_err_free_scratch; 530 531 p = xdr_inline_decode(&stream, cnt << 2); 532 if (unlikely(!p)) 533 goto out_err_free_stripe_indices; 534 535 indexp = &stripe_indices[0]; 536 max_stripe_index = 0; 537 for (i = 0; i < cnt; i++) { 538 *indexp = be32_to_cpup(p++); 539 max_stripe_index = max(max_stripe_index, *indexp); 540 indexp++; 541 } 542 543 /* Check the multipath list count */ 544 p = xdr_inline_decode(&stream, 4); 545 if (unlikely(!p)) 546 goto out_err_free_stripe_indices; 547 548 num = be32_to_cpup(p); 549 dprintk("%s ds_num %u\n", __func__, num); 550 if (num > NFS4_PNFS_MAX_MULTI_CNT) { 551 printk(KERN_WARNING "NFS: %s: multipath count %d greater than " 552 "supported maximum %d\n", __func__, 553 num, NFS4_PNFS_MAX_MULTI_CNT); 554 goto out_err_free_stripe_indices; 555 } 556 557 /* validate stripe indices are all < num */ 558 if (max_stripe_index >= num) { 559 printk(KERN_WARNING "NFS: %s: stripe index %u >= num ds %u\n", 560 __func__, max_stripe_index, num); 561 goto out_err_free_stripe_indices; 562 } 563 564 dsaddr = kzalloc(sizeof(*dsaddr) + 565 (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), 566 gfp_flags); 567 if (!dsaddr) 568 goto out_err_free_stripe_indices; 569 570 dsaddr->stripe_count = cnt; 571 dsaddr->stripe_indices = stripe_indices; 572 stripe_indices = NULL; 573 dsaddr->ds_num = num; 574 nfs4_init_deviceid_node(&dsaddr->id_node, server, &pdev->dev_id); 575 576 INIT_LIST_HEAD(&dsaddrs); 577 578 for (i = 0; i < dsaddr->ds_num; i++) { 579 int j; 580 u32 mp_count; 581 582 p = xdr_inline_decode(&stream, 4); 583 if (unlikely(!p)) 584 goto out_err_free_deviceid; 585 586 mp_count = be32_to_cpup(p); /* multipath count */ 587 for (j = 0; j < mp_count; j++) { 588 da = decode_ds_addr(server->nfs_client->cl_net, 589 &stream, gfp_flags); 590 if (da) 591 list_add_tail(&da->da_node, &dsaddrs); 592 } 593 if (list_empty(&dsaddrs)) { 594 dprintk("%s: no suitable DS addresses found\n", 595 __func__); 596 goto out_err_free_deviceid; 597 } 598 599 dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags); 600 if (!dsaddr->ds_list[i]) 601 goto out_err_drain_dsaddrs; 602 603 /* If DS was already in cache, free ds addrs */ 604 while (!list_empty(&dsaddrs)) { 605 da = list_first_entry(&dsaddrs, 606 struct nfs4_pnfs_ds_addr, 607 da_node); 608 list_del_init(&da->da_node); 609 kfree(da->da_remotestr); 610 kfree(da); 611 } 612 } 613 614 __free_page(scratch); 615 return dsaddr; 616 617 out_err_drain_dsaddrs: 618 while (!list_empty(&dsaddrs)) { 619 da = list_first_entry(&dsaddrs, struct nfs4_pnfs_ds_addr, 620 da_node); 621 list_del_init(&da->da_node); 622 kfree(da->da_remotestr); 623 kfree(da); 624 } 625 out_err_free_deviceid: 626 nfs4_fl_free_deviceid(dsaddr); 627 /* stripe_indicies was part of dsaddr */ 628 goto out_err_free_scratch; 629 out_err_free_stripe_indices: 630 kfree(stripe_indices); 631 out_err_free_scratch: 632 __free_page(scratch); 633 out_err: 634 dprintk("%s ERROR: returning NULL\n", __func__); 635 return NULL; 636 } 637 638 void 639 nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 640 { 641 nfs4_put_deviceid_node(&dsaddr->id_node); 642 } 643 644 /* 645 * Want res = (offset - layout->pattern_offset)/ layout->stripe_unit 646 * Then: ((res + fsi) % dsaddr->stripe_count) 647 */ 648 u32 649 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset) 650 { 651 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); 652 u64 tmp; 653 654 tmp = offset - flseg->pattern_offset; 655 do_div(tmp, flseg->stripe_unit); 656 tmp += flseg->first_stripe_index; 657 return do_div(tmp, flseg->dsaddr->stripe_count); 658 } 659 660 u32 661 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j) 662 { 663 return FILELAYOUT_LSEG(lseg)->dsaddr->stripe_indices[j]; 664 } 665 666 struct nfs_fh * 667 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j) 668 { 669 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); 670 u32 i; 671 672 if (flseg->stripe_type == STRIPE_SPARSE) { 673 if (flseg->num_fh == 1) 674 i = 0; 675 else if (flseg->num_fh == 0) 676 /* Use the MDS OPEN fh set in nfs_read_rpcsetup */ 677 return NULL; 678 else 679 i = nfs4_fl_calc_ds_index(lseg, j); 680 } else 681 i = j; 682 return flseg->fh_array[i]; 683 } 684 685 static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) 686 { 687 might_sleep(); 688 wait_on_bit_action(&ds->ds_state, NFS4DS_CONNECTING, 689 nfs_wait_bit_killable, TASK_KILLABLE); 690 } 691 692 static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds) 693 { 694 smp_mb__before_atomic(); 695 clear_bit(NFS4DS_CONNECTING, &ds->ds_state); 696 smp_mb__after_atomic(); 697 wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING); 698 } 699 700 701 struct nfs4_pnfs_ds * 702 nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) 703 { 704 struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; 705 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; 706 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); 707 struct nfs4_pnfs_ds *ret = ds; 708 709 if (ds == NULL) { 710 printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", 711 __func__, ds_idx); 712 filelayout_mark_devid_invalid(devid); 713 goto out; 714 } 715 smp_rmb(); 716 if (ds->ds_clp) 717 goto out_test_devid; 718 719 if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { 720 struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); 721 int err; 722 723 err = nfs4_ds_connect(s, ds); 724 if (err) 725 nfs4_mark_deviceid_unavailable(devid); 726 nfs4_clear_ds_conn_bit(ds); 727 } else { 728 /* Either ds is connected, or ds is NULL */ 729 nfs4_wait_ds_connect(ds); 730 } 731 out_test_devid: 732 if (filelayout_test_devid_unavailable(devid)) 733 ret = NULL; 734 out: 735 return ret; 736 } 737 738 module_param(dataserver_retrans, uint, 0644); 739 MODULE_PARM_DESC(dataserver_retrans, "The number of times the NFSv4.1 client " 740 "retries a request before it attempts further " 741 " recovery action."); 742 module_param(dataserver_timeo, uint, 0644); 743 MODULE_PARM_DESC(dataserver_timeo, "The time (in tenths of a second) the " 744 "NFSv4.1 client waits for a response from a " 745 " data server before it retries an NFS request."); 746