linux/fs/nfs/delegation.c
<<
>>
Prefs
   1/*
   2 * linux/fs/nfs/delegation.c
   3 *
   4 * Copyright (C) 2004 Trond Myklebust
   5 *
   6 * NFS file delegation management
   7 *
   8 */
   9#include <linux/completion.h>
  10#include <linux/kthread.h>
  11#include <linux/module.h>
  12#include <linux/sched.h>
  13#include <linux/slab.h>
  14#include <linux/spinlock.h>
  15#include <linux/iversion.h>
  16
  17#include <linux/nfs4.h>
  18#include <linux/nfs_fs.h>
  19#include <linux/nfs_xdr.h>
  20
  21#include "nfs4_fs.h"
  22#include "nfs4session.h"
  23#include "delegation.h"
  24#include "internal.h"
  25#include "nfs4trace.h"
  26
  27static void nfs_free_delegation(struct nfs_delegation *delegation)
  28{
  29        if (delegation->cred) {
  30                put_rpccred(delegation->cred);
  31                delegation->cred = NULL;
  32        }
  33        kfree_rcu(delegation, rcu);
  34}
  35
  36/**
  37 * nfs_mark_delegation_referenced - set delegation's REFERENCED flag
  38 * @delegation: delegation to process
  39 *
  40 */
  41void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
  42{
  43        set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
  44}
  45
  46static bool
  47nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
  48                fmode_t flags)
  49{
  50        if (delegation != NULL && (delegation->type & flags) == flags &&
  51            !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
  52            !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
  53                return true;
  54        return false;
  55}
  56
  57static int
  58nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
  59{
  60        struct nfs_delegation *delegation;
  61        int ret = 0;
  62
  63        flags &= FMODE_READ|FMODE_WRITE;
  64        rcu_read_lock();
  65        delegation = rcu_dereference(NFS_I(inode)->delegation);
  66        if (nfs4_is_valid_delegation(delegation, flags)) {
  67                if (mark)
  68                        nfs_mark_delegation_referenced(delegation);
  69                ret = 1;
  70        }
  71        rcu_read_unlock();
  72        return ret;
  73}
  74/**
  75 * nfs_have_delegation - check if inode has a delegation, mark it
  76 * NFS_DELEGATION_REFERENCED if there is one.
  77 * @inode: inode to check
  78 * @flags: delegation types to check for
  79 *
  80 * Returns one if inode has the indicated delegation, otherwise zero.
  81 */
  82int nfs4_have_delegation(struct inode *inode, fmode_t flags)
  83{
  84        return nfs4_do_check_delegation(inode, flags, true);
  85}
  86
  87/*
  88 * nfs4_check_delegation - check if inode has a delegation, do not mark
  89 * NFS_DELEGATION_REFERENCED if it has one.
  90 */
  91int nfs4_check_delegation(struct inode *inode, fmode_t flags)
  92{
  93        return nfs4_do_check_delegation(inode, flags, false);
  94}
  95
  96static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
  97{
  98        struct inode *inode = state->inode;
  99        struct file_lock *fl;
 100        struct file_lock_context *flctx = inode->i_flctx;
 101        struct list_head *list;
 102        int status = 0;
 103
 104        if (flctx == NULL)
 105                goto out;
 106
 107        list = &flctx->flc_posix;
 108        spin_lock(&flctx->flc_lock);
 109restart:
 110        list_for_each_entry(fl, list, fl_list) {
 111                if (nfs_file_open_context(fl->fl_file) != ctx)
 112                        continue;
 113                spin_unlock(&flctx->flc_lock);
 114                status = nfs4_lock_delegation_recall(fl, state, stateid);
 115                if (status < 0)
 116                        goto out;
 117                spin_lock(&flctx->flc_lock);
 118        }
 119        if (list == &flctx->flc_posix) {
 120                list = &flctx->flc_flock;
 121                goto restart;
 122        }
 123        spin_unlock(&flctx->flc_lock);
 124out:
 125        return status;
 126}
 127
 128static int nfs_delegation_claim_opens(struct inode *inode,
 129                const nfs4_stateid *stateid, fmode_t type)
 130{
 131        struct nfs_inode *nfsi = NFS_I(inode);
 132        struct nfs_open_context *ctx;
 133        struct nfs4_state_owner *sp;
 134        struct nfs4_state *state;
 135        unsigned int seq;
 136        int err;
 137
 138again:
 139        spin_lock(&inode->i_lock);
 140        list_for_each_entry(ctx, &nfsi->open_files, list) {
 141                state = ctx->state;
 142                if (state == NULL)
 143                        continue;
 144                if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
 145                        continue;
 146                if (!nfs4_valid_open_stateid(state))
 147                        continue;
 148                if (!nfs4_stateid_match(&state->stateid, stateid))
 149                        continue;
 150                get_nfs_open_context(ctx);
 151                spin_unlock(&inode->i_lock);
 152                sp = state->owner;
 153                /* Block nfs4_proc_unlck */
 154                mutex_lock(&sp->so_delegreturn_mutex);
 155                seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
 156                err = nfs4_open_delegation_recall(ctx, state, stateid, type);
 157                if (!err)
 158                        err = nfs_delegation_claim_locks(ctx, state, stateid);
 159                if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
 160                        err = -EAGAIN;
 161                mutex_unlock(&sp->so_delegreturn_mutex);
 162                put_nfs_open_context(ctx);
 163                if (err != 0)
 164                        return err;
 165                goto again;
 166        }
 167        spin_unlock(&inode->i_lock);
 168        return 0;
 169}
 170
 171/**
 172 * nfs_inode_reclaim_delegation - process a delegation reclaim request
 173 * @inode: inode to process
 174 * @cred: credential to use for request
 175 * @type: delegation type
 176 * @stateid: delegation stateid
 177 * @pagemod_limit: write delegation "space_limit"
 178 *
 179 */
 180void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
 181                                  fmode_t type,
 182                                  const nfs4_stateid *stateid,
 183                                  unsigned long pagemod_limit)
 184{
 185        struct nfs_delegation *delegation;
 186        struct rpc_cred *oldcred = NULL;
 187
 188        rcu_read_lock();
 189        delegation = rcu_dereference(NFS_I(inode)->delegation);
 190        if (delegation != NULL) {
 191                spin_lock(&delegation->lock);
 192                if (delegation->inode != NULL) {
 193                        nfs4_stateid_copy(&delegation->stateid, stateid);
 194                        delegation->type = type;
 195                        delegation->pagemod_limit = pagemod_limit;
 196                        oldcred = delegation->cred;
 197                        delegation->cred = get_rpccred(cred);
 198                        clear_bit(NFS_DELEGATION_NEED_RECLAIM,
 199                                  &delegation->flags);
 200                        spin_unlock(&delegation->lock);
 201                        rcu_read_unlock();
 202                        put_rpccred(oldcred);
 203                        trace_nfs4_reclaim_delegation(inode, type);
 204                        return;
 205                }
 206                /* We appear to have raced with a delegation return. */
 207                spin_unlock(&delegation->lock);
 208        }
 209        rcu_read_unlock();
 210        nfs_inode_set_delegation(inode, cred, type, stateid, pagemod_limit);
 211}
 212
 213static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
 214{
 215        int res = 0;
 216
 217        if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
 218                res = nfs4_proc_delegreturn(inode,
 219                                delegation->cred,
 220                                &delegation->stateid,
 221                                issync);
 222        nfs_free_delegation(delegation);
 223        return res;
 224}
 225
 226static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
 227{
 228        struct inode *inode = NULL;
 229
 230        spin_lock(&delegation->lock);
 231        if (delegation->inode != NULL)
 232                inode = igrab(delegation->inode);
 233        spin_unlock(&delegation->lock);
 234        return inode;
 235}
 236
 237static struct nfs_delegation *
 238nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
 239{
 240        struct nfs_delegation *ret = NULL;
 241        struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
 242
 243        if (delegation == NULL)
 244                goto out;
 245        spin_lock(&delegation->lock);
 246        if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
 247                ret = delegation;
 248        spin_unlock(&delegation->lock);
 249out:
 250        return ret;
 251}
 252
 253static struct nfs_delegation *
 254nfs_start_delegation_return(struct nfs_inode *nfsi)
 255{
 256        struct nfs_delegation *delegation;
 257
 258        rcu_read_lock();
 259        delegation = nfs_start_delegation_return_locked(nfsi);
 260        rcu_read_unlock();
 261        return delegation;
 262}
 263
 264static void
 265nfs_abort_delegation_return(struct nfs_delegation *delegation,
 266                struct nfs_client *clp)
 267{
 268
 269        spin_lock(&delegation->lock);
 270        clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
 271        set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
 272        spin_unlock(&delegation->lock);
 273        set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
 274}
 275
 276static struct nfs_delegation *
 277nfs_detach_delegation_locked(struct nfs_inode *nfsi,
 278                struct nfs_delegation *delegation,
 279                struct nfs_client *clp)
 280{
 281        struct nfs_delegation *deleg_cur =
 282                rcu_dereference_protected(nfsi->delegation,
 283                                lockdep_is_held(&clp->cl_lock));
 284
 285        if (deleg_cur == NULL || delegation != deleg_cur)
 286                return NULL;
 287
 288        spin_lock(&delegation->lock);
 289        set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
 290        list_del_rcu(&delegation->super_list);
 291        delegation->inode = NULL;
 292        rcu_assign_pointer(nfsi->delegation, NULL);
 293        spin_unlock(&delegation->lock);
 294        return delegation;
 295}
 296
 297static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
 298                struct nfs_delegation *delegation,
 299                struct nfs_server *server)
 300{
 301        struct nfs_client *clp = server->nfs_client;
 302
 303        spin_lock(&clp->cl_lock);
 304        delegation = nfs_detach_delegation_locked(nfsi, delegation, clp);
 305        spin_unlock(&clp->cl_lock);
 306        return delegation;
 307}
 308
 309static struct nfs_delegation *
 310nfs_inode_detach_delegation(struct inode *inode)
 311{
 312        struct nfs_inode *nfsi = NFS_I(inode);
 313        struct nfs_server *server = NFS_SERVER(inode);
 314        struct nfs_delegation *delegation;
 315
 316        delegation = nfs_start_delegation_return(nfsi);
 317        if (delegation == NULL)
 318                return NULL;
 319        return nfs_detach_delegation(nfsi, delegation, server);
 320}
 321
 322static void
 323nfs_update_inplace_delegation(struct nfs_delegation *delegation,
 324                const struct nfs_delegation *update)
 325{
 326        if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) {
 327                delegation->stateid.seqid = update->stateid.seqid;
 328                smp_wmb();
 329                delegation->type = update->type;
 330        }
 331}
 332
 333/**
 334 * nfs_inode_set_delegation - set up a delegation on an inode
 335 * @inode: inode to which delegation applies
 336 * @cred: cred to use for subsequent delegation processing
 337 * @type: delegation type
 338 * @stateid: delegation stateid
 339 * @pagemod_limit: write delegation "space_limit"
 340 *
 341 * Returns zero on success, or a negative errno value.
 342 */
 343int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
 344                                  fmode_t type,
 345                                  const nfs4_stateid *stateid,
 346                                  unsigned long pagemod_limit)
 347{
 348        struct nfs_server *server = NFS_SERVER(inode);
 349        struct nfs_client *clp = server->nfs_client;
 350        struct nfs_inode *nfsi = NFS_I(inode);
 351        struct nfs_delegation *delegation, *old_delegation;
 352        struct nfs_delegation *freeme = NULL;
 353        int status = 0;
 354
 355        delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
 356        if (delegation == NULL)
 357                return -ENOMEM;
 358        nfs4_stateid_copy(&delegation->stateid, stateid);
 359        delegation->type = type;
 360        delegation->pagemod_limit = pagemod_limit;
 361        delegation->change_attr = inode_peek_iversion_raw(inode);
 362        delegation->cred = get_rpccred(cred);
 363        delegation->inode = inode;
 364        delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
 365        spin_lock_init(&delegation->lock);
 366
 367        spin_lock(&clp->cl_lock);
 368        old_delegation = rcu_dereference_protected(nfsi->delegation,
 369                                        lockdep_is_held(&clp->cl_lock));
 370        if (old_delegation != NULL) {
 371                /* Is this an update of the existing delegation? */
 372                if (nfs4_stateid_match_other(&old_delegation->stateid,
 373                                        &delegation->stateid)) {
 374                        nfs_update_inplace_delegation(old_delegation,
 375                                        delegation);
 376                        goto out;
 377                }
 378                /*
 379                 * Deal with broken servers that hand out two
 380                 * delegations for the same file.
 381                 * Allow for upgrades to a WRITE delegation, but
 382                 * nothing else.
 383                 */
 384                dfprintk(FILE, "%s: server %s handed out "
 385                                "a duplicate delegation!\n",
 386                                __func__, clp->cl_hostname);
 387                if (delegation->type == old_delegation->type ||
 388                    !(delegation->type & FMODE_WRITE)) {
 389                        freeme = delegation;
 390                        delegation = NULL;
 391                        goto out;
 392                }
 393                if (test_and_set_bit(NFS_DELEGATION_RETURNING,
 394                                        &old_delegation->flags))
 395                        goto out;
 396                freeme = nfs_detach_delegation_locked(nfsi,
 397                                old_delegation, clp);
 398                if (freeme == NULL)
 399                        goto out;
 400        }
 401        list_add_tail_rcu(&delegation->super_list, &server->delegations);
 402        rcu_assign_pointer(nfsi->delegation, delegation);
 403        delegation = NULL;
 404
 405        trace_nfs4_set_delegation(inode, type);
 406
 407        spin_lock(&inode->i_lock);
 408        if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME))
 409                NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED;
 410        spin_unlock(&inode->i_lock);
 411out:
 412        spin_unlock(&clp->cl_lock);
 413        if (delegation != NULL)
 414                nfs_free_delegation(delegation);
 415        if (freeme != NULL)
 416                nfs_do_return_delegation(inode, freeme, 0);
 417        return status;
 418}
 419
 420/*
 421 * Basic procedure for returning a delegation to the server
 422 */
 423static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
 424{
 425        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 426        struct nfs_inode *nfsi = NFS_I(inode);
 427        int err = 0;
 428
 429        if (delegation == NULL)
 430                return 0;
 431        do {
 432                if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
 433                        break;
 434                err = nfs_delegation_claim_opens(inode, &delegation->stateid,
 435                                delegation->type);
 436                if (!issync || err != -EAGAIN)
 437                        break;
 438                /*
 439                 * Guard against state recovery
 440                 */
 441                err = nfs4_wait_clnt_recover(clp);
 442        } while (err == 0);
 443
 444        if (err) {
 445                nfs_abort_delegation_return(delegation, clp);
 446                goto out;
 447        }
 448        if (!nfs_detach_delegation(nfsi, delegation, NFS_SERVER(inode)))
 449                goto out;
 450
 451        err = nfs_do_return_delegation(inode, delegation, issync);
 452out:
 453        return err;
 454}
 455
 456static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
 457{
 458        bool ret = false;
 459
 460        if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
 461                goto out;
 462        if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
 463                ret = true;
 464        if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) {
 465                struct inode *inode;
 466
 467                spin_lock(&delegation->lock);
 468                inode = delegation->inode;
 469                if (inode && list_empty(&NFS_I(inode)->open_files))
 470                        ret = true;
 471                spin_unlock(&delegation->lock);
 472        }
 473out:
 474        return ret;
 475}
 476
 477/**
 478 * nfs_client_return_marked_delegations - return previously marked delegations
 479 * @clp: nfs_client to process
 480 *
 481 * Note that this function is designed to be called by the state
 482 * manager thread. For this reason, it cannot flush the dirty data,
 483 * since that could deadlock in case of a state recovery error.
 484 *
 485 * Returns zero on success, or a negative errno value.
 486 */
 487int nfs_client_return_marked_delegations(struct nfs_client *clp)
 488{
 489        struct nfs_delegation *delegation;
 490        struct nfs_delegation *prev;
 491        struct nfs_server *server;
 492        struct inode *inode;
 493        struct inode *place_holder = NULL;
 494        struct nfs_delegation *place_holder_deleg = NULL;
 495        int err = 0;
 496
 497restart:
 498        /*
 499         * To avoid quadratic looping we hold a reference
 500         * to an inode place_holder.  Each time we restart, we
 501         * list nfs_servers from the server of that inode, and
 502         * delegation in the server from the delegations of that
 503         * inode.
 504         * prev is an RCU-protected pointer to a delegation which
 505         * wasn't marked for return and might be a good choice for
 506         * the next place_holder.
 507         */
 508        rcu_read_lock();
 509        prev = NULL;
 510        if (place_holder)
 511                server = NFS_SERVER(place_holder);
 512        else
 513                server = list_entry_rcu(clp->cl_superblocks.next,
 514                                        struct nfs_server, client_link);
 515        list_for_each_entry_from_rcu(server, &clp->cl_superblocks, client_link) {
 516                delegation = NULL;
 517                if (place_holder && server == NFS_SERVER(place_holder))
 518                        delegation = rcu_dereference(NFS_I(place_holder)->delegation);
 519                if (!delegation || delegation != place_holder_deleg)
 520                        delegation = list_entry_rcu(server->delegations.next,
 521                                                    struct nfs_delegation, super_list);
 522                list_for_each_entry_from_rcu(delegation, &server->delegations, super_list) {
 523                        struct inode *to_put = NULL;
 524
 525                        if (!nfs_delegation_need_return(delegation)) {
 526                                prev = delegation;
 527                                continue;
 528                        }
 529                        if (!nfs_sb_active(server->super))
 530                                break; /* continue in outer loop */
 531
 532                        if (prev) {
 533                                struct inode *tmp;
 534
 535                                tmp = nfs_delegation_grab_inode(prev);
 536                                if (tmp) {
 537                                        to_put = place_holder;
 538                                        place_holder = tmp;
 539                                        place_holder_deleg = prev;
 540                                }
 541                        }
 542
 543                        inode = nfs_delegation_grab_inode(delegation);
 544                        if (inode == NULL) {
 545                                rcu_read_unlock();
 546                                if (to_put)
 547                                        iput(to_put);
 548                                nfs_sb_deactive(server->super);
 549                                goto restart;
 550                        }
 551                        delegation = nfs_start_delegation_return_locked(NFS_I(inode));
 552                        rcu_read_unlock();
 553
 554                        if (to_put)
 555                                iput(to_put);
 556
 557                        err = nfs_end_delegation_return(inode, delegation, 0);
 558                        iput(inode);
 559                        nfs_sb_deactive(server->super);
 560                        cond_resched();
 561                        if (!err)
 562                                goto restart;
 563                        set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
 564                        if (place_holder)
 565                                iput(place_holder);
 566                        return err;
 567                }
 568        }
 569        rcu_read_unlock();
 570        if (place_holder)
 571                iput(place_holder);
 572        return 0;
 573}
 574
 575/**
 576 * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
 577 * @inode: inode to process
 578 *
 579 * Does not protect against delegation reclaims, therefore really only safe
 580 * to be called from nfs4_clear_inode().
 581 */
 582void nfs_inode_return_delegation_noreclaim(struct inode *inode)
 583{
 584        struct nfs_delegation *delegation;
 585
 586        delegation = nfs_inode_detach_delegation(inode);
 587        if (delegation != NULL)
 588                nfs_do_return_delegation(inode, delegation, 1);
 589}
 590
 591/**
 592 * nfs_inode_return_delegation - synchronously return a delegation
 593 * @inode: inode to process
 594 *
 595 * This routine will always flush any dirty data to disk on the
 596 * assumption that if we need to return the delegation, then
 597 * we should stop caching.
 598 *
 599 * Returns zero on success, or a negative errno value.
 600 */
 601int nfs4_inode_return_delegation(struct inode *inode)
 602{
 603        struct nfs_inode *nfsi = NFS_I(inode);
 604        struct nfs_delegation *delegation;
 605        int err = 0;
 606
 607        nfs_wb_all(inode);
 608        delegation = nfs_start_delegation_return(nfsi);
 609        if (delegation != NULL)
 610                err = nfs_end_delegation_return(inode, delegation, 1);
 611        return err;
 612}
 613
 614/**
 615 * nfs4_inode_make_writeable
 616 * @inode: pointer to inode
 617 *
 618 * Make the inode writeable by returning the delegation if necessary
 619 *
 620 * Returns zero on success, or a negative errno value.
 621 */
 622int nfs4_inode_make_writeable(struct inode *inode)
 623{
 624        if (!nfs4_has_session(NFS_SERVER(inode)->nfs_client) ||
 625            !nfs4_check_delegation(inode, FMODE_WRITE))
 626                return nfs4_inode_return_delegation(inode);
 627        return 0;
 628}
 629
 630static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
 631                struct nfs_delegation *delegation)
 632{
 633        set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
 634        set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
 635}
 636
 637static void nfs_mark_return_delegation(struct nfs_server *server,
 638                struct nfs_delegation *delegation)
 639{
 640        set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
 641        set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
 642}
 643
 644static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
 645{
 646        struct nfs_delegation *delegation;
 647        bool ret = false;
 648
 649        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 650                nfs_mark_return_delegation(server, delegation);
 651                ret = true;
 652        }
 653        return ret;
 654}
 655
 656static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
 657{
 658        struct nfs_server *server;
 659
 660        rcu_read_lock();
 661        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
 662                nfs_server_mark_return_all_delegations(server);
 663        rcu_read_unlock();
 664}
 665
 666static void nfs_delegation_run_state_manager(struct nfs_client *clp)
 667{
 668        if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
 669                nfs4_schedule_state_manager(clp);
 670}
 671
 672/**
 673 * nfs_expire_all_delegations
 674 * @clp: client to process
 675 *
 676 */
 677void nfs_expire_all_delegations(struct nfs_client *clp)
 678{
 679        nfs_client_mark_return_all_delegations(clp);
 680        nfs_delegation_run_state_manager(clp);
 681}
 682
 683/**
 684 * nfs_super_return_all_delegations - return delegations for one superblock
 685 * @sb: sb to process
 686 *
 687 */
 688void nfs_server_return_all_delegations(struct nfs_server *server)
 689{
 690        struct nfs_client *clp = server->nfs_client;
 691        bool need_wait;
 692
 693        if (clp == NULL)
 694                return;
 695
 696        rcu_read_lock();
 697        need_wait = nfs_server_mark_return_all_delegations(server);
 698        rcu_read_unlock();
 699
 700        if (need_wait) {
 701                nfs4_schedule_state_manager(clp);
 702                nfs4_wait_clnt_recover(clp);
 703        }
 704}
 705
 706static void nfs_mark_return_unused_delegation_types(struct nfs_server *server,
 707                                                 fmode_t flags)
 708{
 709        struct nfs_delegation *delegation;
 710
 711        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 712                if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
 713                        continue;
 714                if (delegation->type & flags)
 715                        nfs_mark_return_if_closed_delegation(server, delegation);
 716        }
 717}
 718
 719static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *clp,
 720                                                        fmode_t flags)
 721{
 722        struct nfs_server *server;
 723
 724        rcu_read_lock();
 725        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
 726                nfs_mark_return_unused_delegation_types(server, flags);
 727        rcu_read_unlock();
 728}
 729
 730static void nfs_mark_delegation_revoked(struct nfs_server *server,
 731                struct nfs_delegation *delegation)
 732{
 733        set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
 734        delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
 735        nfs_mark_return_delegation(server, delegation);
 736}
 737
 738static bool nfs_revoke_delegation(struct inode *inode,
 739                const nfs4_stateid *stateid)
 740{
 741        struct nfs_delegation *delegation;
 742        nfs4_stateid tmp;
 743        bool ret = false;
 744
 745        rcu_read_lock();
 746        delegation = rcu_dereference(NFS_I(inode)->delegation);
 747        if (delegation == NULL)
 748                goto out;
 749        if (stateid == NULL) {
 750                nfs4_stateid_copy(&tmp, &delegation->stateid);
 751                stateid = &tmp;
 752        } else if (!nfs4_stateid_match(stateid, &delegation->stateid))
 753                goto out;
 754        nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
 755        ret = true;
 756out:
 757        rcu_read_unlock();
 758        if (ret)
 759                nfs_inode_find_state_and_recover(inode, stateid);
 760        return ret;
 761}
 762
 763void nfs_remove_bad_delegation(struct inode *inode,
 764                const nfs4_stateid *stateid)
 765{
 766        struct nfs_delegation *delegation;
 767
 768        if (!nfs_revoke_delegation(inode, stateid))
 769                return;
 770        delegation = nfs_inode_detach_delegation(inode);
 771        if (delegation)
 772                nfs_free_delegation(delegation);
 773}
 774EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
 775
 776/**
 777 * nfs_expire_unused_delegation_types
 778 * @clp: client to process
 779 * @flags: delegation types to expire
 780 *
 781 */
 782void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags)
 783{
 784        nfs_client_mark_return_unused_delegation_types(clp, flags);
 785        nfs_delegation_run_state_manager(clp);
 786}
 787
 788static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
 789{
 790        struct nfs_delegation *delegation;
 791
 792        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 793                if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
 794                        continue;
 795                nfs_mark_return_if_closed_delegation(server, delegation);
 796        }
 797}
 798
 799/**
 800 * nfs_expire_unreferenced_delegations - Eliminate unused delegations
 801 * @clp: nfs_client to process
 802 *
 803 */
 804void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
 805{
 806        struct nfs_server *server;
 807
 808        rcu_read_lock();
 809        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
 810                nfs_mark_return_unreferenced_delegations(server);
 811        rcu_read_unlock();
 812
 813        nfs_delegation_run_state_manager(clp);
 814}
 815
 816/**
 817 * nfs_async_inode_return_delegation - asynchronously return a delegation
 818 * @inode: inode to process
 819 * @stateid: state ID information
 820 *
 821 * Returns zero on success, or a negative errno value.
 822 */
 823int nfs_async_inode_return_delegation(struct inode *inode,
 824                                      const nfs4_stateid *stateid)
 825{
 826        struct nfs_server *server = NFS_SERVER(inode);
 827        struct nfs_client *clp = server->nfs_client;
 828        struct nfs_delegation *delegation;
 829
 830        rcu_read_lock();
 831        delegation = rcu_dereference(NFS_I(inode)->delegation);
 832        if (delegation == NULL)
 833                goto out_enoent;
 834        if (stateid != NULL &&
 835            !clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
 836                goto out_enoent;
 837        nfs_mark_return_delegation(server, delegation);
 838        rcu_read_unlock();
 839
 840        nfs_delegation_run_state_manager(clp);
 841        return 0;
 842out_enoent:
 843        rcu_read_unlock();
 844        return -ENOENT;
 845}
 846
 847static struct inode *
 848nfs_delegation_find_inode_server(struct nfs_server *server,
 849                                 const struct nfs_fh *fhandle)
 850{
 851        struct nfs_delegation *delegation;
 852        struct inode *res = NULL;
 853
 854        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 855                spin_lock(&delegation->lock);
 856                if (delegation->inode != NULL &&
 857                    nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
 858                        res = igrab(delegation->inode);
 859                        spin_unlock(&delegation->lock);
 860                        if (res != NULL)
 861                                return res;
 862                        return ERR_PTR(-EAGAIN);
 863                }
 864                spin_unlock(&delegation->lock);
 865        }
 866        return ERR_PTR(-ENOENT);
 867}
 868
 869/**
 870 * nfs_delegation_find_inode - retrieve the inode associated with a delegation
 871 * @clp: client state handle
 872 * @fhandle: filehandle from a delegation recall
 873 *
 874 * Returns pointer to inode matching "fhandle," or NULL if a matching inode
 875 * cannot be found.
 876 */
 877struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
 878                                        const struct nfs_fh *fhandle)
 879{
 880        struct nfs_server *server;
 881        struct inode *res;
 882
 883        rcu_read_lock();
 884        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 885                res = nfs_delegation_find_inode_server(server, fhandle);
 886                if (res != ERR_PTR(-ENOENT)) {
 887                        rcu_read_unlock();
 888                        return res;
 889                }
 890        }
 891        rcu_read_unlock();
 892        return ERR_PTR(-ENOENT);
 893}
 894
 895static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
 896{
 897        struct nfs_delegation *delegation;
 898
 899        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 900                /*
 901                 * If the delegation may have been admin revoked, then we
 902                 * cannot reclaim it.
 903                 */
 904                if (test_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags))
 905                        continue;
 906                set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
 907        }
 908}
 909
 910/**
 911 * nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed
 912 * @clp: nfs_client to process
 913 *
 914 */
 915void nfs_delegation_mark_reclaim(struct nfs_client *clp)
 916{
 917        struct nfs_server *server;
 918
 919        rcu_read_lock();
 920        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
 921                nfs_delegation_mark_reclaim_server(server);
 922        rcu_read_unlock();
 923}
 924
 925/**
 926 * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
 927 * @clp: nfs_client to process
 928 *
 929 */
 930void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
 931{
 932        struct nfs_delegation *delegation;
 933        struct nfs_server *server;
 934        struct inode *inode;
 935
 936restart:
 937        rcu_read_lock();
 938        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 939                list_for_each_entry_rcu(delegation, &server->delegations,
 940                                                                super_list) {
 941                        if (test_bit(NFS_DELEGATION_RETURNING,
 942                                                &delegation->flags))
 943                                continue;
 944                        if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
 945                                                &delegation->flags) == 0)
 946                                continue;
 947                        if (!nfs_sb_active(server->super))
 948                                break; /* continue in outer loop */
 949                        inode = nfs_delegation_grab_inode(delegation);
 950                        if (inode == NULL) {
 951                                rcu_read_unlock();
 952                                nfs_sb_deactive(server->super);
 953                                goto restart;
 954                        }
 955                        delegation = nfs_start_delegation_return_locked(NFS_I(inode));
 956                        rcu_read_unlock();
 957                        if (delegation != NULL) {
 958                                delegation = nfs_detach_delegation(NFS_I(inode),
 959                                        delegation, server);
 960                                if (delegation != NULL)
 961                                        nfs_free_delegation(delegation);
 962                        }
 963                        iput(inode);
 964                        nfs_sb_deactive(server->super);
 965                        cond_resched();
 966                        goto restart;
 967                }
 968        }
 969        rcu_read_unlock();
 970}
 971
 972static inline bool nfs4_server_rebooted(const struct nfs_client *clp)
 973{
 974        return (clp->cl_state & (BIT(NFS4CLNT_CHECK_LEASE) |
 975                                BIT(NFS4CLNT_LEASE_EXPIRED) |
 976                                BIT(NFS4CLNT_SESSION_RESET))) != 0;
 977}
 978
 979static void nfs_mark_test_expired_delegation(struct nfs_server *server,
 980            struct nfs_delegation *delegation)
 981{
 982        if (delegation->stateid.type == NFS4_INVALID_STATEID_TYPE)
 983                return;
 984        clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
 985        set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
 986        set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state);
 987}
 988
 989static void nfs_inode_mark_test_expired_delegation(struct nfs_server *server,
 990                struct inode *inode)
 991{
 992        struct nfs_delegation *delegation;
 993
 994        rcu_read_lock();
 995        delegation = rcu_dereference(NFS_I(inode)->delegation);
 996        if (delegation)
 997                nfs_mark_test_expired_delegation(server, delegation);
 998        rcu_read_unlock();
 999
1000}
1001
1002static void nfs_delegation_mark_test_expired_server(struct nfs_server *server)
1003{
1004        struct nfs_delegation *delegation;
1005
1006        list_for_each_entry_rcu(delegation, &server->delegations, super_list)
1007                nfs_mark_test_expired_delegation(server, delegation);
1008}
1009
1010/**
1011 * nfs_mark_test_expired_all_delegations - mark all delegations for testing
1012 * @clp: nfs_client to process
1013 *
1014 * Iterates through all the delegations associated with this server and
1015 * marks them as needing to be checked for validity.
1016 */
1017void nfs_mark_test_expired_all_delegations(struct nfs_client *clp)
1018{
1019        struct nfs_server *server;
1020
1021        rcu_read_lock();
1022        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
1023                nfs_delegation_mark_test_expired_server(server);
1024        rcu_read_unlock();
1025}
1026
1027/**
1028 * nfs_reap_expired_delegations - reap expired delegations
1029 * @clp: nfs_client to process
1030 *
1031 * Iterates through all the delegations associated with this server and
1032 * checks if they have may have been revoked. This function is usually
1033 * expected to be called in cases where the server may have lost its
1034 * lease.
1035 */
1036void nfs_reap_expired_delegations(struct nfs_client *clp)
1037{
1038        const struct nfs4_minor_version_ops *ops = clp->cl_mvops;
1039        struct nfs_delegation *delegation;
1040        struct nfs_server *server;
1041        struct inode *inode;
1042        struct rpc_cred *cred;
1043        nfs4_stateid stateid;
1044
1045restart:
1046        rcu_read_lock();
1047        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
1048                list_for_each_entry_rcu(delegation, &server->delegations,
1049                                                                super_list) {
1050                        if (test_bit(NFS_DELEGATION_RETURNING,
1051                                                &delegation->flags))
1052                                continue;
1053                        if (test_bit(NFS_DELEGATION_TEST_EXPIRED,
1054                                                &delegation->flags) == 0)
1055                                continue;
1056                        if (!nfs_sb_active(server->super))
1057                                break; /* continue in outer loop */
1058                        inode = nfs_delegation_grab_inode(delegation);
1059                        if (inode == NULL) {
1060                                rcu_read_unlock();
1061                                nfs_sb_deactive(server->super);
1062                                goto restart;
1063                        }
1064                        cred = get_rpccred_rcu(delegation->cred);
1065                        nfs4_stateid_copy(&stateid, &delegation->stateid);
1066                        clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
1067                        rcu_read_unlock();
1068                        if (cred != NULL &&
1069                            ops->test_and_free_expired(server, &stateid, cred) < 0) {
1070                                nfs_revoke_delegation(inode, &stateid);
1071                                nfs_inode_find_state_and_recover(inode, &stateid);
1072                        }
1073                        put_rpccred(cred);
1074                        if (nfs4_server_rebooted(clp)) {
1075                                nfs_inode_mark_test_expired_delegation(server,inode);
1076                                iput(inode);
1077                                nfs_sb_deactive(server->super);
1078                                return;
1079                        }
1080                        iput(inode);
1081                        nfs_sb_deactive(server->super);
1082                        cond_resched();
1083                        goto restart;
1084                }
1085        }
1086        rcu_read_unlock();
1087}
1088
1089void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
1090                const nfs4_stateid *stateid)
1091{
1092        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
1093        struct nfs_delegation *delegation;
1094        bool found = false;
1095
1096        rcu_read_lock();
1097        delegation = rcu_dereference(NFS_I(inode)->delegation);
1098        if (delegation &&
1099            nfs4_stateid_match_other(&delegation->stateid, stateid)) {
1100                nfs_mark_test_expired_delegation(NFS_SERVER(inode), delegation);
1101                found = true;
1102        }
1103        rcu_read_unlock();
1104        if (found)
1105                nfs4_schedule_state_manager(clp);
1106}
1107
1108/**
1109 * nfs_delegations_present - check for existence of delegations
1110 * @clp: client state handle
1111 *
1112 * Returns one if there are any nfs_delegation structures attached
1113 * to this nfs_client.
1114 */
1115int nfs_delegations_present(struct nfs_client *clp)
1116{
1117        struct nfs_server *server;
1118        int ret = 0;
1119
1120        rcu_read_lock();
1121        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
1122                if (!list_empty(&server->delegations)) {
1123                        ret = 1;
1124                        break;
1125                }
1126        rcu_read_unlock();
1127        return ret;
1128}
1129
1130/**
1131 * nfs4_refresh_delegation_stateid - Update delegation stateid seqid
1132 * @dst: stateid to refresh
1133 * @inode: inode to check
1134 *
1135 * Returns "true" and updates "dst->seqid" * if inode had a delegation
1136 * that matches our delegation stateid. Otherwise "false" is returned.
1137 */
1138bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
1139{
1140        struct nfs_delegation *delegation;
1141        bool ret = false;
1142        if (!inode)
1143                goto out;
1144
1145        rcu_read_lock();
1146        delegation = rcu_dereference(NFS_I(inode)->delegation);
1147        if (delegation != NULL &&
1148            nfs4_stateid_match_other(dst, &delegation->stateid)) {
1149                dst->seqid = delegation->stateid.seqid;
1150                return ret;
1151        }
1152        rcu_read_unlock();
1153out:
1154        return ret;
1155}
1156
1157/**
1158 * nfs4_copy_delegation_stateid - Copy inode's state ID information
1159 * @inode: inode to check
1160 * @flags: delegation type requirement
1161 * @dst: stateid data structure to fill in
1162 * @cred: optional argument to retrieve credential
1163 *
1164 * Returns "true" and fills in "dst->data" * if inode had a delegation,
1165 * otherwise "false" is returned.
1166 */
1167bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags,
1168                nfs4_stateid *dst, struct rpc_cred **cred)
1169{
1170        struct nfs_inode *nfsi = NFS_I(inode);
1171        struct nfs_delegation *delegation;
1172        bool ret;
1173
1174        flags &= FMODE_READ|FMODE_WRITE;
1175        rcu_read_lock();
1176        delegation = rcu_dereference(nfsi->delegation);
1177        ret = nfs4_is_valid_delegation(delegation, flags);
1178        if (ret) {
1179                nfs4_stateid_copy(dst, &delegation->stateid);
1180                nfs_mark_delegation_referenced(delegation);
1181                if (cred)
1182                        *cred = get_rpccred(delegation->cred);
1183        }
1184        rcu_read_unlock();
1185        return ret;
1186}
1187
1188/**
1189 * nfs4_delegation_flush_on_close - Check if we must flush file on close
1190 * @inode: inode to check
1191 *
1192 * This function checks the number of outstanding writes to the file
1193 * against the delegation 'space_limit' field to see if
1194 * the spec requires us to flush the file on close.
1195 */
1196bool nfs4_delegation_flush_on_close(const struct inode *inode)
1197{
1198        struct nfs_inode *nfsi = NFS_I(inode);
1199        struct nfs_delegation *delegation;
1200        bool ret = true;
1201
1202        rcu_read_lock();
1203        delegation = rcu_dereference(nfsi->delegation);
1204        if (delegation == NULL || !(delegation->type & FMODE_WRITE))
1205                goto out;
1206        if (atomic_long_read(&nfsi->nrequests) < delegation->pagemod_limit)
1207                ret = false;
1208out:
1209        rcu_read_unlock();
1210        return ret;
1211}
1212