/* Reduce the fore channel's max_slots to the target value */ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy) { struct nfs_client *clp; struct nfs4_slot_table *fc_tbl; __be32 status; status = htonl(NFS4ERR_OP_NOT_IN_SESSION); clp = nfs_find_client(args->crsa_addr, 4); if (clp == NULL) goto out; dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), args->crsa_target_max_slots); fc_tbl = &clp->cl_session->fc_slot_table; status = htonl(NFS4ERR_BAD_HIGH_SLOT); if (args->crsa_target_max_slots > fc_tbl->max_slots || args->crsa_target_max_slots < 1) goto out_putclient; status = htonl(NFS4_OK); if (args->crsa_target_max_slots == fc_tbl->max_slots) goto out_putclient; fc_tbl->target_max_slots = args->crsa_target_max_slots; nfs41_handle_recall_slot(clp); out_putclient: nfs_put_client(clp); /* balance nfs_find_client */ out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; }
__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) { struct nfs_client *clp; __be32 status; fmode_t flags = 0; status = htonl(NFS4ERR_OP_NOT_IN_SESSION); clp = nfs_find_client(args->craa_addr, 4); if (clp == NULL) goto out; dprintk("NFS: RECALL_ANY callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags = FMODE_READ; if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *) &args->craa_type_mask)) flags |= FMODE_WRITE; if (flags) nfs_expire_all_delegation_types(clp, flags); status = htonl(NFS4_OK); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); return status; }
/* * Returns a pointer to a held 'struct nfs_client' that matches the server's * address, major version number, and session ID. It is the caller's * responsibility to release the returned reference. * * Returns NULL if there are no connections with sessions, or if no session * matches the one of interest. */ static struct nfs_client *find_client_with_session( const struct sockaddr *addr, u32 nfsversion, struct nfs4_sessionid *sessionid) { struct nfs_client *clp; clp = nfs_find_client(addr, 4); if (clp == NULL) return NULL; do { struct nfs_client *prev = clp; if (clp->cl_session != NULL) { if (memcmp(clp->cl_session->sess_id.data, sessionid->data, NFS4_MAX_SESSIONID_LEN) == 0) { /* Returns a held reference to clp */ return clp; } } clp = nfs_find_client_next(prev); nfs_put_client(prev); } while (clp != NULL); return NULL; }
static int nfs_callback_authenticate(struct svc_rqst *rqstp) { struct nfs_client *clp; RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); int ret = SVC_OK; /* Don't talk to strangers */ clp = nfs_find_client(svc_addr(rqstp), 4); if (clp == NULL) return SVC_DROP; dprintk("%s: %s NFSv4 callback!\n", __func__, svc_print_addr(rqstp, buf, sizeof(buf))); switch (rqstp->rq_authop->flavour) { case RPC_AUTH_NULL: if (rqstp->rq_proc != CB_NULL) ret = SVC_DENIED; break; case RPC_AUTH_UNIX: break; case RPC_AUTH_GSS: ret = check_gss_callback_principal(clp, rqstp); break; default: ret = SVC_DENIED; } nfs_put_client(clp); return ret; }
__be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) { struct nfs_client *clp; struct nfs_delegation *delegation; struct nfs_inode *nfsi; struct inode *inode; res->bitmap[0] = res->bitmap[1] = 0; res->status = htonl(NFS4ERR_BADHANDLE); clp = nfs_find_client(args->addr, 4); if (clp == NULL) goto out; dprintk("NFS: GETATTR callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); inode = nfs_delegation_find_inode(clp, &args->fh); if (inode == NULL) goto out_putclient; nfsi = NFS_I(inode); rcu_read_lock(); delegation = rcu_dereference(nfsi->delegation); if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) goto out_iput; res->size = i_size_read(inode); res->change_attr = delegation->change_attr; if (nfsi->npages != 0) res->change_attr++; res->ctime = inode->i_ctime; res->mtime = inode->i_mtime; res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) & args->bitmap[0]; res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) & args->bitmap[1]; res->status = 0; out_iput: rcu_read_unlock(); iput(inode); out_putclient: nfs_put_client(clp); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status)); return res->status; }
__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { struct nfs_client *clp; struct inode *inode; __be32 res; res = htonl(NFS4ERR_BADHANDLE); clp = nfs_find_client(args->addr, 4); if (clp == NULL) goto out; dprintk("NFS: RECALL callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); do { struct nfs_client *prev = clp; inode = nfs_delegation_find_inode(clp, &args->fh); if (inode != NULL) { /* Set up a helper thread to actually return the delegation */ switch (nfs_async_inode_return_delegation(inode, &args->stateid, nfs_validate_delegation_stateid(clp))) { case 0: res = 0; break; case -ENOENT: if (res != 0) res = htonl(NFS4ERR_BAD_STATEID); break; default: res = htonl(NFS4ERR_RESOURCE); } iput(inode); } clp = nfs_find_client_next(prev); nfs_put_client(prev); } while (clp != NULL); out: dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); return res; }