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