linux/fs/nfs/callback_proc.c
<<
>>
Prefs
   1/*
   2 * linux/fs/nfs/callback_proc.c
   3 *
   4 * Copyright (C) 2004 Trond Myklebust
   5 *
   6 * NFSv4 callback procedures
   7 */
   8#include <linux/nfs4.h>
   9#include <linux/nfs_fs.h>
  10#include <linux/slab.h>
  11#include <linux/rcupdate.h>
  12#include "nfs4_fs.h"
  13#include "callback.h"
  14#include "delegation.h"
  15#include "internal.h"
  16#include "pnfs.h"
  17#include "nfs4session.h"
  18#include "nfs4trace.h"
  19
  20#define NFSDBG_FACILITY NFSDBG_CALLBACK
  21
  22__be32 nfs4_callback_getattr(struct cb_getattrargs *args,
  23                             struct cb_getattrres *res,
  24                             struct cb_process_state *cps)
  25{
  26        struct nfs_delegation *delegation;
  27        struct nfs_inode *nfsi;
  28        struct inode *inode;
  29
  30        res->status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
  31        if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
  32                goto out;
  33
  34        res->bitmap[0] = res->bitmap[1] = 0;
  35        res->status = htonl(NFS4ERR_BADHANDLE);
  36
  37        dprintk_rcu("NFS: GETATTR callback request from %s\n",
  38                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
  39
  40        inode = nfs_delegation_find_inode(cps->clp, &args->fh);
  41        if (inode == NULL) {
  42                trace_nfs4_cb_getattr(cps->clp, &args->fh, NULL,
  43                                -ntohl(res->status));
  44                goto out;
  45        }
  46        nfsi = NFS_I(inode);
  47        rcu_read_lock();
  48        delegation = rcu_dereference(nfsi->delegation);
  49        if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
  50                goto out_iput;
  51        res->size = i_size_read(inode);
  52        res->change_attr = delegation->change_attr;
  53        if (nfsi->nrequests != 0)
  54                res->change_attr++;
  55        res->ctime = inode->i_ctime;
  56        res->mtime = inode->i_mtime;
  57        res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
  58                args->bitmap[0];
  59        res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
  60                args->bitmap[1];
  61        res->status = 0;
  62out_iput:
  63        rcu_read_unlock();
  64        trace_nfs4_cb_getattr(cps->clp, &args->fh, inode, -ntohl(res->status));
  65        iput(inode);
  66out:
  67        dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status));
  68        return res->status;
  69}
  70
  71__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
  72                            struct cb_process_state *cps)
  73{
  74        struct inode *inode;
  75        __be32 res;
  76        
  77        res = htonl(NFS4ERR_OP_NOT_IN_SESSION);
  78        if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
  79                goto out;
  80
  81        dprintk_rcu("NFS: RECALL callback request from %s\n",
  82                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
  83
  84        res = htonl(NFS4ERR_BADHANDLE);
  85        inode = nfs_delegation_find_inode(cps->clp, &args->fh);
  86        if (inode == NULL) {
  87                trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
  88                                &args->stateid, -ntohl(res));
  89                goto out;
  90        }
  91        /* Set up a helper thread to actually return the delegation */
  92        switch (nfs_async_inode_return_delegation(inode, &args->stateid)) {
  93        case 0:
  94                res = 0;
  95                break;
  96        case -ENOENT:
  97                res = htonl(NFS4ERR_BAD_STATEID);
  98                break;
  99        default:
 100                res = htonl(NFS4ERR_RESOURCE);
 101        }
 102        trace_nfs4_cb_recall(cps->clp, &args->fh, inode,
 103                        &args->stateid, -ntohl(res));
 104        iput(inode);
 105out:
 106        dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
 107        return res;
 108}
 109
 110#if defined(CONFIG_NFS_V4_1)
 111
 112/*
 113 * Lookup a layout by filehandle.
 114 *
 115 * Note: gets a refcount on the layout hdr and on its respective inode.
 116 * Caller must put the layout hdr and the inode.
 117 *
 118 * TODO: keep track of all layouts (and delegations) in a hash table
 119 * hashed by filehandle.
 120 */
 121static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
 122                struct nfs_fh *fh)
 123{
 124        struct nfs_server *server;
 125        struct nfs_inode *nfsi;
 126        struct inode *ino;
 127        struct pnfs_layout_hdr *lo;
 128
 129restart:
 130        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 131                list_for_each_entry(lo, &server->layouts, plh_layouts) {
 132                        nfsi = NFS_I(lo->plh_inode);
 133                        if (nfs_compare_fh(fh, &nfsi->fh))
 134                                continue;
 135                        if (nfsi->layout != lo)
 136                                continue;
 137                        ino = igrab(lo->plh_inode);
 138                        if (!ino)
 139                                break;
 140                        spin_lock(&ino->i_lock);
 141                        /* Is this layout in the process of being freed? */
 142                        if (nfsi->layout != lo) {
 143                                spin_unlock(&ino->i_lock);
 144                                iput(ino);
 145                                goto restart;
 146                        }
 147                        pnfs_get_layout_hdr(lo);
 148                        spin_unlock(&ino->i_lock);
 149                        return lo;
 150                }
 151        }
 152
 153        return NULL;
 154}
 155
 156static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
 157                struct nfs_fh *fh)
 158{
 159        struct pnfs_layout_hdr *lo;
 160
 161        spin_lock(&clp->cl_lock);
 162        rcu_read_lock();
 163        lo = get_layout_by_fh_locked(clp, fh);
 164        rcu_read_unlock();
 165        spin_unlock(&clp->cl_lock);
 166
 167        return lo;
 168}
 169
 170/*
 171 * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
 172 */
 173static u32 pnfs_check_callback_stateid(struct pnfs_layout_hdr *lo,
 174                                        const nfs4_stateid *new)
 175{
 176        u32 oldseq, newseq;
 177
 178        /* Is the stateid still not initialised? */
 179        if (!pnfs_layout_is_valid(lo))
 180                return NFS4ERR_DELAY;
 181
 182        /* Mismatched stateid? */
 183        if (!nfs4_stateid_match_other(&lo->plh_stateid, new))
 184                return NFS4ERR_BAD_STATEID;
 185
 186        newseq = be32_to_cpu(new->seqid);
 187        /* Are we already in a layout recall situation? */
 188        if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) &&
 189            lo->plh_return_seq != 0) {
 190                if (newseq < lo->plh_return_seq)
 191                        return NFS4ERR_OLD_STATEID;
 192                if (newseq > lo->plh_return_seq)
 193                        return NFS4ERR_DELAY;
 194                goto out;
 195        }
 196
 197        /* Check that the stateid matches what we think it should be. */
 198        oldseq = be32_to_cpu(lo->plh_stateid.seqid);
 199        if (newseq > oldseq + 1)
 200                return NFS4ERR_DELAY;
 201        /* Crazy server! */
 202        if (newseq <= oldseq)
 203                return NFS4ERR_OLD_STATEID;
 204out:
 205        return NFS_OK;
 206}
 207
 208static u32 initiate_file_draining(struct nfs_client *clp,
 209                                  struct cb_layoutrecallargs *args)
 210{
 211        struct inode *ino;
 212        struct pnfs_layout_hdr *lo;
 213        u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
 214        LIST_HEAD(free_me_list);
 215
 216        lo = get_layout_by_fh(clp, &args->cbl_fh);
 217        if (!lo) {
 218                trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, NULL,
 219                                &args->cbl_stateid, -rv);
 220                goto out;
 221        }
 222
 223        ino = lo->plh_inode;
 224        pnfs_layoutcommit_inode(ino, false);
 225
 226
 227        spin_lock(&ino->i_lock);
 228        rv = pnfs_check_callback_stateid(lo, &args->cbl_stateid);
 229        if (rv != NFS_OK)
 230                goto unlock;
 231        pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
 232
 233        /*
 234         * Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
 235         */
 236        if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
 237                rv = NFS4ERR_DELAY;
 238                goto unlock;
 239        }
 240
 241        if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
 242                                &args->cbl_range,
 243                                be32_to_cpu(args->cbl_stateid.seqid))) {
 244                rv = NFS4_OK;
 245                goto unlock;
 246        }
 247
 248        /* Embrace your forgetfulness! */
 249        rv = NFS4ERR_NOMATCHING_LAYOUT;
 250
 251        if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
 252                NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
 253                        &args->cbl_range);
 254        }
 255unlock:
 256        spin_unlock(&ino->i_lock);
 257        pnfs_free_lseg_list(&free_me_list);
 258        /* Free all lsegs that are attached to commit buckets */
 259        nfs_commit_inode(ino, 0);
 260        pnfs_put_layout_hdr(lo);
 261        trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
 262                        &args->cbl_stateid, -rv);
 263        iput(ino);
 264out:
 265        return rv;
 266}
 267
 268static u32 initiate_bulk_draining(struct nfs_client *clp,
 269                                  struct cb_layoutrecallargs *args)
 270{
 271        int stat;
 272
 273        if (args->cbl_recall_type == RETURN_FSID)
 274                stat = pnfs_destroy_layouts_byfsid(clp, &args->cbl_fsid, true);
 275        else
 276                stat = pnfs_destroy_layouts_byclid(clp, true);
 277        if (stat != 0)
 278                return NFS4ERR_DELAY;
 279        return NFS4ERR_NOMATCHING_LAYOUT;
 280}
 281
 282static u32 do_callback_layoutrecall(struct nfs_client *clp,
 283                                    struct cb_layoutrecallargs *args)
 284{
 285        u32 res;
 286
 287        dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type);
 288        if (args->cbl_recall_type == RETURN_FILE)
 289                res = initiate_file_draining(clp, args);
 290        else
 291                res = initiate_bulk_draining(clp, args);
 292        dprintk("%s returning %i\n", __func__, res);
 293        return res;
 294
 295}
 296
 297__be32 nfs4_callback_layoutrecall(struct cb_layoutrecallargs *args,
 298                                  void *dummy, struct cb_process_state *cps)
 299{
 300        u32 res;
 301
 302        dprintk("%s: -->\n", __func__);
 303
 304        if (cps->clp)
 305                res = do_callback_layoutrecall(cps->clp, args);
 306        else
 307                res = NFS4ERR_OP_NOT_IN_SESSION;
 308
 309        dprintk("%s: exit with status = %d\n", __func__, res);
 310        return cpu_to_be32(res);
 311}
 312
 313static void pnfs_recall_all_layouts(struct nfs_client *clp)
 314{
 315        struct cb_layoutrecallargs args;
 316
 317        /* Pretend we got a CB_LAYOUTRECALL(ALL) */
 318        memset(&args, 0, sizeof(args));
 319        args.cbl_recall_type = RETURN_ALL;
 320        /* FIXME we ignore errors, what should we do? */
 321        do_callback_layoutrecall(clp, &args);
 322}
 323
 324__be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
 325                                  void *dummy, struct cb_process_state *cps)
 326{
 327        int i;
 328        __be32 res = 0;
 329        struct nfs_client *clp = cps->clp;
 330        struct nfs_server *server = NULL;
 331
 332        dprintk("%s: -->\n", __func__);
 333
 334        if (!clp) {
 335                res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
 336                goto out;
 337        }
 338
 339        for (i = 0; i < args->ndevs; i++) {
 340                struct cb_devicenotifyitem *dev = &args->devs[i];
 341
 342                if (!server ||
 343                    server->pnfs_curr_ld->id != dev->cbd_layout_type) {
 344                        rcu_read_lock();
 345                        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
 346                                if (server->pnfs_curr_ld &&
 347                                    server->pnfs_curr_ld->id == dev->cbd_layout_type) {
 348                                        rcu_read_unlock();
 349                                        goto found;
 350                                }
 351                        rcu_read_unlock();
 352                        dprintk("%s: layout type %u not found\n",
 353                                __func__, dev->cbd_layout_type);
 354                        continue;
 355                }
 356
 357        found:
 358                nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
 359        }
 360
 361out:
 362        kfree(args->devs);
 363        dprintk("%s: exit with status = %u\n",
 364                __func__, be32_to_cpu(res));
 365        return res;
 366}
 367
 368/*
 369 * Validate the sequenceID sent by the server.
 370 * Return success if the sequenceID is one more than what we last saw on
 371 * this slot, accounting for wraparound.  Increments the slot's sequence.
 372 *
 373 * We don't yet implement a duplicate request cache, instead we set the
 374 * back channel ca_maxresponsesize_cached to zero. This is OK for now
 375 * since we only currently implement idempotent callbacks anyway.
 376 *
 377 * We have a single slot backchannel at this time, so we don't bother
 378 * checking the used_slots bit array on the table.  The lower layer guarantees
 379 * a single outstanding callback request at a time.
 380 */
 381static __be32
 382validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
 383                const struct cb_sequenceargs * args)
 384{
 385        dprintk("%s enter. slotid %u seqid %u, slot table seqid: %u\n",
 386                __func__, args->csa_slotid, args->csa_sequenceid, slot->seq_nr);
 387
 388        if (args->csa_slotid > tbl->server_highest_slotid)
 389                return htonl(NFS4ERR_BADSLOT);
 390
 391        /* Replay */
 392        if (args->csa_sequenceid == slot->seq_nr) {
 393                dprintk("%s seqid %u is a replay\n",
 394                        __func__, args->csa_sequenceid);
 395                if (nfs4_test_locked_slot(tbl, slot->slot_nr))
 396                        return htonl(NFS4ERR_DELAY);
 397                /* Signal process_op to set this error on next op */
 398                if (args->csa_cachethis == 0)
 399                        return htonl(NFS4ERR_RETRY_UNCACHED_REP);
 400
 401                /* Liar! We never allowed you to set csa_cachethis != 0 */
 402                return htonl(NFS4ERR_SEQ_FALSE_RETRY);
 403        }
 404
 405        /* Wraparound */
 406        if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) {
 407                if (args->csa_sequenceid == 1)
 408                        return htonl(NFS4_OK);
 409        } else if (likely(args->csa_sequenceid == slot->seq_nr + 1))
 410                return htonl(NFS4_OK);
 411
 412        /* Misordered request */
 413        return htonl(NFS4ERR_SEQ_MISORDERED);
 414}
 415
 416/*
 417 * For each referring call triple, check the session's slot table for
 418 * a match.  If the slot is in use and the sequence numbers match, the
 419 * client is still waiting for a response to the original request.
 420 */
 421static bool referring_call_exists(struct nfs_client *clp,
 422                                  uint32_t nrclists,
 423                                  struct referring_call_list *rclists)
 424{
 425        bool status = 0;
 426        int i, j;
 427        struct nfs4_session *session;
 428        struct nfs4_slot_table *tbl;
 429        struct referring_call_list *rclist;
 430        struct referring_call *ref;
 431
 432        /*
 433         * XXX When client trunking is implemented, this becomes
 434         * a session lookup from within the loop
 435         */
 436        session = clp->cl_session;
 437        tbl = &session->fc_slot_table;
 438
 439        for (i = 0; i < nrclists; i++) {
 440                rclist = &rclists[i];
 441                if (memcmp(session->sess_id.data,
 442                           rclist->rcl_sessionid.data,
 443                           NFS4_MAX_SESSIONID_LEN) != 0)
 444                        continue;
 445
 446                for (j = 0; j < rclist->rcl_nrefcalls; j++) {
 447                        ref = &rclist->rcl_refcalls[j];
 448
 449                        dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
 450                                "slotid %u\n", __func__,
 451                                ((u32 *)&rclist->rcl_sessionid.data)[0],
 452                                ((u32 *)&rclist->rcl_sessionid.data)[1],
 453                                ((u32 *)&rclist->rcl_sessionid.data)[2],
 454                                ((u32 *)&rclist->rcl_sessionid.data)[3],
 455                                ref->rc_sequenceid, ref->rc_slotid);
 456
 457                        status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
 458                                        ref->rc_sequenceid, HZ >> 1) < 0;
 459                        if (status)
 460                                goto out;
 461                }
 462        }
 463
 464out:
 465        return status;
 466}
 467
 468__be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 469                              struct cb_sequenceres *res,
 470                              struct cb_process_state *cps)
 471{
 472        struct nfs4_slot_table *tbl;
 473        struct nfs4_slot *slot;
 474        struct nfs_client *clp;
 475        int i;
 476        __be32 status = htonl(NFS4ERR_BADSESSION);
 477
 478        clp = nfs4_find_client_sessionid(cps->net, args->csa_addr,
 479                                         &args->csa_sessionid, cps->minorversion);
 480        if (clp == NULL)
 481                goto out;
 482
 483        if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
 484                goto out;
 485
 486        tbl = &clp->cl_session->bc_slot_table;
 487
 488        /* Set up res before grabbing the spinlock */
 489        memcpy(&res->csr_sessionid, &args->csa_sessionid,
 490               sizeof(res->csr_sessionid));
 491        res->csr_sequenceid = args->csa_sequenceid;
 492        res->csr_slotid = args->csa_slotid;
 493
 494        spin_lock(&tbl->slot_tbl_lock);
 495        /* state manager is resetting the session */
 496        if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) {
 497                status = htonl(NFS4ERR_DELAY);
 498                /* Return NFS4ERR_BADSESSION if we're draining the session
 499                 * in order to reset it.
 500                 */
 501                if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
 502                        status = htonl(NFS4ERR_BADSESSION);
 503                goto out_unlock;
 504        }
 505
 506        status = htonl(NFS4ERR_BADSLOT);
 507        slot = nfs4_lookup_slot(tbl, args->csa_slotid);
 508        if (IS_ERR(slot))
 509                goto out_unlock;
 510
 511        res->csr_highestslotid = tbl->server_highest_slotid;
 512        res->csr_target_highestslotid = tbl->target_highest_slotid;
 513
 514        status = validate_seqid(tbl, slot, args);
 515        if (status)
 516                goto out_unlock;
 517        if (!nfs4_try_to_lock_slot(tbl, slot)) {
 518                status = htonl(NFS4ERR_DELAY);
 519                goto out_unlock;
 520        }
 521        cps->slot = slot;
 522
 523        /* The ca_maxresponsesize_cached is 0 with no DRC */
 524        if (args->csa_cachethis != 0) {
 525                status = htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
 526                goto out_unlock;
 527        }
 528
 529        /*
 530         * Check for pending referring calls.  If a match is found, a
 531         * related callback was received before the response to the original
 532         * call.
 533         */
 534        if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
 535                status = htonl(NFS4ERR_DELAY);
 536                goto out_unlock;
 537        }
 538
 539        /*
 540         * RFC5661 20.9.3
 541         * If CB_SEQUENCE returns an error, then the state of the slot
 542         * (sequence ID, cached reply) MUST NOT change.
 543         */
 544        slot->seq_nr = args->csa_sequenceid;
 545out_unlock:
 546        spin_unlock(&tbl->slot_tbl_lock);
 547
 548out:
 549        cps->clp = clp; /* put in nfs4_callback_compound */
 550        for (i = 0; i < args->csa_nrclists; i++)
 551                kfree(args->csa_rclists[i].rcl_refcalls);
 552        kfree(args->csa_rclists);
 553
 554        if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
 555                cps->drc_status = status;
 556                status = 0;
 557        } else
 558                res->csr_status = status;
 559
 560        trace_nfs4_cb_sequence(args, res, status);
 561        dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
 562                ntohl(status), ntohl(res->csr_status));
 563        return status;
 564}
 565
 566static bool
 567validate_bitmap_values(unsigned long mask)
 568{
 569        return (mask & ~RCA4_TYPE_MASK_ALL) == 0;
 570}
 571
 572__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy,
 573                               struct cb_process_state *cps)
 574{
 575        __be32 status;
 576        fmode_t flags = 0;
 577
 578        status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
 579        if (!cps->clp) /* set in cb_sequence */
 580                goto out;
 581
 582        dprintk_rcu("NFS: RECALL_ANY callback request from %s\n",
 583                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
 584
 585        status = cpu_to_be32(NFS4ERR_INVAL);
 586        if (!validate_bitmap_values(args->craa_type_mask))
 587                goto out;
 588
 589        status = cpu_to_be32(NFS4_OK);
 590        if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *)
 591                     &args->craa_type_mask))
 592                flags = FMODE_READ;
 593        if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *)
 594                     &args->craa_type_mask))
 595                flags |= FMODE_WRITE;
 596        if (test_bit(RCA4_TYPE_MASK_FILE_LAYOUT, (const unsigned long *)
 597                     &args->craa_type_mask))
 598                pnfs_recall_all_layouts(cps->clp);
 599        if (flags)
 600                nfs_expire_unused_delegation_types(cps->clp, flags);
 601out:
 602        dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
 603        return status;
 604}
 605
 606/* Reduce the fore channel's max_slots to the target value */
 607__be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
 608                                struct cb_process_state *cps)
 609{
 610        struct nfs4_slot_table *fc_tbl;
 611        __be32 status;
 612
 613        status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
 614        if (!cps->clp) /* set in cb_sequence */
 615                goto out;
 616
 617        dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %u\n",
 618                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR),
 619                args->crsa_target_highest_slotid);
 620
 621        fc_tbl = &cps->clp->cl_session->fc_slot_table;
 622
 623        status = htonl(NFS4_OK);
 624
 625        nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid);
 626        nfs41_notify_server(cps->clp);
 627out:
 628        dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
 629        return status;
 630}
 631
 632__be32 nfs4_callback_notify_lock(struct cb_notify_lock_args *args, void *dummy,
 633                                 struct cb_process_state *cps)
 634{
 635        if (!cps->clp) /* set in cb_sequence */
 636                return htonl(NFS4ERR_OP_NOT_IN_SESSION);
 637
 638        dprintk_rcu("NFS: CB_NOTIFY_LOCK request from %s\n",
 639                rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
 640
 641        /* Don't wake anybody if the string looked bogus */
 642        if (args->cbnl_valid)
 643                __wake_up(&cps->clp->cl_lock_waitq, TASK_NORMAL, 0, args);
 644
 645        return htonl(NFS4_OK);
 646}
 647#endif /* CONFIG_NFS_V4_1 */
 648