linux/fs/nfs/nfs4client.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
   3 * Written by David Howells (dhowells@redhat.com)
   4 */
   5#include <linux/module.h>
   6#include <linux/nfs_fs.h>
   7#include <linux/nfs_mount.h>
   8#include <linux/sunrpc/addr.h>
   9#include <linux/sunrpc/auth.h>
  10#include <linux/sunrpc/xprt.h>
  11#include <linux/sunrpc/bc_xprt.h>
  12#include <linux/sunrpc/rpc_pipe_fs.h>
  13#include "internal.h"
  14#include "callback.h"
  15#include "delegation.h"
  16#include "nfs4session.h"
  17#include "nfs4idmap.h"
  18#include "pnfs.h"
  19#include "netns.h"
  20
  21#define NFSDBG_FACILITY         NFSDBG_CLIENT
  22
  23/*
  24 * Get a unique NFSv4.0 callback identifier which will be used
  25 * by the V4.0 callback service to lookup the nfs_client struct
  26 */
  27static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
  28{
  29        int ret = 0;
  30        struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
  31
  32        if (clp->rpc_ops->version != 4 || minorversion != 0)
  33                return ret;
  34        idr_preload(GFP_KERNEL);
  35        spin_lock(&nn->nfs_client_lock);
  36        ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT);
  37        if (ret >= 0)
  38                clp->cl_cb_ident = ret;
  39        spin_unlock(&nn->nfs_client_lock);
  40        idr_preload_end();
  41        return ret < 0 ? ret : 0;
  42}
  43
  44#ifdef CONFIG_NFS_V4_1
  45/**
  46 * Per auth flavor data server rpc clients
  47 */
  48struct nfs4_ds_server {
  49        struct list_head        list;   /* ds_clp->cl_ds_clients */
  50        struct rpc_clnt         *rpc_clnt;
  51};
  52
  53/**
  54 * Common lookup case for DS I/O
  55 */
  56static struct nfs4_ds_server *
  57nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
  58{
  59        struct nfs4_ds_server *dss;
  60
  61        rcu_read_lock();
  62        list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) {
  63                if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
  64                        continue;
  65                goto out;
  66        }
  67        dss = NULL;
  68out:
  69        rcu_read_unlock();
  70        return dss;
  71}
  72
  73static struct nfs4_ds_server *
  74nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor,
  75                           struct nfs4_ds_server *new)
  76{
  77        struct nfs4_ds_server *dss;
  78
  79        spin_lock(&ds_clp->cl_lock);
  80        list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) {
  81                if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
  82                        continue;
  83                goto out;
  84        }
  85        if (new)
  86                list_add_rcu(&new->list, &ds_clp->cl_ds_clients);
  87        dss = new;
  88out:
  89        spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */
  90        return dss;
  91}
  92
  93static struct nfs4_ds_server *
  94nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
  95{
  96        struct nfs4_ds_server *dss;
  97
  98        dss = kmalloc(sizeof(*dss), GFP_NOFS);
  99        if (dss == NULL)
 100                return ERR_PTR(-ENOMEM);
 101
 102        dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor);
 103        if (IS_ERR(dss->rpc_clnt)) {
 104                int err = PTR_ERR(dss->rpc_clnt);
 105                kfree (dss);
 106                return ERR_PTR(err);
 107        }
 108        INIT_LIST_HEAD(&dss->list);
 109
 110        return dss;
 111}
 112
 113static void
 114nfs4_free_ds_server(struct nfs4_ds_server *dss)
 115{
 116        rpc_release_client(dss->rpc_clnt);
 117        kfree(dss);
 118}
 119
 120/**
 121* Find or create a DS rpc client with th MDS server rpc client auth flavor
 122* in the nfs_client cl_ds_clients list.
 123*/
 124struct rpc_clnt *
 125nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode)
 126{
 127        struct nfs4_ds_server *dss, *new;
 128        rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor;
 129
 130        dss = nfs4_find_ds_client(ds_clp, flavor);
 131        if (dss != NULL)
 132                goto out;
 133        new = nfs4_alloc_ds_server(ds_clp, flavor);
 134        if (IS_ERR(new))
 135                return ERR_CAST(new);
 136        dss = nfs4_add_ds_client(ds_clp, flavor, new);
 137        if (dss != new)
 138                nfs4_free_ds_server(new);
 139out:
 140        return dss->rpc_clnt;
 141}
 142EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client);
 143
 144static void
 145nfs4_shutdown_ds_clients(struct nfs_client *clp)
 146{
 147        struct nfs4_ds_server *dss;
 148        LIST_HEAD(shutdown_list);
 149
 150        while (!list_empty(&clp->cl_ds_clients)) {
 151                dss = list_entry(clp->cl_ds_clients.next,
 152                                        struct nfs4_ds_server, list);
 153                list_del(&dss->list);
 154                rpc_shutdown_client(dss->rpc_clnt);
 155                kfree (dss);
 156        }
 157}
 158
 159void nfs41_shutdown_client(struct nfs_client *clp)
 160{
 161        if (nfs4_has_session(clp)) {
 162                nfs4_shutdown_ds_clients(clp);
 163                nfs4_destroy_session(clp->cl_session);
 164                nfs4_destroy_clientid(clp);
 165        }
 166
 167}
 168#endif  /* CONFIG_NFS_V4_1 */
 169
 170void nfs40_shutdown_client(struct nfs_client *clp)
 171{
 172        if (clp->cl_slot_tbl) {
 173                nfs4_shutdown_slot_table(clp->cl_slot_tbl);
 174                kfree(clp->cl_slot_tbl);
 175        }
 176}
 177
 178struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
 179{
 180        int err;
 181        struct nfs_client *clp = nfs_alloc_client(cl_init);
 182        if (IS_ERR(clp))
 183                return clp;
 184
 185        err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
 186        if (err)
 187                goto error;
 188
 189        if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) {
 190                err = -EINVAL;
 191                goto error;
 192        }
 193
 194        spin_lock_init(&clp->cl_lock);
 195        INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
 196        INIT_LIST_HEAD(&clp->cl_ds_clients);
 197        rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
 198        clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
 199        clp->cl_minorversion = cl_init->minorversion;
 200        clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
 201        clp->cl_mig_gen = 1;
 202#if IS_ENABLED(CONFIG_NFS_V4_1)
 203        init_waitqueue_head(&clp->cl_lock_waitq);
 204#endif
 205        return clp;
 206
 207error:
 208        nfs_free_client(clp);
 209        return ERR_PTR(err);
 210}
 211
 212/*
 213 * Destroy the NFS4 callback service
 214 */
 215static void nfs4_destroy_callback(struct nfs_client *clp)
 216{
 217        if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
 218                nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net);
 219}
 220
 221static void nfs4_shutdown_client(struct nfs_client *clp)
 222{
 223        if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
 224                nfs4_kill_renewd(clp);
 225        clp->cl_mvops->shutdown_client(clp);
 226        nfs4_destroy_callback(clp);
 227        if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
 228                nfs_idmap_delete(clp);
 229
 230        rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
 231        kfree(clp->cl_serverowner);
 232        kfree(clp->cl_serverscope);
 233        kfree(clp->cl_implid);
 234        kfree(clp->cl_owner_id);
 235}
 236
 237void nfs4_free_client(struct nfs_client *clp)
 238{
 239        nfs4_shutdown_client(clp);
 240        nfs_free_client(clp);
 241}
 242
 243/*
 244 * Initialize the NFS4 callback service
 245 */
 246static int nfs4_init_callback(struct nfs_client *clp)
 247{
 248        struct rpc_xprt *xprt;
 249        int error;
 250
 251        xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
 252
 253        if (nfs4_has_session(clp)) {
 254                error = xprt_setup_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
 255                if (error < 0)
 256                        return error;
 257        }
 258
 259        error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
 260        if (error < 0) {
 261                dprintk("%s: failed to start callback. Error = %d\n",
 262                        __func__, error);
 263                return error;
 264        }
 265        __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
 266
 267        return 0;
 268}
 269
 270/**
 271 * nfs40_init_client - nfs_client initialization tasks for NFSv4.0
 272 * @clp - nfs_client to initialize
 273 *
 274 * Returns zero on success, or a negative errno if some error occurred.
 275 */
 276int nfs40_init_client(struct nfs_client *clp)
 277{
 278        struct nfs4_slot_table *tbl;
 279        int ret;
 280
 281        tbl = kzalloc(sizeof(*tbl), GFP_NOFS);
 282        if (tbl == NULL)
 283                return -ENOMEM;
 284
 285        ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE,
 286                                        "NFSv4.0 transport Slot table");
 287        if (ret) {
 288                kfree(tbl);
 289                return ret;
 290        }
 291
 292        clp->cl_slot_tbl = tbl;
 293        return 0;
 294}
 295
 296#if defined(CONFIG_NFS_V4_1)
 297
 298/**
 299 * nfs41_init_client - nfs_client initialization tasks for NFSv4.1+
 300 * @clp - nfs_client to initialize
 301 *
 302 * Returns zero on success, or a negative errno if some error occurred.
 303 */
 304int nfs41_init_client(struct nfs_client *clp)
 305{
 306        struct nfs4_session *session = NULL;
 307
 308        /*
 309         * Create the session and mark it expired.
 310         * When a SEQUENCE operation encounters the expired session
 311         * it will do session recovery to initialize it.
 312         */
 313        session = nfs4_alloc_session(clp);
 314        if (!session)
 315                return -ENOMEM;
 316
 317        clp->cl_session = session;
 318
 319        /*
 320         * The create session reply races with the server back
 321         * channel probe. Mark the client NFS_CS_SESSION_INITING
 322         * so that the client back channel can find the
 323         * nfs_client struct
 324         */
 325        nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
 326        return 0;
 327}
 328
 329#endif  /* CONFIG_NFS_V4_1 */
 330
 331/*
 332 * Initialize the minor version specific parts of an NFS4 client record
 333 */
 334static int nfs4_init_client_minor_version(struct nfs_client *clp)
 335{
 336        int ret;
 337
 338        ret = clp->cl_mvops->init_client(clp);
 339        if (ret)
 340                return ret;
 341        return nfs4_init_callback(clp);
 342}
 343
 344/**
 345 * nfs4_init_client - Initialise an NFS4 client record
 346 *
 347 * @clp: nfs_client to initialise
 348 * @timeparms: timeout parameters for underlying RPC transport
 349 * @ip_addr: callback IP address in presentation format
 350 * @authflavor: authentication flavor for underlying RPC transport
 351 *
 352 * Returns pointer to an NFS client, or an ERR_PTR value.
 353 */
 354struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 355                                    const struct nfs_client_initdata *cl_init)
 356{
 357        char buf[INET6_ADDRSTRLEN + 1];
 358        const char *ip_addr = cl_init->ip_addr;
 359        struct nfs_client *old;
 360        int error;
 361
 362        if (clp->cl_cons_state == NFS_CS_READY)
 363                /* the client is initialised already */
 364                return clp;
 365
 366        /* Check NFS protocol revision and initialize RPC op vector */
 367        clp->rpc_ops = &nfs_v4_clientops;
 368
 369        if (clp->cl_minorversion != 0)
 370                __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
 371        __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
 372        __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
 373
 374        error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_GSS_KRB5I);
 375        if (error == -EINVAL)
 376                error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX);
 377        if (error < 0)
 378                goto error;
 379
 380        /* If no clientaddr= option was specified, find a usable cb address */
 381        if (ip_addr == NULL) {
 382                struct sockaddr_storage cb_addr;
 383                struct sockaddr *sap = (struct sockaddr *)&cb_addr;
 384
 385                error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
 386                if (error < 0)
 387                        goto error;
 388                error = rpc_ntop(sap, buf, sizeof(buf));
 389                if (error < 0)
 390                        goto error;
 391                ip_addr = (const char *)buf;
 392        }
 393        strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
 394
 395        error = nfs_idmap_new(clp);
 396        if (error < 0) {
 397                dprintk("%s: failed to create idmapper. Error = %d\n",
 398                        __func__, error);
 399                goto error;
 400        }
 401        __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
 402
 403        error = nfs4_init_client_minor_version(clp);
 404        if (error < 0)
 405                goto error;
 406
 407        if (!nfs4_has_session(clp))
 408                nfs_mark_client_ready(clp, NFS_CS_READY);
 409
 410        error = nfs4_discover_server_trunking(clp, &old);
 411        if (error < 0)
 412                goto error;
 413
 414        if (clp != old)
 415                clp->cl_preserve_clid = true;
 416        nfs_put_client(clp);
 417        return old;
 418
 419error:
 420        nfs_mark_client_ready(clp, error);
 421        nfs_put_client(clp);
 422        return ERR_PTR(error);
 423}
 424
 425/*
 426 * SETCLIENTID just did a callback update with the callback ident in
 427 * "drop," but server trunking discovery claims "drop" and "keep" are
 428 * actually the same server.  Swap the callback IDs so that "keep"
 429 * will continue to use the callback ident the server now knows about,
 430 * and so that "keep"'s original callback ident is destroyed when
 431 * "drop" is freed.
 432 */
 433static void nfs4_swap_callback_idents(struct nfs_client *keep,
 434                                      struct nfs_client *drop)
 435{
 436        struct nfs_net *nn = net_generic(keep->cl_net, nfs_net_id);
 437        unsigned int save = keep->cl_cb_ident;
 438
 439        if (keep->cl_cb_ident == drop->cl_cb_ident)
 440                return;
 441
 442        dprintk("%s: keeping callback ident %u and dropping ident %u\n",
 443                __func__, keep->cl_cb_ident, drop->cl_cb_ident);
 444
 445        spin_lock(&nn->nfs_client_lock);
 446
 447        idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident);
 448        keep->cl_cb_ident = drop->cl_cb_ident;
 449
 450        idr_replace(&nn->cb_ident_idr, drop, save);
 451        drop->cl_cb_ident = save;
 452
 453        spin_unlock(&nn->nfs_client_lock);
 454}
 455
 456static bool nfs4_match_client_owner_id(const struct nfs_client *clp1,
 457                const struct nfs_client *clp2)
 458{
 459        if (clp1->cl_owner_id == NULL || clp2->cl_owner_id == NULL)
 460                return true;
 461        return strcmp(clp1->cl_owner_id, clp2->cl_owner_id) == 0;
 462}
 463
 464static bool nfs4_same_verifier(nfs4_verifier *v1, nfs4_verifier *v2)
 465{
 466        return memcmp(v1->data, v2->data, sizeof(v1->data)) == 0;
 467}
 468
 469static int nfs4_match_client(struct nfs_client  *pos,  struct nfs_client *new,
 470                             struct nfs_client **prev, struct nfs_net *nn)
 471{
 472        int status;
 473
 474        if (pos->rpc_ops != new->rpc_ops)
 475                return 1;
 476
 477        if (pos->cl_minorversion != new->cl_minorversion)
 478                return 1;
 479
 480        /* If "pos" isn't marked ready, we can't trust the
 481         * remaining fields in "pos", especially the client
 482         * ID and serverowner fields.  Wait for CREATE_SESSION
 483         * to finish. */
 484        if (pos->cl_cons_state > NFS_CS_READY) {
 485                atomic_inc(&pos->cl_count);
 486                spin_unlock(&nn->nfs_client_lock);
 487
 488                nfs_put_client(*prev);
 489                *prev = pos;
 490
 491                status = nfs_wait_client_init_complete(pos);
 492                spin_lock(&nn->nfs_client_lock);
 493
 494                if (status < 0)
 495                        return status;
 496        }
 497
 498        if (pos->cl_cons_state != NFS_CS_READY)
 499                return 1;
 500
 501        if (pos->cl_clientid != new->cl_clientid)
 502                return 1;
 503
 504        /* NFSv4.1 always uses the uniform string, however someone
 505         * might switch the uniquifier string on us.
 506         */
 507        if (!nfs4_match_client_owner_id(pos, new))
 508                return 1;
 509
 510        return 0;
 511}
 512
 513/**
 514 * nfs40_walk_client_list - Find server that recognizes a client ID
 515 *
 516 * @new: nfs_client with client ID to test
 517 * @result: OUT: found nfs_client, or new
 518 * @cred: credential to use for trunking test
 519 *
 520 * Returns zero, a negative errno, or a negative NFS4ERR status.
 521 * If zero is returned, an nfs_client pointer is planted in "result."
 522 *
 523 * NB: nfs40_walk_client_list() relies on the new nfs_client being
 524 *     the last nfs_client on the list.
 525 */
 526int nfs40_walk_client_list(struct nfs_client *new,
 527                           struct nfs_client **result,
 528                           struct rpc_cred *cred)
 529{
 530        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
 531        struct nfs_client *pos, *prev = NULL;
 532        struct nfs4_setclientid_res clid = {
 533                .clientid       = new->cl_clientid,
 534                .confirm        = new->cl_confirm,
 535        };
 536        int status = -NFS4ERR_STALE_CLIENTID;
 537
 538        spin_lock(&nn->nfs_client_lock);
 539        list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 540
 541                status = nfs4_match_client(pos, new, &prev, nn);
 542                if (status < 0)
 543                        goto out_unlock;
 544                if (status != 0)
 545                        continue;
 546                /*
 547                 * We just sent a new SETCLIENTID, which should have
 548                 * caused the server to return a new cl_confirm.  So if
 549                 * cl_confirm is the same, then this is a different
 550                 * server that just returned the same cl_confirm by
 551                 * coincidence:
 552                 */
 553                if ((new != pos) && nfs4_same_verifier(&pos->cl_confirm,
 554                                                       &new->cl_confirm))
 555                        continue;
 556                /*
 557                 * But if the cl_confirm's are different, then the only
 558                 * way that a SETCLIENTID_CONFIRM to pos can succeed is
 559                 * if new and pos point to the same server:
 560                 */
 561                atomic_inc(&pos->cl_count);
 562                spin_unlock(&nn->nfs_client_lock);
 563
 564                nfs_put_client(prev);
 565                prev = pos;
 566
 567                status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
 568                switch (status) {
 569                case -NFS4ERR_STALE_CLIENTID:
 570                        break;
 571                case 0:
 572                        nfs4_swap_callback_idents(pos, new);
 573                        pos->cl_confirm = new->cl_confirm;
 574
 575                        prev = NULL;
 576                        *result = pos;
 577                        goto out;
 578                case -ERESTARTSYS:
 579                case -ETIMEDOUT:
 580                        /* The callback path may have been inadvertently
 581                         * changed. Schedule recovery!
 582                         */
 583                        nfs4_schedule_path_down_recovery(pos);
 584                default:
 585                        goto out;
 586                }
 587
 588                spin_lock(&nn->nfs_client_lock);
 589        }
 590out_unlock:
 591        spin_unlock(&nn->nfs_client_lock);
 592
 593        /* No match found. The server lost our clientid */
 594out:
 595        nfs_put_client(prev);
 596        return status;
 597}
 598
 599#ifdef CONFIG_NFS_V4_1
 600/*
 601 * Returns true if the server major ids match
 602 */
 603static bool
 604nfs4_check_serverowner_major_id(struct nfs41_server_owner *o1,
 605                                struct nfs41_server_owner *o2)
 606{
 607        if (o1->major_id_sz != o2->major_id_sz)
 608                return false;
 609        return memcmp(o1->major_id, o2->major_id, o1->major_id_sz) == 0;
 610}
 611
 612/*
 613 * Returns true if the server scopes match
 614 */
 615static bool
 616nfs4_check_server_scope(struct nfs41_server_scope *s1,
 617                        struct nfs41_server_scope *s2)
 618{
 619        if (s1->server_scope_sz != s2->server_scope_sz)
 620                return false;
 621        return memcmp(s1->server_scope, s2->server_scope,
 622                                        s1->server_scope_sz) == 0;
 623}
 624
 625/**
 626 * nfs4_detect_session_trunking - Checks for session trunking.
 627 *
 628 * Called after a successful EXCHANGE_ID on a multi-addr connection.
 629 * Upon success, add the transport.
 630 *
 631 * @clp:    original mount nfs_client
 632 * @res:    result structure from an exchange_id using the original mount
 633 *          nfs_client with a new multi_addr transport
 634 *
 635 * Returns zero on success, otherwise -EINVAL
 636 *
 637 * Note: since the exchange_id for the new multi_addr transport uses the
 638 * same nfs_client from the original mount, the cl_owner_id is reused,
 639 * so eir_clientowner is the same.
 640 */
 641int nfs4_detect_session_trunking(struct nfs_client *clp,
 642                                 struct nfs41_exchange_id_res *res,
 643                                 struct rpc_xprt *xprt)
 644{
 645        /* Check eir_clientid */
 646        if (clp->cl_clientid != res->clientid)
 647                goto out_err;
 648
 649        /* Check eir_server_owner so_major_id */
 650        if (!nfs4_check_serverowner_major_id(clp->cl_serverowner,
 651                                             res->server_owner))
 652                goto out_err;
 653
 654        /* Check eir_server_owner so_minor_id */
 655        if (clp->cl_serverowner->minor_id != res->server_owner->minor_id)
 656                goto out_err;
 657
 658        /* Check eir_server_scope */
 659        if (!nfs4_check_server_scope(clp->cl_serverscope, res->server_scope))
 660                goto out_err;
 661
 662        /* Session trunking passed, add the xprt */
 663        rpc_clnt_xprt_switch_add_xprt(clp->cl_rpcclient, xprt);
 664
 665        pr_info("NFS:  %s: Session trunking succeeded for %s\n",
 666                clp->cl_hostname,
 667                xprt->address_strings[RPC_DISPLAY_ADDR]);
 668
 669        return 0;
 670out_err:
 671        pr_info("NFS:  %s: Session trunking failed for %s\n", clp->cl_hostname,
 672                xprt->address_strings[RPC_DISPLAY_ADDR]);
 673
 674        return -EINVAL;
 675}
 676
 677/**
 678 * nfs41_walk_client_list - Find nfs_client that matches a client/server owner
 679 *
 680 * @new: nfs_client with client ID to test
 681 * @result: OUT: found nfs_client, or new
 682 * @cred: credential to use for trunking test
 683 *
 684 * Returns zero, a negative errno, or a negative NFS4ERR status.
 685 * If zero is returned, an nfs_client pointer is planted in "result."
 686 *
 687 * NB: nfs41_walk_client_list() relies on the new nfs_client being
 688 *     the last nfs_client on the list.
 689 */
 690int nfs41_walk_client_list(struct nfs_client *new,
 691                           struct nfs_client **result,
 692                           struct rpc_cred *cred)
 693{
 694        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
 695        struct nfs_client *pos, *prev = NULL;
 696        int status = -NFS4ERR_STALE_CLIENTID;
 697
 698        spin_lock(&nn->nfs_client_lock);
 699        list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 700
 701                if (pos == new)
 702                        goto found;
 703
 704                status = nfs4_match_client(pos, new, &prev, nn);
 705                if (status < 0)
 706                        goto out;
 707                if (status != 0)
 708                        continue;
 709
 710                /*
 711                 * Note that session trunking is just a special subcase of
 712                 * client id trunking. In either case, we want to fall back
 713                 * to using the existing nfs_client.
 714                 */
 715                if (!nfs4_check_serverowner_major_id(pos->cl_serverowner,
 716                                                     new->cl_serverowner))
 717                        continue;
 718
 719found:
 720                atomic_inc(&pos->cl_count);
 721                *result = pos;
 722                status = 0;
 723                break;
 724        }
 725
 726out:
 727        spin_unlock(&nn->nfs_client_lock);
 728        nfs_put_client(prev);
 729        return status;
 730}
 731#endif  /* CONFIG_NFS_V4_1 */
 732
 733static void nfs4_destroy_server(struct nfs_server *server)
 734{
 735        nfs_server_return_all_delegations(server);
 736        unset_pnfs_layoutdriver(server);
 737        nfs4_purge_state_owners(server);
 738}
 739
 740/*
 741 * NFSv4.0 callback thread helper
 742 *
 743 * Find a client by callback identifier
 744 */
 745struct nfs_client *
 746nfs4_find_client_ident(struct net *net, int cb_ident)
 747{
 748        struct nfs_client *clp;
 749        struct nfs_net *nn = net_generic(net, nfs_net_id);
 750
 751        spin_lock(&nn->nfs_client_lock);
 752        clp = idr_find(&nn->cb_ident_idr, cb_ident);
 753        if (clp)
 754                atomic_inc(&clp->cl_count);
 755        spin_unlock(&nn->nfs_client_lock);
 756        return clp;
 757}
 758
 759#if defined(CONFIG_NFS_V4_1)
 760/* Common match routine for v4.0 and v4.1 callback services */
 761static bool nfs4_cb_match_client(const struct sockaddr *addr,
 762                struct nfs_client *clp, u32 minorversion)
 763{
 764        struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 765
 766        /* Don't match clients that failed to initialise */
 767        if (!(clp->cl_cons_state == NFS_CS_READY ||
 768            clp->cl_cons_state == NFS_CS_SESSION_INITING))
 769                return false;
 770
 771        smp_rmb();
 772
 773        /* Match the version and minorversion */
 774        if (clp->rpc_ops->version != 4 ||
 775            clp->cl_minorversion != minorversion)
 776                return false;
 777
 778        /* Match only the IP address, not the port number */
 779        return rpc_cmp_addr(addr, clap);
 780}
 781
 782/*
 783 * NFSv4.1 callback thread helper
 784 * For CB_COMPOUND calls, find a client by IP address, protocol version,
 785 * minorversion, and sessionID
 786 *
 787 * Returns NULL if no such client
 788 */
 789struct nfs_client *
 790nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
 791                           struct nfs4_sessionid *sid, u32 minorversion)
 792{
 793        struct nfs_client *clp;
 794        struct nfs_net *nn = net_generic(net, nfs_net_id);
 795
 796        spin_lock(&nn->nfs_client_lock);
 797        list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
 798                if (nfs4_cb_match_client(addr, clp, minorversion) == false)
 799                        continue;
 800
 801                if (!nfs4_has_session(clp))
 802                        continue;
 803
 804                /* Match sessionid*/
 805                if (memcmp(clp->cl_session->sess_id.data,
 806                    sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
 807                        continue;
 808
 809                atomic_inc(&clp->cl_count);
 810                spin_unlock(&nn->nfs_client_lock);
 811                return clp;
 812        }
 813        spin_unlock(&nn->nfs_client_lock);
 814        return NULL;
 815}
 816
 817#else /* CONFIG_NFS_V4_1 */
 818
 819struct nfs_client *
 820nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
 821                           struct nfs4_sessionid *sid, u32 minorversion)
 822{
 823        return NULL;
 824}
 825#endif /* CONFIG_NFS_V4_1 */
 826
 827/*
 828 * Set up an NFS4 client
 829 */
 830static int nfs4_set_client(struct nfs_server *server,
 831                const char *hostname,
 832                const struct sockaddr *addr,
 833                const size_t addrlen,
 834                const char *ip_addr,
 835                int proto, const struct rpc_timeout *timeparms,
 836                u32 minorversion, struct net *net)
 837{
 838        struct nfs_client_initdata cl_init = {
 839                .hostname = hostname,
 840                .addr = addr,
 841                .addrlen = addrlen,
 842                .ip_addr = ip_addr,
 843                .nfs_mod = &nfs_v4,
 844                .proto = proto,
 845                .minorversion = minorversion,
 846                .net = net,
 847                .timeparms = timeparms,
 848        };
 849        struct nfs_client *clp;
 850
 851        if (server->flags & NFS_MOUNT_NORESVPORT)
 852                set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
 853        if (server->options & NFS_OPTION_MIGRATION)
 854                set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
 855
 856        /* Allocate or find a client reference we can use */
 857        clp = nfs_get_client(&cl_init);
 858        if (IS_ERR(clp))
 859                return PTR_ERR(clp);
 860
 861        if (server->nfs_client == clp)
 862                return -ELOOP;
 863
 864        /*
 865         * Query for the lease time on clientid setup or renewal
 866         *
 867         * Note that this will be set on nfs_clients that were created
 868         * only for the DS role and did not set this bit, but now will
 869         * serve a dual role.
 870         */
 871        set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
 872
 873        server->nfs_client = clp;
 874        return 0;
 875}
 876
 877/*
 878 * Set up a pNFS Data Server client.
 879 *
 880 * Return any existing nfs_client that matches server address,port,version
 881 * and minorversion.
 882 *
 883 * For a new nfs_client, use a soft mount (default), a low retrans and a
 884 * low timeout interval so that if a connection is lost, we retry through
 885 * the MDS.
 886 */
 887struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
 888                const struct sockaddr *ds_addr, int ds_addrlen,
 889                int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans,
 890                u32 minor_version)
 891{
 892        struct rpc_timeout ds_timeout;
 893        struct nfs_client *mds_clp = mds_srv->nfs_client;
 894        struct nfs_client_initdata cl_init = {
 895                .addr = ds_addr,
 896                .addrlen = ds_addrlen,
 897                .nodename = mds_clp->cl_rpcclient->cl_nodename,
 898                .ip_addr = mds_clp->cl_ipaddr,
 899                .nfs_mod = &nfs_v4,
 900                .proto = ds_proto,
 901                .minorversion = minor_version,
 902                .net = mds_clp->cl_net,
 903                .timeparms = &ds_timeout,
 904        };
 905        char buf[INET6_ADDRSTRLEN + 1];
 906
 907        if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
 908                return ERR_PTR(-EINVAL);
 909        cl_init.hostname = buf;
 910
 911        if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
 912                __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
 913
 914        /*
 915         * Set an authflavor equual to the MDS value. Use the MDS nfs_client
 916         * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
 917         * (section 13.1 RFC 5661).
 918         */
 919        nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
 920        return nfs_get_client(&cl_init);
 921}
 922EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
 923
 924/*
 925 * Session has been established, and the client marked ready.
 926 * Set the mount rsize and wsize with negotiated fore channel
 927 * attributes which will be bound checked in nfs_server_set_fsinfo.
 928 */
 929static void nfs4_session_set_rwsize(struct nfs_server *server)
 930{
 931#ifdef CONFIG_NFS_V4_1
 932        struct nfs4_session *sess;
 933        u32 server_resp_sz;
 934        u32 server_rqst_sz;
 935
 936        if (!nfs4_has_session(server->nfs_client))
 937                return;
 938        sess = server->nfs_client->cl_session;
 939        server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
 940        server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
 941
 942        if (!server->rsize || server->rsize > server_resp_sz)
 943                server->rsize = server_resp_sz;
 944        if (!server->wsize || server->wsize > server_rqst_sz)
 945                server->wsize = server_rqst_sz;
 946#endif /* CONFIG_NFS_V4_1 */
 947}
 948
 949static int nfs4_server_common_setup(struct nfs_server *server,
 950                struct nfs_fh *mntfh, bool auth_probe)
 951{
 952        struct nfs_fattr *fattr;
 953        int error;
 954
 955        /* data servers support only a subset of NFSv4.1 */
 956        if (is_ds_only_client(server->nfs_client))
 957                return -EPROTONOSUPPORT;
 958
 959        fattr = nfs_alloc_fattr();
 960        if (fattr == NULL)
 961                return -ENOMEM;
 962
 963        /* We must ensure the session is initialised first */
 964        error = nfs4_init_session(server->nfs_client);
 965        if (error < 0)
 966                goto out;
 967
 968        /* Set the basic capabilities */
 969        server->caps |= server->nfs_client->cl_mvops->init_caps;
 970        if (server->flags & NFS_MOUNT_NORDIRPLUS)
 971                        server->caps &= ~NFS_CAP_READDIRPLUS;
 972        /*
 973         * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
 974         * authentication.
 975         */
 976        if (nfs4_disable_idmapping &&
 977                        server->client->cl_auth->au_flavor == RPC_AUTH_UNIX)
 978                server->caps |= NFS_CAP_UIDGID_NOMAP;
 979
 980
 981        /* Probe the root fh to retrieve its FSID and filehandle */
 982        error = nfs4_get_rootfh(server, mntfh, auth_probe);
 983        if (error < 0)
 984                goto out;
 985
 986        dprintk("Server FSID: %llx:%llx\n",
 987                        (unsigned long long) server->fsid.major,
 988                        (unsigned long long) server->fsid.minor);
 989        nfs_display_fhandle(mntfh, "Pseudo-fs root FH");
 990
 991        nfs4_session_set_rwsize(server);
 992
 993        error = nfs_probe_fsinfo(server, mntfh, fattr);
 994        if (error < 0)
 995                goto out;
 996
 997        if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
 998                server->namelen = NFS4_MAXNAMLEN;
 999
1000        nfs_server_insert_lists(server);
1001        server->mount_time = jiffies;
1002        server->destroy = nfs4_destroy_server;
1003out:
1004        nfs_free_fattr(fattr);
1005        return error;
1006}
1007
1008/*
1009 * Create a version 4 volume record
1010 */
1011static int nfs4_init_server(struct nfs_server *server,
1012                struct nfs_parsed_mount_data *data)
1013{
1014        struct rpc_timeout timeparms;
1015        int error;
1016
1017        nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
1018                        data->timeo, data->retrans);
1019
1020        /* Initialise the client representation from the mount data */
1021        server->flags = data->flags;
1022        server->options = data->options;
1023        server->auth_info = data->auth_info;
1024
1025        /* Use the first specified auth flavor. If this flavor isn't
1026         * allowed by the server, use the SECINFO path to try the
1027         * other specified flavors */
1028        if (data->auth_info.flavor_len >= 1)
1029                data->selected_flavor = data->auth_info.flavors[0];
1030        else
1031                data->selected_flavor = RPC_AUTH_UNIX;
1032
1033        /* Get a client record */
1034        error = nfs4_set_client(server,
1035                        data->nfs_server.hostname,
1036                        (const struct sockaddr *)&data->nfs_server.address,
1037                        data->nfs_server.addrlen,
1038                        data->client_address,
1039                        data->nfs_server.protocol,
1040                        &timeparms,
1041                        data->minorversion,
1042                        data->net);
1043        if (error < 0)
1044                return error;
1045
1046        if (data->rsize)
1047                server->rsize = nfs_block_size(data->rsize, NULL);
1048        if (data->wsize)
1049                server->wsize = nfs_block_size(data->wsize, NULL);
1050
1051        server->acregmin = data->acregmin * HZ;
1052        server->acregmax = data->acregmax * HZ;
1053        server->acdirmin = data->acdirmin * HZ;
1054        server->acdirmax = data->acdirmax * HZ;
1055        server->port     = data->nfs_server.port;
1056
1057        return nfs_init_server_rpcclient(server, &timeparms,
1058                                         data->selected_flavor);
1059}
1060
1061/*
1062 * Create a version 4 volume record
1063 * - keyed on server and FSID
1064 */
1065/*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1066                                      struct nfs_fh *mntfh)*/
1067struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
1068                                      struct nfs_subversion *nfs_mod)
1069{
1070        struct nfs_server *server;
1071        bool auth_probe;
1072        int error;
1073
1074        server = nfs_alloc_server();
1075        if (!server)
1076                return ERR_PTR(-ENOMEM);
1077
1078        auth_probe = mount_info->parsed->auth_info.flavor_len < 1;
1079
1080        /* set up the general RPC client */
1081        error = nfs4_init_server(server, mount_info->parsed);
1082        if (error < 0)
1083                goto error;
1084
1085        error = nfs4_server_common_setup(server, mount_info->mntfh, auth_probe);
1086        if (error < 0)
1087                goto error;
1088
1089        return server;
1090
1091error:
1092        nfs_free_server(server);
1093        return ERR_PTR(error);
1094}
1095
1096/*
1097 * Create an NFS4 referral server record
1098 */
1099struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1100                                               struct nfs_fh *mntfh)
1101{
1102        struct nfs_client *parent_client;
1103        struct nfs_server *server, *parent_server;
1104        bool auth_probe;
1105        int error;
1106
1107        server = nfs_alloc_server();
1108        if (!server)
1109                return ERR_PTR(-ENOMEM);
1110
1111        parent_server = NFS_SB(data->sb);
1112        parent_client = parent_server->nfs_client;
1113
1114        /* Initialise the client representation from the parent server */
1115        nfs_server_copy_userdata(server, parent_server);
1116
1117        /* Get a client representation.
1118         * Note: NFSv4 always uses TCP, */
1119        error = nfs4_set_client(server, data->hostname,
1120                                data->addr,
1121                                data->addrlen,
1122                                parent_client->cl_ipaddr,
1123                                rpc_protocol(parent_server->client),
1124                                parent_server->client->cl_timeout,
1125                                parent_client->cl_mvops->minor_version,
1126                                parent_client->cl_net);
1127        if (error < 0)
1128                goto error;
1129
1130        error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
1131        if (error < 0)
1132                goto error;
1133
1134        auth_probe = parent_server->auth_info.flavor_len < 1;
1135
1136        error = nfs4_server_common_setup(server, mntfh, auth_probe);
1137        if (error < 0)
1138                goto error;
1139
1140        return server;
1141
1142error:
1143        nfs_free_server(server);
1144        return ERR_PTR(error);
1145}
1146
1147/*
1148 * Grab the destination's particulars, including lease expiry time.
1149 *
1150 * Returns zero if probe succeeded and retrieved FSID matches the FSID
1151 * we have cached.
1152 */
1153static int nfs_probe_destination(struct nfs_server *server)
1154{
1155        struct inode *inode = d_inode(server->super->s_root);
1156        struct nfs_fattr *fattr;
1157        int error;
1158
1159        fattr = nfs_alloc_fattr();
1160        if (fattr == NULL)
1161                return -ENOMEM;
1162
1163        /* Sanity: the probe won't work if the destination server
1164         * does not recognize the migrated FH. */
1165        error = nfs_probe_fsinfo(server, NFS_FH(inode), fattr);
1166
1167        nfs_free_fattr(fattr);
1168        return error;
1169}
1170
1171/**
1172 * nfs4_update_server - Move an nfs_server to a different nfs_client
1173 *
1174 * @server: represents FSID to be moved
1175 * @hostname: new end-point's hostname
1176 * @sap: new end-point's socket address
1177 * @salen: size of "sap"
1178 * @net: net namespace
1179 *
1180 * The nfs_server must be quiescent before this function is invoked.
1181 * Either its session is drained (NFSv4.1+), or its transport is
1182 * plugged and drained (NFSv4.0).
1183 *
1184 * Returns zero on success, or a negative errno value.
1185 */
1186int nfs4_update_server(struct nfs_server *server, const char *hostname,
1187                       struct sockaddr *sap, size_t salen, struct net *net)
1188{
1189        struct nfs_client *clp = server->nfs_client;
1190        struct rpc_clnt *clnt = server->client;
1191        struct xprt_create xargs = {
1192                .ident          = clp->cl_proto,
1193                .net            = net,
1194                .dstaddr        = sap,
1195                .addrlen        = salen,
1196                .servername     = hostname,
1197        };
1198        char buf[INET6_ADDRSTRLEN + 1];
1199        struct sockaddr_storage address;
1200        struct sockaddr *localaddr = (struct sockaddr *)&address;
1201        int error;
1202
1203        error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout);
1204        if (error != 0)
1205                return error;
1206
1207        error = rpc_localaddr(clnt, localaddr, sizeof(address));
1208        if (error != 0)
1209                return error;
1210
1211        if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0)
1212                return -EAFNOSUPPORT;
1213
1214        nfs_server_remove_lists(server);
1215        error = nfs4_set_client(server, hostname, sap, salen, buf,
1216                                clp->cl_proto, clnt->cl_timeout,
1217                                clp->cl_minorversion, net);
1218        nfs_put_client(clp);
1219        if (error != 0) {
1220                nfs_server_insert_lists(server);
1221                return error;
1222        }
1223
1224        if (server->nfs_client->cl_hostname == NULL)
1225                server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
1226        nfs_server_insert_lists(server);
1227
1228        return nfs_probe_destination(server);
1229}
1230