root/fs/nfs/pnfs_nfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pnfs_generic_rw_release
  2. pnfs_generic_prepare_to_resend_writes
  3. pnfs_generic_write_commit_done
  4. pnfs_generic_commit_release
  5. pnfs_generic_clear_request_commit
  6. pnfs_generic_scan_ds_commit_list
  7. pnfs_generic_scan_commit_lists
  8. pnfs_generic_recover_commit_reqs
  9. pnfs_generic_retry_commit
  10. pnfs_generic_alloc_ds_commits
  11. pnfs_fetch_commit_bucket_list
  12. pnfs_generic_commit_cancel_empty_pagelist
  13. pnfs_generic_commit_pagelist
  14. print_ds
  15. same_sockaddr
  16. _same_data_server_addrs_locked
  17. _data_server_lookup_locked
  18. destroy_ds
  19. nfs4_pnfs_ds_put
  20. nfs4_pnfs_remotestr
  21. nfs4_pnfs_ds_add
  22. nfs4_wait_ds_connect
  23. nfs4_clear_ds_conn_bit
  24. load_v3_ds_connect
  25. nfs4_pnfs_v3_ds_connect_unload
  26. _nfs4_pnfs_v3_ds_connect
  27. _nfs4_pnfs_v4_ds_connect
  28. nfs4_pnfs_ds_connect
  29. nfs4_decode_mp_ds_addr
  30. pnfs_layout_mark_request_commit
  31. pnfs_nfs_generic_sync

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Common NFS I/O  operations for the pnfs file based
   4  * layout drivers.
   5  *
   6  * Copyright (c) 2014, Primary Data, Inc. All rights reserved.
   7  *
   8  * Tom Haynes <loghyr@primarydata.com>
   9  */
  10 
  11 #include <linux/nfs_fs.h>
  12 #include <linux/nfs_page.h>
  13 #include <linux/sunrpc/addr.h>
  14 #include <linux/module.h>
  15 
  16 #include "nfs4session.h"
  17 #include "internal.h"
  18 #include "pnfs.h"
  19 
  20 #define NFSDBG_FACILITY         NFSDBG_PNFS
  21 
  22 void pnfs_generic_rw_release(void *data)
  23 {
  24         struct nfs_pgio_header *hdr = data;
  25 
  26         nfs_put_client(hdr->ds_clp);
  27         hdr->mds_ops->rpc_release(data);
  28 }
  29 EXPORT_SYMBOL_GPL(pnfs_generic_rw_release);
  30 
  31 /* Fake up some data that will cause nfs_commit_release to retry the writes. */
  32 void pnfs_generic_prepare_to_resend_writes(struct nfs_commit_data *data)
  33 {
  34         struct nfs_writeverf *verf = data->res.verf;
  35 
  36         data->task.tk_status = 0;
  37         memset(&verf->verifier, 0, sizeof(verf->verifier));
  38         verf->committed = NFS_UNSTABLE;
  39 }
  40 EXPORT_SYMBOL_GPL(pnfs_generic_prepare_to_resend_writes);
  41 
  42 void pnfs_generic_write_commit_done(struct rpc_task *task, void *data)
  43 {
  44         struct nfs_commit_data *wdata = data;
  45 
  46         /* Note this may cause RPC to be resent */
  47         wdata->mds_ops->rpc_call_done(task, data);
  48 }
  49 EXPORT_SYMBOL_GPL(pnfs_generic_write_commit_done);
  50 
  51 void pnfs_generic_commit_release(void *calldata)
  52 {
  53         struct nfs_commit_data *data = calldata;
  54 
  55         data->completion_ops->completion(data);
  56         pnfs_put_lseg(data->lseg);
  57         nfs_put_client(data->ds_clp);
  58         nfs_commitdata_release(data);
  59 }
  60 EXPORT_SYMBOL_GPL(pnfs_generic_commit_release);
  61 
  62 /* The generic layer is about to remove the req from the commit list.
  63  * If this will make the bucket empty, it will need to put the lseg reference.
  64  * Note this must be called holding nfsi->commit_mutex
  65  */
  66 void
  67 pnfs_generic_clear_request_commit(struct nfs_page *req,
  68                                   struct nfs_commit_info *cinfo)
  69 {
  70         struct pnfs_layout_segment *freeme = NULL;
  71 
  72         if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
  73                 goto out;
  74         cinfo->ds->nwritten--;
  75         if (list_is_singular(&req->wb_list)) {
  76                 struct pnfs_commit_bucket *bucket;
  77 
  78                 bucket = list_first_entry(&req->wb_list,
  79                                           struct pnfs_commit_bucket,
  80                                           written);
  81                 freeme = bucket->wlseg;
  82                 bucket->wlseg = NULL;
  83         }
  84 out:
  85         nfs_request_remove_commit_list(req, cinfo);
  86         pnfs_put_lseg(freeme);
  87 }
  88 EXPORT_SYMBOL_GPL(pnfs_generic_clear_request_commit);
  89 
  90 static int
  91 pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
  92                                  struct nfs_commit_info *cinfo,
  93                                  int max)
  94 {
  95         struct list_head *src = &bucket->written;
  96         struct list_head *dst = &bucket->committing;
  97         int ret;
  98 
  99         lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
 100         ret = nfs_scan_commit_list(src, dst, cinfo, max);
 101         if (ret) {
 102                 cinfo->ds->nwritten -= ret;
 103                 cinfo->ds->ncommitting += ret;
 104                 if (bucket->clseg == NULL)
 105                         bucket->clseg = pnfs_get_lseg(bucket->wlseg);
 106                 if (list_empty(src)) {
 107                         pnfs_put_lseg(bucket->wlseg);
 108                         bucket->wlseg = NULL;
 109                 }
 110         }
 111         return ret;
 112 }
 113 
 114 /* Move reqs from written to committing lists, returning count
 115  * of number moved.
 116  */
 117 int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
 118                                    int max)
 119 {
 120         int i, rv = 0, cnt;
 121 
 122         lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
 123         for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
 124                 cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i],
 125                                                        cinfo, max);
 126                 max -= cnt;
 127                 rv += cnt;
 128         }
 129         return rv;
 130 }
 131 EXPORT_SYMBOL_GPL(pnfs_generic_scan_commit_lists);
 132 
 133 /* Pull everything off the committing lists and dump into @dst.  */
 134 void pnfs_generic_recover_commit_reqs(struct list_head *dst,
 135                                       struct nfs_commit_info *cinfo)
 136 {
 137         struct pnfs_commit_bucket *b;
 138         struct pnfs_layout_segment *freeme;
 139         int nwritten;
 140         int i;
 141 
 142         lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
 143 restart:
 144         for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
 145                 nwritten = nfs_scan_commit_list(&b->written, dst, cinfo, 0);
 146                 if (!nwritten)
 147                         continue;
 148                 cinfo->ds->nwritten -= nwritten;
 149                 if (list_empty(&b->written)) {
 150                         freeme = b->wlseg;
 151                         b->wlseg = NULL;
 152                         pnfs_put_lseg(freeme);
 153                         goto restart;
 154                 }
 155         }
 156 }
 157 EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs);
 158 
 159 static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx)
 160 {
 161         struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
 162         struct pnfs_commit_bucket *bucket;
 163         struct pnfs_layout_segment *freeme;
 164         struct list_head *pos;
 165         LIST_HEAD(pages);
 166         int i;
 167 
 168         mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
 169         for (i = idx; i < fl_cinfo->nbuckets; i++) {
 170                 bucket = &fl_cinfo->buckets[i];
 171                 if (list_empty(&bucket->committing))
 172                         continue;
 173                 freeme = bucket->clseg;
 174                 bucket->clseg = NULL;
 175                 list_for_each(pos, &bucket->committing)
 176                         cinfo->ds->ncommitting--;
 177                 list_splice_init(&bucket->committing, &pages);
 178                 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 179                 nfs_retry_commit(&pages, freeme, cinfo, i);
 180                 pnfs_put_lseg(freeme);
 181                 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
 182         }
 183         mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 184 }
 185 
 186 static unsigned int
 187 pnfs_generic_alloc_ds_commits(struct nfs_commit_info *cinfo,
 188                               struct list_head *list)
 189 {
 190         struct pnfs_ds_commit_info *fl_cinfo;
 191         struct pnfs_commit_bucket *bucket;
 192         struct nfs_commit_data *data;
 193         int i;
 194         unsigned int nreq = 0;
 195 
 196         fl_cinfo = cinfo->ds;
 197         bucket = fl_cinfo->buckets;
 198         for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) {
 199                 if (list_empty(&bucket->committing))
 200                         continue;
 201                 data = nfs_commitdata_alloc(false);
 202                 if (!data)
 203                         break;
 204                 data->ds_commit_index = i;
 205                 list_add(&data->pages, list);
 206                 nreq++;
 207         }
 208 
 209         /* Clean up on error */
 210         pnfs_generic_retry_commit(cinfo, i);
 211         return nreq;
 212 }
 213 
 214 static inline
 215 void pnfs_fetch_commit_bucket_list(struct list_head *pages,
 216                 struct nfs_commit_data *data,
 217                 struct nfs_commit_info *cinfo)
 218 {
 219         struct pnfs_commit_bucket *bucket;
 220         struct list_head *pos;
 221 
 222         bucket = &cinfo->ds->buckets[data->ds_commit_index];
 223         mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
 224         list_for_each(pos, &bucket->committing)
 225                 cinfo->ds->ncommitting--;
 226         list_splice_init(&bucket->committing, pages);
 227         data->lseg = bucket->clseg;
 228         bucket->clseg = NULL;
 229         mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 230 
 231 }
 232 
 233 /* Helper function for pnfs_generic_commit_pagelist to catch an empty
 234  * page list. This can happen when two commits race.
 235  *
 236  * This must be called instead of nfs_init_commit - call one or the other, but
 237  * not both!
 238  */
 239 static bool
 240 pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
 241                                           struct nfs_commit_data *data,
 242                                           struct nfs_commit_info *cinfo)
 243 {
 244         if (list_empty(pages)) {
 245                 if (atomic_dec_and_test(&cinfo->mds->rpcs_out))
 246                         wake_up_var(&cinfo->mds->rpcs_out);
 247                 /* don't call nfs_commitdata_release - it tries to put
 248                  * the open_context which is not acquired until nfs_init_commit
 249                  * which has not been called on @data */
 250                 WARN_ON_ONCE(data->context);
 251                 nfs_commit_free(data);
 252                 return true;
 253         }
 254 
 255         return false;
 256 }
 257 
 258 /* This follows nfs_commit_list pretty closely */
 259 int
 260 pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
 261                              int how, struct nfs_commit_info *cinfo,
 262                              int (*initiate_commit)(struct nfs_commit_data *data,
 263                                                     int how))
 264 {
 265         struct nfs_commit_data *data, *tmp;
 266         LIST_HEAD(list);
 267         unsigned int nreq = 0;
 268 
 269         if (!list_empty(mds_pages)) {
 270                 data = nfs_commitdata_alloc(true);
 271                 data->ds_commit_index = -1;
 272                 list_add(&data->pages, &list);
 273                 nreq++;
 274         }
 275 
 276         nreq += pnfs_generic_alloc_ds_commits(cinfo, &list);
 277 
 278         if (nreq == 0)
 279                 goto out;
 280 
 281         atomic_add(nreq, &cinfo->mds->rpcs_out);
 282 
 283         list_for_each_entry_safe(data, tmp, &list, pages) {
 284                 list_del_init(&data->pages);
 285                 if (data->ds_commit_index < 0) {
 286                         /* another commit raced with us */
 287                         if (pnfs_generic_commit_cancel_empty_pagelist(mds_pages,
 288                                 data, cinfo))
 289                                 continue;
 290 
 291                         nfs_init_commit(data, mds_pages, NULL, cinfo);
 292                         nfs_initiate_commit(NFS_CLIENT(inode), data,
 293                                             NFS_PROTO(data->inode),
 294                                             data->mds_ops, how, 0);
 295                 } else {
 296                         LIST_HEAD(pages);
 297 
 298                         pnfs_fetch_commit_bucket_list(&pages, data, cinfo);
 299 
 300                         /* another commit raced with us */
 301                         if (pnfs_generic_commit_cancel_empty_pagelist(&pages,
 302                                 data, cinfo))
 303                                 continue;
 304 
 305                         nfs_init_commit(data, &pages, data->lseg, cinfo);
 306                         initiate_commit(data, how);
 307                 }
 308         }
 309 out:
 310         return PNFS_ATTEMPTED;
 311 }
 312 EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist);
 313 
 314 /*
 315  * Data server cache
 316  *
 317  * Data servers can be mapped to different device ids.
 318  * nfs4_pnfs_ds reference counting
 319  *   - set to 1 on allocation
 320  *   - incremented when a device id maps a data server already in the cache.
 321  *   - decremented when deviceid is removed from the cache.
 322  */
 323 static DEFINE_SPINLOCK(nfs4_ds_cache_lock);
 324 static LIST_HEAD(nfs4_data_server_cache);
 325 
 326 /* Debug routines */
 327 static void
 328 print_ds(struct nfs4_pnfs_ds *ds)
 329 {
 330         if (ds == NULL) {
 331                 printk(KERN_WARNING "%s NULL device\n", __func__);
 332                 return;
 333         }
 334         printk(KERN_WARNING "        ds %s\n"
 335                 "        ref count %d\n"
 336                 "        client %p\n"
 337                 "        cl_exchange_flags %x\n",
 338                 ds->ds_remotestr,
 339                 refcount_read(&ds->ds_count), ds->ds_clp,
 340                 ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
 341 }
 342 
 343 static bool
 344 same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
 345 {
 346         struct sockaddr_in *a, *b;
 347         struct sockaddr_in6 *a6, *b6;
 348 
 349         if (addr1->sa_family != addr2->sa_family)
 350                 return false;
 351 
 352         switch (addr1->sa_family) {
 353         case AF_INET:
 354                 a = (struct sockaddr_in *)addr1;
 355                 b = (struct sockaddr_in *)addr2;
 356 
 357                 if (a->sin_addr.s_addr == b->sin_addr.s_addr &&
 358                     a->sin_port == b->sin_port)
 359                         return true;
 360                 break;
 361 
 362         case AF_INET6:
 363                 a6 = (struct sockaddr_in6 *)addr1;
 364                 b6 = (struct sockaddr_in6 *)addr2;
 365 
 366                 /* LINKLOCAL addresses must have matching scope_id */
 367                 if (ipv6_addr_src_scope(&a6->sin6_addr) ==
 368                     IPV6_ADDR_SCOPE_LINKLOCAL &&
 369                     a6->sin6_scope_id != b6->sin6_scope_id)
 370                         return false;
 371 
 372                 if (ipv6_addr_equal(&a6->sin6_addr, &b6->sin6_addr) &&
 373                     a6->sin6_port == b6->sin6_port)
 374                         return true;
 375                 break;
 376 
 377         default:
 378                 dprintk("%s: unhandled address family: %u\n",
 379                         __func__, addr1->sa_family);
 380                 return false;
 381         }
 382 
 383         return false;
 384 }
 385 
 386 /*
 387  * Checks if 'dsaddrs1' contains a subset of 'dsaddrs2'. If it does,
 388  * declare a match.
 389  */
 390 static bool
 391 _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
 392                                const struct list_head *dsaddrs2)
 393 {
 394         struct nfs4_pnfs_ds_addr *da1, *da2;
 395         struct sockaddr *sa1, *sa2;
 396         bool match = false;
 397 
 398         list_for_each_entry(da1, dsaddrs1, da_node) {
 399                 sa1 = (struct sockaddr *)&da1->da_addr;
 400                 match = false;
 401                 list_for_each_entry(da2, dsaddrs2, da_node) {
 402                         sa2 = (struct sockaddr *)&da2->da_addr;
 403                         match = same_sockaddr(sa1, sa2);
 404                         if (match)
 405                                 break;
 406                 }
 407                 if (!match)
 408                         break;
 409         }
 410         return match;
 411 }
 412 
 413 /*
 414  * Lookup DS by addresses.  nfs4_ds_cache_lock is held
 415  */
 416 static struct nfs4_pnfs_ds *
 417 _data_server_lookup_locked(const struct list_head *dsaddrs)
 418 {
 419         struct nfs4_pnfs_ds *ds;
 420 
 421         list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
 422                 if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
 423                         return ds;
 424         return NULL;
 425 }
 426 
 427 static void destroy_ds(struct nfs4_pnfs_ds *ds)
 428 {
 429         struct nfs4_pnfs_ds_addr *da;
 430 
 431         dprintk("--> %s\n", __func__);
 432         ifdebug(FACILITY)
 433                 print_ds(ds);
 434 
 435         nfs_put_client(ds->ds_clp);
 436 
 437         while (!list_empty(&ds->ds_addrs)) {
 438                 da = list_first_entry(&ds->ds_addrs,
 439                                       struct nfs4_pnfs_ds_addr,
 440                                       da_node);
 441                 list_del_init(&da->da_node);
 442                 kfree(da->da_remotestr);
 443                 kfree(da);
 444         }
 445 
 446         kfree(ds->ds_remotestr);
 447         kfree(ds);
 448 }
 449 
 450 void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds)
 451 {
 452         if (refcount_dec_and_lock(&ds->ds_count,
 453                                 &nfs4_ds_cache_lock)) {
 454                 list_del_init(&ds->ds_node);
 455                 spin_unlock(&nfs4_ds_cache_lock);
 456                 destroy_ds(ds);
 457         }
 458 }
 459 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_put);
 460 
 461 /*
 462  * Create a string with a human readable address and port to avoid
 463  * complicated setup around many dprinks.
 464  */
 465 static char *
 466 nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)
 467 {
 468         struct nfs4_pnfs_ds_addr *da;
 469         char *remotestr;
 470         size_t len;
 471         char *p;
 472 
 473         len = 3;        /* '{', '}' and eol */
 474         list_for_each_entry(da, dsaddrs, da_node) {
 475                 len += strlen(da->da_remotestr) + 1;    /* string plus comma */
 476         }
 477 
 478         remotestr = kzalloc(len, gfp_flags);
 479         if (!remotestr)
 480                 return NULL;
 481 
 482         p = remotestr;
 483         *(p++) = '{';
 484         len--;
 485         list_for_each_entry(da, dsaddrs, da_node) {
 486                 size_t ll = strlen(da->da_remotestr);
 487 
 488                 if (ll > len)
 489                         goto out_err;
 490 
 491                 memcpy(p, da->da_remotestr, ll);
 492                 p += ll;
 493                 len -= ll;
 494 
 495                 if (len < 1)
 496                         goto out_err;
 497                 (*p++) = ',';
 498                 len--;
 499         }
 500         if (len < 2)
 501                 goto out_err;
 502         *(p++) = '}';
 503         *p = '\0';
 504         return remotestr;
 505 out_err:
 506         kfree(remotestr);
 507         return NULL;
 508 }
 509 
 510 /*
 511  * Given a list of multipath struct nfs4_pnfs_ds_addr, add it to ds cache if
 512  * uncached and return cached struct nfs4_pnfs_ds.
 513  */
 514 struct nfs4_pnfs_ds *
 515 nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
 516 {
 517         struct nfs4_pnfs_ds *tmp_ds, *ds = NULL;
 518         char *remotestr;
 519 
 520         if (list_empty(dsaddrs)) {
 521                 dprintk("%s: no addresses defined\n", __func__);
 522                 goto out;
 523         }
 524 
 525         ds = kzalloc(sizeof(*ds), gfp_flags);
 526         if (!ds)
 527                 goto out;
 528 
 529         /* this is only used for debugging, so it's ok if its NULL */
 530         remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags);
 531 
 532         spin_lock(&nfs4_ds_cache_lock);
 533         tmp_ds = _data_server_lookup_locked(dsaddrs);
 534         if (tmp_ds == NULL) {
 535                 INIT_LIST_HEAD(&ds->ds_addrs);
 536                 list_splice_init(dsaddrs, &ds->ds_addrs);
 537                 ds->ds_remotestr = remotestr;
 538                 refcount_set(&ds->ds_count, 1);
 539                 INIT_LIST_HEAD(&ds->ds_node);
 540                 ds->ds_clp = NULL;
 541                 list_add(&ds->ds_node, &nfs4_data_server_cache);
 542                 dprintk("%s add new data server %s\n", __func__,
 543                         ds->ds_remotestr);
 544         } else {
 545                 kfree(remotestr);
 546                 kfree(ds);
 547                 refcount_inc(&tmp_ds->ds_count);
 548                 dprintk("%s data server %s found, inc'ed ds_count to %d\n",
 549                         __func__, tmp_ds->ds_remotestr,
 550                         refcount_read(&tmp_ds->ds_count));
 551                 ds = tmp_ds;
 552         }
 553         spin_unlock(&nfs4_ds_cache_lock);
 554 out:
 555         return ds;
 556 }
 557 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add);
 558 
 559 static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
 560 {
 561         might_sleep();
 562         wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING,
 563                         TASK_KILLABLE);
 564 }
 565 
 566 static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
 567 {
 568         smp_mb__before_atomic();
 569         clear_bit(NFS4DS_CONNECTING, &ds->ds_state);
 570         smp_mb__after_atomic();
 571         wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
 572 }
 573 
 574 static struct nfs_client *(*get_v3_ds_connect)(
 575                         struct nfs_server *mds_srv,
 576                         const struct sockaddr *ds_addr,
 577                         int ds_addrlen,
 578                         int ds_proto,
 579                         unsigned int ds_timeo,
 580                         unsigned int ds_retrans);
 581 
 582 static bool load_v3_ds_connect(void)
 583 {
 584         if (!get_v3_ds_connect) {
 585                 get_v3_ds_connect = symbol_request(nfs3_set_ds_client);
 586                 WARN_ON_ONCE(!get_v3_ds_connect);
 587         }
 588 
 589         return(get_v3_ds_connect != NULL);
 590 }
 591 
 592 void nfs4_pnfs_v3_ds_connect_unload(void)
 593 {
 594         if (get_v3_ds_connect) {
 595                 symbol_put(nfs3_set_ds_client);
 596                 get_v3_ds_connect = NULL;
 597         }
 598 }
 599 
 600 static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
 601                                  struct nfs4_pnfs_ds *ds,
 602                                  unsigned int timeo,
 603                                  unsigned int retrans)
 604 {
 605         struct nfs_client *clp = ERR_PTR(-EIO);
 606         struct nfs4_pnfs_ds_addr *da;
 607         int status = 0;
 608 
 609         dprintk("--> %s DS %s\n", __func__, ds->ds_remotestr);
 610 
 611         if (!load_v3_ds_connect())
 612                 goto out;
 613 
 614         list_for_each_entry(da, &ds->ds_addrs, da_node) {
 615                 dprintk("%s: DS %s: trying address %s\n",
 616                         __func__, ds->ds_remotestr, da->da_remotestr);
 617 
 618                 if (!IS_ERR(clp)) {
 619                         struct xprt_create xprt_args = {
 620                                 .ident = XPRT_TRANSPORT_TCP,
 621                                 .net = clp->cl_net,
 622                                 .dstaddr = (struct sockaddr *)&da->da_addr,
 623                                 .addrlen = da->da_addrlen,
 624                                 .servername = clp->cl_hostname,
 625                         };
 626                         /* Add this address as an alias */
 627                         rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
 628                                         rpc_clnt_test_and_add_xprt, NULL);
 629                         continue;
 630                 }
 631                 clp = get_v3_ds_connect(mds_srv,
 632                                 (struct sockaddr *)&da->da_addr,
 633                                 da->da_addrlen, IPPROTO_TCP,
 634                                 timeo, retrans);
 635                 if (IS_ERR(clp))
 636                         continue;
 637                 clp->cl_rpcclient->cl_softerr = 0;
 638                 clp->cl_rpcclient->cl_softrtry = 0;
 639         }
 640 
 641         if (IS_ERR(clp)) {
 642                 status = PTR_ERR(clp);
 643                 goto out;
 644         }
 645 
 646         smp_wmb();
 647         ds->ds_clp = clp;
 648         dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
 649 out:
 650         return status;
 651 }
 652 
 653 static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
 654                                  struct nfs4_pnfs_ds *ds,
 655                                  unsigned int timeo,
 656                                  unsigned int retrans,
 657                                  u32 minor_version)
 658 {
 659         struct nfs_client *clp = ERR_PTR(-EIO);
 660         struct nfs4_pnfs_ds_addr *da;
 661         int status = 0;
 662 
 663         dprintk("--> %s DS %s\n", __func__, ds->ds_remotestr);
 664 
 665         list_for_each_entry(da, &ds->ds_addrs, da_node) {
 666                 dprintk("%s: DS %s: trying address %s\n",
 667                         __func__, ds->ds_remotestr, da->da_remotestr);
 668 
 669                 if (!IS_ERR(clp) && clp->cl_mvops->session_trunk) {
 670                         struct xprt_create xprt_args = {
 671                                 .ident = XPRT_TRANSPORT_TCP,
 672                                 .net = clp->cl_net,
 673                                 .dstaddr = (struct sockaddr *)&da->da_addr,
 674                                 .addrlen = da->da_addrlen,
 675                                 .servername = clp->cl_hostname,
 676                         };
 677                         struct nfs4_add_xprt_data xprtdata = {
 678                                 .clp = clp,
 679                                 .cred = nfs4_get_clid_cred(clp),
 680                         };
 681                         struct rpc_add_xprt_test rpcdata = {
 682                                 .add_xprt_test = clp->cl_mvops->session_trunk,
 683                                 .data = &xprtdata,
 684                         };
 685 
 686                         /**
 687                         * Test this address for session trunking and
 688                         * add as an alias
 689                         */
 690                         rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
 691                                           rpc_clnt_setup_test_and_add_xprt,
 692                                           &rpcdata);
 693                         if (xprtdata.cred)
 694                                 put_cred(xprtdata.cred);
 695                 } else {
 696                         clp = nfs4_set_ds_client(mds_srv,
 697                                                 (struct sockaddr *)&da->da_addr,
 698                                                 da->da_addrlen, IPPROTO_TCP,
 699                                                 timeo, retrans, minor_version);
 700                         if (IS_ERR(clp))
 701                                 continue;
 702 
 703                         status = nfs4_init_ds_session(clp,
 704                                         mds_srv->nfs_client->cl_lease_time);
 705                         if (status) {
 706                                 nfs_put_client(clp);
 707                                 clp = ERR_PTR(-EIO);
 708                                 continue;
 709                         }
 710 
 711                 }
 712         }
 713 
 714         if (IS_ERR(clp)) {
 715                 status = PTR_ERR(clp);
 716                 goto out;
 717         }
 718 
 719         smp_wmb();
 720         ds->ds_clp = clp;
 721         dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
 722 out:
 723         return status;
 724 }
 725 
 726 /*
 727  * Create an rpc connection to the nfs4_pnfs_ds data server.
 728  * Currently only supports IPv4 and IPv6 addresses.
 729  * If connection fails, make devid unavailable and return a -errno.
 730  */
 731 int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
 732                           struct nfs4_deviceid_node *devid, unsigned int timeo,
 733                           unsigned int retrans, u32 version, u32 minor_version)
 734 {
 735         int err;
 736 
 737 again:
 738         err = 0;
 739         if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
 740                 if (version == 3) {
 741                         err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
 742                                                        retrans);
 743                 } else if (version == 4) {
 744                         err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo,
 745                                                        retrans, minor_version);
 746                 } else {
 747                         dprintk("%s: unsupported DS version %d\n", __func__,
 748                                 version);
 749                         err = -EPROTONOSUPPORT;
 750                 }
 751 
 752                 nfs4_clear_ds_conn_bit(ds);
 753         } else {
 754                 nfs4_wait_ds_connect(ds);
 755 
 756                 /* what was waited on didn't connect AND didn't mark unavail */
 757                 if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid))
 758                         goto again;
 759         }
 760 
 761         /*
 762          * At this point the ds->ds_clp should be ready, but it might have
 763          * hit an error.
 764          */
 765         if (!err) {
 766                 if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) {
 767                         WARN_ON_ONCE(ds->ds_clp ||
 768                                 !nfs4_test_deviceid_unavailable(devid));
 769                         return -EINVAL;
 770                 }
 771                 err = nfs_client_init_status(ds->ds_clp);
 772         }
 773 
 774         return err;
 775 }
 776 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
 777 
 778 /*
 779  * Currently only supports ipv4, ipv6 and one multi-path address.
 780  */
 781 struct nfs4_pnfs_ds_addr *
 782 nfs4_decode_mp_ds_addr(struct net *net, struct xdr_stream *xdr, gfp_t gfp_flags)
 783 {
 784         struct nfs4_pnfs_ds_addr *da = NULL;
 785         char *buf, *portstr;
 786         __be16 port;
 787         int nlen, rlen;
 788         int tmp[2];
 789         __be32 *p;
 790         char *netid, *match_netid;
 791         size_t len, match_netid_len;
 792         char *startsep = "";
 793         char *endsep = "";
 794 
 795 
 796         /* r_netid */
 797         p = xdr_inline_decode(xdr, 4);
 798         if (unlikely(!p))
 799                 goto out_err;
 800         nlen = be32_to_cpup(p++);
 801 
 802         p = xdr_inline_decode(xdr, nlen);
 803         if (unlikely(!p))
 804                 goto out_err;
 805 
 806         netid = kmalloc(nlen+1, gfp_flags);
 807         if (unlikely(!netid))
 808                 goto out_err;
 809 
 810         netid[nlen] = '\0';
 811         memcpy(netid, p, nlen);
 812 
 813         /* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
 814         p = xdr_inline_decode(xdr, 4);
 815         if (unlikely(!p))
 816                 goto out_free_netid;
 817         rlen = be32_to_cpup(p);
 818 
 819         p = xdr_inline_decode(xdr, rlen);
 820         if (unlikely(!p))
 821                 goto out_free_netid;
 822 
 823         /* port is ".ABC.DEF", 8 chars max */
 824         if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) {
 825                 dprintk("%s: Invalid address, length %d\n", __func__,
 826                         rlen);
 827                 goto out_free_netid;
 828         }
 829         buf = kmalloc(rlen + 1, gfp_flags);
 830         if (!buf) {
 831                 dprintk("%s: Not enough memory\n", __func__);
 832                 goto out_free_netid;
 833         }
 834         buf[rlen] = '\0';
 835         memcpy(buf, p, rlen);
 836 
 837         /* replace port '.' with '-' */
 838         portstr = strrchr(buf, '.');
 839         if (!portstr) {
 840                 dprintk("%s: Failed finding expected dot in port\n",
 841                         __func__);
 842                 goto out_free_buf;
 843         }
 844         *portstr = '-';
 845 
 846         /* find '.' between address and port */
 847         portstr = strrchr(buf, '.');
 848         if (!portstr) {
 849                 dprintk("%s: Failed finding expected dot between address and "
 850                         "port\n", __func__);
 851                 goto out_free_buf;
 852         }
 853         *portstr = '\0';
 854 
 855         da = kzalloc(sizeof(*da), gfp_flags);
 856         if (unlikely(!da))
 857                 goto out_free_buf;
 858 
 859         INIT_LIST_HEAD(&da->da_node);
 860 
 861         if (!rpc_pton(net, buf, portstr-buf, (struct sockaddr *)&da->da_addr,
 862                       sizeof(da->da_addr))) {
 863                 dprintk("%s: error parsing address %s\n", __func__, buf);
 864                 goto out_free_da;
 865         }
 866 
 867         portstr++;
 868         sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
 869         port = htons((tmp[0] << 8) | (tmp[1]));
 870 
 871         switch (da->da_addr.ss_family) {
 872         case AF_INET:
 873                 ((struct sockaddr_in *)&da->da_addr)->sin_port = port;
 874                 da->da_addrlen = sizeof(struct sockaddr_in);
 875                 match_netid = "tcp";
 876                 match_netid_len = 3;
 877                 break;
 878 
 879         case AF_INET6:
 880                 ((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port;
 881                 da->da_addrlen = sizeof(struct sockaddr_in6);
 882                 match_netid = "tcp6";
 883                 match_netid_len = 4;
 884                 startsep = "[";
 885                 endsep = "]";
 886                 break;
 887 
 888         default:
 889                 dprintk("%s: unsupported address family: %u\n",
 890                         __func__, da->da_addr.ss_family);
 891                 goto out_free_da;
 892         }
 893 
 894         if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) {
 895                 dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n",
 896                         __func__, netid, match_netid);
 897                 goto out_free_da;
 898         }
 899 
 900         /* save human readable address */
 901         len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7;
 902         da->da_remotestr = kzalloc(len, gfp_flags);
 903 
 904         /* NULL is ok, only used for dprintk */
 905         if (da->da_remotestr)
 906                 snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep,
 907                          buf, endsep, ntohs(port));
 908 
 909         dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr);
 910         kfree(buf);
 911         kfree(netid);
 912         return da;
 913 
 914 out_free_da:
 915         kfree(da);
 916 out_free_buf:
 917         dprintk("%s: Error parsing DS addr: %s\n", __func__, buf);
 918         kfree(buf);
 919 out_free_netid:
 920         kfree(netid);
 921 out_err:
 922         return NULL;
 923 }
 924 EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr);
 925 
 926 void
 927 pnfs_layout_mark_request_commit(struct nfs_page *req,
 928                                 struct pnfs_layout_segment *lseg,
 929                                 struct nfs_commit_info *cinfo,
 930                                 u32 ds_commit_idx)
 931 {
 932         struct list_head *list;
 933         struct pnfs_commit_bucket *buckets;
 934 
 935         mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
 936         buckets = cinfo->ds->buckets;
 937         list = &buckets[ds_commit_idx].written;
 938         if (list_empty(list)) {
 939                 if (!pnfs_is_valid_lseg(lseg)) {
 940                         mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 941                         cinfo->completion_ops->resched_write(cinfo, req);
 942                         return;
 943                 }
 944                 /* Non-empty buckets hold a reference on the lseg.  That ref
 945                  * is normally transferred to the COMMIT call and released
 946                  * there.  It could also be released if the last req is pulled
 947                  * off due to a rewrite, in which case it will be done in
 948                  * pnfs_common_clear_request_commit
 949                  */
 950                 WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
 951                 buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
 952         }
 953         set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
 954         cinfo->ds->nwritten++;
 955 
 956         nfs_request_add_commit_list_locked(req, list, cinfo);
 957         mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 958         nfs_mark_page_unstable(req->wb_page, cinfo);
 959 }
 960 EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
 961 
 962 int
 963 pnfs_nfs_generic_sync(struct inode *inode, bool datasync)
 964 {
 965         int ret;
 966 
 967         if (!pnfs_layoutcommit_outstanding(inode))
 968                 return 0;
 969         ret = nfs_commit_inode(inode, FLUSH_SYNC);
 970         if (ret < 0)
 971                 return ret;
 972         if (datasync)
 973                 return 0;
 974         return pnfs_layoutcommit_inode(inode, true);
 975 }
 976 EXPORT_SYMBOL_GPL(pnfs_nfs_generic_sync);
 977 

/* [<][>][^][v][top][bottom][index][help] */