mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
NFS: Generalise the nfs_client structure
Generalise the nfs_client structure by: (1) Moving nfs_client to a more general place (nfs_fs_sb.h). (2) Renaming its maintenance routines to be non-NFS4 specific. (3) Move those maintenance routines to a new non-NFS4 specific file (client.c) and move the declarations to internal.h. (4) Make nfs_find/get_client() take a full sockaddr_in to include the port number (will be required for NFS2/3). (5) Make nfs_find/get_client() take the NFS protocol version (again will be required to differentiate NFS2, 3 & 4 client records). Also: (6) Make nfs_client construction proceed akin to inodes, marking them as under construction and providing a function to indicate completion. (7) Make nfs_get_client() wait interruptibly if it finds a client that it can share, but that client is currently being constructed. (8) Make nfs4_create_client() use (6) and (7) instead of locking cl_sem. Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
e9326dcab4
commit
24c8dbbb5f
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_NFS_FS) += nfs.o
|
obj-$(CONFIG_NFS_FS) += nfs.o
|
||||||
|
|
||||||
nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \
|
nfs-y := client.o dir.o file.o inode.o super.o nfs2xdr.o \
|
||||||
proc.o read.o symlink.o unlink.o write.o \
|
pagelist.o proc.o read.o symlink.o unlink.o \
|
||||||
namespace.o
|
write.o namespace.o
|
||||||
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
|
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
|
||||||
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
|
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
|
||||||
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
|
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "nfs4_fs.h"
|
#include "nfs4_fs.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
||||||
|
|
||||||
@ -166,15 +167,15 @@ void nfs_callback_down(void)
|
|||||||
|
|
||||||
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
|
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
|
||||||
{
|
{
|
||||||
struct in_addr *addr = &rqstp->rq_addr.sin_addr;
|
struct sockaddr_in *addr = &rqstp->rq_addr;
|
||||||
struct nfs_client *clp;
|
struct nfs_client *clp;
|
||||||
|
|
||||||
/* Don't talk to strangers */
|
/* Don't talk to strangers */
|
||||||
clp = nfs4_find_client(addr);
|
clp = nfs_find_client(addr, 4);
|
||||||
if (clp == NULL)
|
if (clp == NULL)
|
||||||
return SVC_DROP;
|
return SVC_DROP;
|
||||||
dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
|
dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
switch (rqstp->rq_authop->flavour) {
|
switch (rqstp->rq_authop->flavour) {
|
||||||
case RPC_AUTH_NULL:
|
case RPC_AUTH_NULL:
|
||||||
if (rqstp->rq_proc != CB_NULL)
|
if (rqstp->rq_proc != CB_NULL)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "nfs4_fs.h"
|
#include "nfs4_fs.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
#include "delegation.h"
|
#include "delegation.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
#define NFSDBG_FACILITY NFSDBG_CALLBACK
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres
|
|||||||
|
|
||||||
res->bitmap[0] = res->bitmap[1] = 0;
|
res->bitmap[0] = res->bitmap[1] = 0;
|
||||||
res->status = htonl(NFS4ERR_BADHANDLE);
|
res->status = htonl(NFS4ERR_BADHANDLE);
|
||||||
clp = nfs4_find_client(&args->addr->sin_addr);
|
clp = nfs_find_client(args->addr, 4);
|
||||||
if (clp == NULL)
|
if (clp == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
inode = nfs_delegation_find_inode(clp, &args->fh);
|
inode = nfs_delegation_find_inode(clp, &args->fh);
|
||||||
@ -48,7 +49,7 @@ out_iput:
|
|||||||
up_read(&nfsi->rwsem);
|
up_read(&nfsi->rwsem);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
out_putclient:
|
out_putclient:
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
out:
|
out:
|
||||||
dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status));
|
dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status));
|
||||||
return res->status;
|
return res->status;
|
||||||
@ -61,7 +62,7 @@ unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
|
|||||||
unsigned res;
|
unsigned res;
|
||||||
|
|
||||||
res = htonl(NFS4ERR_BADHANDLE);
|
res = htonl(NFS4ERR_BADHANDLE);
|
||||||
clp = nfs4_find_client(&args->addr->sin_addr);
|
clp = nfs_find_client(args->addr, 4);
|
||||||
if (clp == NULL)
|
if (clp == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
inode = nfs_delegation_find_inode(clp, &args->fh);
|
inode = nfs_delegation_find_inode(clp, &args->fh);
|
||||||
@ -80,7 +81,7 @@ unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
|
|||||||
}
|
}
|
||||||
iput(inode);
|
iput(inode);
|
||||||
out_putclient:
|
out_putclient:
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
out:
|
out:
|
||||||
dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res));
|
dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res));
|
||||||
return res;
|
return res;
|
||||||
|
312
fs/nfs/client.c
Normal file
312
fs/nfs/client.c
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/* client.c: NFS client sharing and management code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/stat.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
#include <linux/sunrpc/clnt.h>
|
||||||
|
#include <linux/sunrpc/stats.h>
|
||||||
|
#include <linux/sunrpc/metrics.h>
|
||||||
|
#include <linux/nfs_fs.h>
|
||||||
|
#include <linux/nfs_mount.h>
|
||||||
|
#include <linux/nfs4_mount.h>
|
||||||
|
#include <linux/lockd/bind.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
#include <linux/nfs_idmap.h>
|
||||||
|
#include <linux/vfs.h>
|
||||||
|
#include <linux/inet.h>
|
||||||
|
#include <linux/nfs_xdr.h>
|
||||||
|
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#include "nfs4_fs.h"
|
||||||
|
#include "callback.h"
|
||||||
|
#include "delegation.h"
|
||||||
|
#include "iostat.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define NFSDBG_FACILITY NFSDBG_CLIENT
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(nfs_client_lock);
|
||||||
|
static LIST_HEAD(nfs_client_list);
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a shared client record
|
||||||
|
*
|
||||||
|
* Since these are allocated/deallocated very rarely, we don't
|
||||||
|
* bother putting them in a slab cache...
|
||||||
|
*/
|
||||||
|
static struct nfs_client *nfs_alloc_client(const char *hostname,
|
||||||
|
const struct sockaddr_in *addr,
|
||||||
|
int nfsversion)
|
||||||
|
{
|
||||||
|
struct nfs_client *clp;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
|
||||||
|
goto error_0;
|
||||||
|
|
||||||
|
error = rpciod_up();
|
||||||
|
if (error < 0) {
|
||||||
|
dprintk("%s: couldn't start rpciod! Error = %d\n",
|
||||||
|
__FUNCTION__, error);
|
||||||
|
__set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
|
||||||
|
goto error_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfsversion == 4) {
|
||||||
|
if (nfs_callback_up() < 0)
|
||||||
|
goto error_2;
|
||||||
|
__set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_set(&clp->cl_count, 1);
|
||||||
|
clp->cl_cons_state = NFS_CS_INITING;
|
||||||
|
|
||||||
|
clp->cl_nfsversion = nfsversion;
|
||||||
|
memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
|
||||||
|
|
||||||
|
if (hostname) {
|
||||||
|
clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
|
||||||
|
if (!clp->cl_hostname)
|
||||||
|
goto error_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&clp->cl_superblocks);
|
||||||
|
clp->cl_rpcclient = ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
init_rwsem(&clp->cl_sem);
|
||||||
|
INIT_LIST_HEAD(&clp->cl_delegations);
|
||||||
|
INIT_LIST_HEAD(&clp->cl_state_owners);
|
||||||
|
INIT_LIST_HEAD(&clp->cl_unused);
|
||||||
|
spin_lock_init(&clp->cl_lock);
|
||||||
|
INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
|
||||||
|
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
|
||||||
|
clp->cl_boot_time = CURRENT_TIME;
|
||||||
|
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return clp;
|
||||||
|
|
||||||
|
error_3:
|
||||||
|
nfs_callback_down();
|
||||||
|
__clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
|
||||||
|
error_2:
|
||||||
|
rpciod_down();
|
||||||
|
__clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
|
||||||
|
error_1:
|
||||||
|
kfree(clp);
|
||||||
|
error_0:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a shared client record
|
||||||
|
*/
|
||||||
|
static void nfs_free_client(struct nfs_client *clp)
|
||||||
|
{
|
||||||
|
dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) {
|
||||||
|
while (!list_empty(&clp->cl_unused)) {
|
||||||
|
struct nfs4_state_owner *sp;
|
||||||
|
|
||||||
|
sp = list_entry(clp->cl_unused.next,
|
||||||
|
struct nfs4_state_owner,
|
||||||
|
so_list);
|
||||||
|
list_del(&sp->so_list);
|
||||||
|
kfree(sp);
|
||||||
|
}
|
||||||
|
BUG_ON(!list_empty(&clp->cl_state_owners));
|
||||||
|
nfs_idmap_delete(clp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* -EIO all pending I/O */
|
||||||
|
if (!IS_ERR(clp->cl_rpcclient))
|
||||||
|
rpc_shutdown_client(clp->cl_rpcclient);
|
||||||
|
|
||||||
|
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
|
||||||
|
nfs_callback_down();
|
||||||
|
|
||||||
|
if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
|
||||||
|
rpciod_down();
|
||||||
|
|
||||||
|
kfree(clp->cl_hostname);
|
||||||
|
kfree(clp);
|
||||||
|
|
||||||
|
dprintk("<-- nfs_free_client()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release a reference to a shared client record
|
||||||
|
*/
|
||||||
|
void nfs_put_client(struct nfs_client *clp)
|
||||||
|
{
|
||||||
|
dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
|
||||||
|
|
||||||
|
if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
|
||||||
|
list_del(&clp->cl_share_link);
|
||||||
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
|
BUG_ON(!list_empty(&clp->cl_superblocks));
|
||||||
|
|
||||||
|
nfs_free_client(clp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a client by address
|
||||||
|
* - caller must hold nfs_client_lock
|
||||||
|
*/
|
||||||
|
static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
|
||||||
|
{
|
||||||
|
struct nfs_client *clp;
|
||||||
|
|
||||||
|
list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
|
||||||
|
/* Different NFS versions cannot share the same nfs_client */
|
||||||
|
if (clp->cl_nfsversion != nfsversion)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr,
|
||||||
|
sizeof(clp->cl_addr.sin_addr)) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (clp->cl_addr.sin_port == addr->sin_port)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
found:
|
||||||
|
atomic_inc(&clp->cl_count);
|
||||||
|
return clp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a client by IP address and protocol version
|
||||||
|
* - returns NULL if no such client
|
||||||
|
*/
|
||||||
|
struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
|
||||||
|
{
|
||||||
|
struct nfs_client *clp;
|
||||||
|
|
||||||
|
spin_lock(&nfs_client_lock);
|
||||||
|
clp = __nfs_find_client(addr, nfsversion);
|
||||||
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
|
BUG_ON(clp->cl_cons_state == 0);
|
||||||
|
|
||||||
|
return clp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up a client by IP address and protocol version
|
||||||
|
* - creates a new record if one doesn't yet exist
|
||||||
|
*/
|
||||||
|
struct nfs_client *nfs_get_client(const char *hostname,
|
||||||
|
const struct sockaddr_in *addr,
|
||||||
|
int nfsversion)
|
||||||
|
{
|
||||||
|
struct nfs_client *clp, *new = NULL;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n",
|
||||||
|
hostname ?: "", NIPQUAD(addr->sin_addr),
|
||||||
|
addr->sin_port, nfsversion);
|
||||||
|
|
||||||
|
/* see if the client already exists */
|
||||||
|
do {
|
||||||
|
spin_lock(&nfs_client_lock);
|
||||||
|
|
||||||
|
clp = __nfs_find_client(addr, nfsversion);
|
||||||
|
if (clp)
|
||||||
|
goto found_client;
|
||||||
|
if (new)
|
||||||
|
goto install_client;
|
||||||
|
|
||||||
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
|
new = nfs_alloc_client(hostname, addr, nfsversion);
|
||||||
|
} while (new);
|
||||||
|
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/* install a new client and return with it unready */
|
||||||
|
install_client:
|
||||||
|
clp = new;
|
||||||
|
list_add(&clp->cl_share_link, &nfs_client_list);
|
||||||
|
spin_unlock(&nfs_client_lock);
|
||||||
|
dprintk("--> nfs_get_client() = %p [new]\n", clp);
|
||||||
|
return clp;
|
||||||
|
|
||||||
|
/* found an existing client
|
||||||
|
* - make sure it's ready before returning
|
||||||
|
*/
|
||||||
|
found_client:
|
||||||
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
nfs_free_client(new);
|
||||||
|
|
||||||
|
if (clp->cl_cons_state == NFS_CS_INITING) {
|
||||||
|
DECLARE_WAITQUEUE(myself, current);
|
||||||
|
|
||||||
|
add_wait_queue(&nfs_client_active_wq, &myself);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
if (signal_pending(current) ||
|
||||||
|
clp->cl_cons_state > NFS_CS_READY)
|
||||||
|
break;
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_wait_queue(&nfs_client_active_wq, &myself);
|
||||||
|
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
nfs_put_client(clp);
|
||||||
|
return ERR_PTR(-ERESTARTSYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clp->cl_cons_state < NFS_CS_READY) {
|
||||||
|
error = clp->cl_cons_state;
|
||||||
|
nfs_put_client(clp);
|
||||||
|
return ERR_PTR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintk("--> nfs_get_client() = %p [share]\n", clp);
|
||||||
|
return clp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark a server as ready or failed
|
||||||
|
*/
|
||||||
|
void nfs_mark_client_ready(struct nfs_client *clp, int state)
|
||||||
|
{
|
||||||
|
clp->cl_cons_state = state;
|
||||||
|
wake_up_all(&nfs_client_active_wq);
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "nfs4_fs.h"
|
#include "nfs4_fs.h"
|
||||||
#include "delegation.h"
|
#include "delegation.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
static struct nfs_delegation *nfs_alloc_delegation(void)
|
static struct nfs_delegation *nfs_alloc_delegation(void)
|
||||||
{
|
{
|
||||||
@ -145,7 +146,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
|
|||||||
sizeof(delegation->stateid)) != 0 ||
|
sizeof(delegation->stateid)) != 0 ||
|
||||||
delegation->type != nfsi->delegation->type) {
|
delegation->type != nfsi->delegation->type) {
|
||||||
printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
|
printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
|
||||||
__FUNCTION__, NIPQUAD(clp->cl_addr));
|
__FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr));
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +255,7 @@ restart:
|
|||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
spin_unlock(&clp->cl_lock);
|
spin_unlock(&clp->cl_lock);
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
module_put_and_exit(0);
|
module_put_and_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,10 +267,10 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
|
|||||||
atomic_inc(&clp->cl_count);
|
atomic_inc(&clp->cl_count);
|
||||||
task = kthread_run(nfs_do_expire_all_delegations, clp,
|
task = kthread_run(nfs_do_expire_all_delegations, clp,
|
||||||
"%u.%u.%u.%u-delegreturn",
|
"%u.%u.%u.%u-delegreturn",
|
||||||
NIPQUAD(clp->cl_addr));
|
NIPQUAD(clp->cl_addr.sin_addr));
|
||||||
if (!IS_ERR(task))
|
if (!IS_ERR(task))
|
||||||
return;
|
return;
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@ struct nfs_clone_mount {
|
|||||||
rpc_authflavor_t authflavor;
|
rpc_authflavor_t authflavor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* client.c */
|
||||||
|
extern void nfs_put_client(struct nfs_client *);
|
||||||
|
extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
|
||||||
|
extern struct nfs_client *nfs_get_client(const char *, const struct sockaddr_in *, int);
|
||||||
|
extern void nfs_mark_client_ready(struct nfs_client *, int);
|
||||||
|
|
||||||
/* nfs4namespace.c */
|
/* nfs4namespace.c */
|
||||||
#ifdef CONFIG_NFS_V4
|
#ifdef CONFIG_NFS_V4
|
||||||
extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
|
extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
|
||||||
|
@ -42,55 +42,6 @@ enum nfs4_client_state {
|
|||||||
NFS4CLNT_LEASE_EXPIRED,
|
NFS4CLNT_LEASE_EXPIRED,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* The nfs_client identifies our client state to the server.
|
|
||||||
*/
|
|
||||||
struct nfs_client {
|
|
||||||
struct list_head cl_servers; /* Global list of servers */
|
|
||||||
struct in_addr cl_addr; /* Server identifier */
|
|
||||||
u64 cl_clientid; /* constant */
|
|
||||||
nfs4_verifier cl_confirm;
|
|
||||||
unsigned long cl_state;
|
|
||||||
|
|
||||||
u32 cl_lockowner_id;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following rwsem ensures exclusive access to the server
|
|
||||||
* while we recover the state following a lease expiration.
|
|
||||||
*/
|
|
||||||
struct rw_semaphore cl_sem;
|
|
||||||
|
|
||||||
struct list_head cl_delegations;
|
|
||||||
struct list_head cl_state_owners;
|
|
||||||
struct list_head cl_unused;
|
|
||||||
int cl_nunused;
|
|
||||||
spinlock_t cl_lock;
|
|
||||||
atomic_t cl_count;
|
|
||||||
|
|
||||||
struct rpc_clnt * cl_rpcclient;
|
|
||||||
|
|
||||||
struct list_head cl_superblocks; /* List of nfs_server structs */
|
|
||||||
|
|
||||||
unsigned long cl_lease_time;
|
|
||||||
unsigned long cl_last_renewal;
|
|
||||||
struct work_struct cl_renewd;
|
|
||||||
struct work_struct cl_recoverd;
|
|
||||||
|
|
||||||
struct rpc_wait_queue cl_rpcwaitq;
|
|
||||||
|
|
||||||
/* used for the setclientid verifier */
|
|
||||||
struct timespec cl_boot_time;
|
|
||||||
|
|
||||||
/* idmapper */
|
|
||||||
struct idmap * cl_idmap;
|
|
||||||
|
|
||||||
/* Our own IP address, as a null-terminated string.
|
|
||||||
* This is used to generate the clientid, and the callback address.
|
|
||||||
*/
|
|
||||||
char cl_ipaddr[16];
|
|
||||||
unsigned char cl_id_uniquifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct rpc_sequence ensures that RPC calls are sent in the exact
|
* struct rpc_sequence ensures that RPC calls are sent in the exact
|
||||||
* order that they appear on the list.
|
* order that they appear on the list.
|
||||||
@ -239,9 +190,6 @@ extern void nfs4_renew_state(void *);
|
|||||||
/* nfs4state.c */
|
/* nfs4state.c */
|
||||||
extern void init_nfsv4_state(struct nfs_server *);
|
extern void init_nfsv4_state(struct nfs_server *);
|
||||||
extern void destroy_nfsv4_state(struct nfs_server *);
|
extern void destroy_nfsv4_state(struct nfs_server *);
|
||||||
extern struct nfs_client *nfs4_get_client(struct in_addr *);
|
|
||||||
extern void nfs4_put_client(struct nfs_client *clp);
|
|
||||||
extern struct nfs_client *nfs4_find_client(struct in_addr *);
|
|
||||||
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
|
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
|
||||||
extern u32 nfs4_alloc_lockowner_id(struct nfs_client *);
|
extern u32 nfs4_alloc_lockowner_id(struct nfs_client *);
|
||||||
|
|
||||||
|
@ -2968,7 +2968,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
setclientid.sc_name_len = scnprintf(setclientid.sc_name,
|
setclientid.sc_name_len = scnprintf(setclientid.sc_name,
|
||||||
sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
|
sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
|
||||||
clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
|
clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr),
|
||||||
cred->cr_ops->cr_name,
|
cred->cr_ops->cr_name,
|
||||||
clp->cl_id_uniquifier);
|
clp->cl_id_uniquifier);
|
||||||
setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
|
setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
|
||||||
|
@ -50,12 +50,12 @@
|
|||||||
#include "nfs4_fs.h"
|
#include "nfs4_fs.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
#include "delegation.h"
|
#include "delegation.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
#define OPENOWNER_POOL_SIZE 8
|
#define OPENOWNER_POOL_SIZE 8
|
||||||
|
|
||||||
const nfs4_stateid zero_stateid;
|
const nfs4_stateid zero_stateid;
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(state_spinlock);
|
|
||||||
static LIST_HEAD(nfs4_clientid_list);
|
static LIST_HEAD(nfs4_clientid_list);
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -71,127 +71,11 @@ destroy_nfsv4_state(struct nfs_server *server)
|
|||||||
kfree(server->mnt_path);
|
kfree(server->mnt_path);
|
||||||
server->mnt_path = NULL;
|
server->mnt_path = NULL;
|
||||||
if (server->nfs_client) {
|
if (server->nfs_client) {
|
||||||
nfs4_put_client(server->nfs_client);
|
nfs_put_client(server->nfs_client);
|
||||||
server->nfs_client = NULL;
|
server->nfs_client = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* nfs4_get_client(): returns an empty client structure
|
|
||||||
* nfs4_put_client(): drops reference to client structure
|
|
||||||
*
|
|
||||||
* Since these are allocated/deallocated very rarely, we don't
|
|
||||||
* bother putting them in a slab cache...
|
|
||||||
*/
|
|
||||||
static struct nfs_client *
|
|
||||||
nfs4_alloc_client(struct in_addr *addr)
|
|
||||||
{
|
|
||||||
struct nfs_client *clp;
|
|
||||||
|
|
||||||
if (nfs_callback_up() < 0)
|
|
||||||
return NULL;
|
|
||||||
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
|
|
||||||
nfs_callback_down();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
|
|
||||||
init_rwsem(&clp->cl_sem);
|
|
||||||
INIT_LIST_HEAD(&clp->cl_delegations);
|
|
||||||
INIT_LIST_HEAD(&clp->cl_state_owners);
|
|
||||||
INIT_LIST_HEAD(&clp->cl_unused);
|
|
||||||
spin_lock_init(&clp->cl_lock);
|
|
||||||
atomic_set(&clp->cl_count, 1);
|
|
||||||
INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
|
|
||||||
INIT_LIST_HEAD(&clp->cl_superblocks);
|
|
||||||
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
|
|
||||||
clp->cl_rpcclient = ERR_PTR(-EINVAL);
|
|
||||||
clp->cl_boot_time = CURRENT_TIME;
|
|
||||||
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
|
|
||||||
return clp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nfs4_free_client(struct nfs_client *clp)
|
|
||||||
{
|
|
||||||
struct nfs4_state_owner *sp;
|
|
||||||
|
|
||||||
while (!list_empty(&clp->cl_unused)) {
|
|
||||||
sp = list_entry(clp->cl_unused.next,
|
|
||||||
struct nfs4_state_owner,
|
|
||||||
so_list);
|
|
||||||
list_del(&sp->so_list);
|
|
||||||
kfree(sp);
|
|
||||||
}
|
|
||||||
BUG_ON(!list_empty(&clp->cl_state_owners));
|
|
||||||
nfs_idmap_delete(clp);
|
|
||||||
if (!IS_ERR(clp->cl_rpcclient))
|
|
||||||
rpc_shutdown_client(clp->cl_rpcclient);
|
|
||||||
kfree(clp);
|
|
||||||
nfs_callback_down();
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct nfs_client *__nfs4_find_client(struct in_addr *addr)
|
|
||||||
{
|
|
||||||
struct nfs_client *clp;
|
|
||||||
list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
|
|
||||||
if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) {
|
|
||||||
atomic_inc(&clp->cl_count);
|
|
||||||
return clp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct nfs_client *nfs4_find_client(struct in_addr *addr)
|
|
||||||
{
|
|
||||||
struct nfs_client *clp;
|
|
||||||
spin_lock(&state_spinlock);
|
|
||||||
clp = __nfs4_find_client(addr);
|
|
||||||
spin_unlock(&state_spinlock);
|
|
||||||
return clp;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct nfs_client *
|
|
||||||
nfs4_get_client(struct in_addr *addr)
|
|
||||||
{
|
|
||||||
struct nfs_client *clp, *new = NULL;
|
|
||||||
|
|
||||||
spin_lock(&state_spinlock);
|
|
||||||
for (;;) {
|
|
||||||
clp = __nfs4_find_client(addr);
|
|
||||||
if (clp != NULL)
|
|
||||||
break;
|
|
||||||
clp = new;
|
|
||||||
if (clp != NULL) {
|
|
||||||
list_add(&clp->cl_servers, &nfs4_clientid_list);
|
|
||||||
new = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
spin_unlock(&state_spinlock);
|
|
||||||
new = nfs4_alloc_client(addr);
|
|
||||||
spin_lock(&state_spinlock);
|
|
||||||
if (new == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
spin_unlock(&state_spinlock);
|
|
||||||
if (new)
|
|
||||||
nfs4_free_client(new);
|
|
||||||
return clp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nfs4_put_client(struct nfs_client *clp)
|
|
||||||
{
|
|
||||||
if (!atomic_dec_and_lock(&clp->cl_count, &state_spinlock))
|
|
||||||
return;
|
|
||||||
list_del(&clp->cl_servers);
|
|
||||||
spin_unlock(&state_spinlock);
|
|
||||||
BUG_ON(!list_empty(&clp->cl_superblocks));
|
|
||||||
rpc_wake_up(&clp->cl_rpcwaitq);
|
|
||||||
nfs4_kill_renewd(clp);
|
|
||||||
nfs4_free_client(clp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
|
static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
|
||||||
{
|
{
|
||||||
int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
|
int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
|
||||||
@ -771,11 +655,11 @@ static void nfs4_recover_state(struct nfs_client *clp)
|
|||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
atomic_inc(&clp->cl_count);
|
atomic_inc(&clp->cl_count);
|
||||||
task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim",
|
task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim",
|
||||||
NIPQUAD(clp->cl_addr));
|
NIPQUAD(clp->cl_addr.sin_addr));
|
||||||
if (!IS_ERR(task))
|
if (!IS_ERR(task))
|
||||||
return;
|
return;
|
||||||
nfs4_clear_recover_bit(clp);
|
nfs4_clear_recover_bit(clp);
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,12 +854,12 @@ out:
|
|||||||
if (status == -NFS4ERR_CB_PATH_DOWN)
|
if (status == -NFS4ERR_CB_PATH_DOWN)
|
||||||
nfs_handle_cb_pathdown(clp);
|
nfs_handle_cb_pathdown(clp);
|
||||||
nfs4_clear_recover_bit(clp);
|
nfs4_clear_recover_bit(clp);
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
module_put_and_exit(0);
|
module_put_and_exit(0);
|
||||||
return 0;
|
return 0;
|
||||||
out_error:
|
out_error:
|
||||||
printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
|
printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
|
||||||
NIPQUAD(clp->cl_addr.s_addr), -status);
|
NIPQUAD(clp->cl_addr.sin_addr), -status);
|
||||||
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1104,47 +1104,46 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
|
|||||||
struct rpc_clnt *clnt = NULL;
|
struct rpc_clnt *clnt = NULL;
|
||||||
int err = -EIO;
|
int err = -EIO;
|
||||||
|
|
||||||
clp = nfs4_get_client(&server->addr.sin_addr);
|
clp = nfs_get_client(server->hostname, &server->addr, 4);
|
||||||
if (!clp) {
|
if (!clp) {
|
||||||
dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
|
dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now create transport and client */
|
/* Now create transport and client */
|
||||||
down_write(&clp->cl_sem);
|
if (clp->cl_cons_state == NFS_CS_INITING) {
|
||||||
if (IS_ERR(clp->cl_rpcclient)) {
|
|
||||||
xprt = xprt_create_proto(proto, &server->addr, timeparms);
|
xprt = xprt_create_proto(proto, &server->addr, timeparms);
|
||||||
if (IS_ERR(xprt)) {
|
if (IS_ERR(xprt)) {
|
||||||
up_write(&clp->cl_sem);
|
|
||||||
err = PTR_ERR(xprt);
|
err = PTR_ERR(xprt);
|
||||||
dprintk("%s: cannot create RPC transport. Error = %d\n",
|
dprintk("%s: cannot create RPC transport. Error = %d\n",
|
||||||
__FUNCTION__, err);
|
__FUNCTION__, err);
|
||||||
goto out_fail;
|
goto client_init_error;
|
||||||
}
|
}
|
||||||
/* Bind to a reserved port! */
|
/* Bind to a reserved port! */
|
||||||
xprt->resvport = 1;
|
xprt->resvport = 1;
|
||||||
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
|
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
|
||||||
server->rpc_ops->version, flavor);
|
server->rpc_ops->version, flavor);
|
||||||
if (IS_ERR(clnt)) {
|
if (IS_ERR(clnt)) {
|
||||||
up_write(&clp->cl_sem);
|
|
||||||
err = PTR_ERR(clnt);
|
err = PTR_ERR(clnt);
|
||||||
dprintk("%s: cannot create RPC client. Error = %d\n",
|
dprintk("%s: cannot create RPC client. Error = %d\n",
|
||||||
__FUNCTION__, err);
|
__FUNCTION__, err);
|
||||||
goto out_fail;
|
goto client_init_error;
|
||||||
}
|
}
|
||||||
clnt->cl_intr = 1;
|
clnt->cl_intr = 1;
|
||||||
clnt->cl_softrtry = 1;
|
clnt->cl_softrtry = 1;
|
||||||
clp->cl_rpcclient = clnt;
|
clp->cl_rpcclient = clnt;
|
||||||
memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
|
memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
|
||||||
if (nfs_idmap_new(clp) < 0)
|
err = nfs_idmap_new(clp);
|
||||||
goto out_fail;
|
if (err < 0) {
|
||||||
|
dprintk("%s: failed to create idmapper.\n",
|
||||||
|
__FUNCTION__);
|
||||||
|
goto client_init_error;
|
||||||
|
}
|
||||||
|
__set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
|
||||||
|
nfs_mark_client_ready(clp, 0);
|
||||||
}
|
}
|
||||||
list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
|
|
||||||
clnt = rpc_clone_client(clp->cl_rpcclient);
|
clnt = rpc_clone_client(clp->cl_rpcclient);
|
||||||
if (!IS_ERR(clnt))
|
|
||||||
server->nfs_client = clp;
|
|
||||||
up_write(&clp->cl_sem);
|
|
||||||
clp = NULL;
|
|
||||||
|
|
||||||
if (IS_ERR(clnt)) {
|
if (IS_ERR(clnt)) {
|
||||||
dprintk("%s: cannot create RPC client. Error = %d\n",
|
dprintk("%s: cannot create RPC client. Error = %d\n",
|
||||||
@ -1152,11 +1151,6 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
|
|||||||
return clnt;
|
return clnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->nfs_client->cl_idmap == NULL) {
|
|
||||||
dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clnt->cl_auth->au_flavor != flavor) {
|
if (clnt->cl_auth->au_flavor != flavor) {
|
||||||
struct rpc_auth *auth;
|
struct rpc_auth *auth;
|
||||||
|
|
||||||
@ -1166,11 +1160,16 @@ static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
|
|||||||
return (struct rpc_clnt *)auth;
|
return (struct rpc_clnt *)auth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server->nfs_client = clp;
|
||||||
|
down_write(&clp->cl_sem);
|
||||||
|
list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
|
||||||
|
up_write(&clp->cl_sem);
|
||||||
return clnt;
|
return clnt;
|
||||||
|
|
||||||
out_fail:
|
client_init_error:
|
||||||
if (clp)
|
nfs_mark_client_ready(clp, err);
|
||||||
nfs4_put_client(clp);
|
nfs_put_client(clp);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1329,14 +1328,6 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fire up rpciod if not yet running */
|
|
||||||
error = rpciod_up();
|
|
||||||
if (error < 0) {
|
|
||||||
dprintk("%s: couldn't start rpciod! Error = %d\n",
|
|
||||||
__FUNCTION__, error);
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
|
s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
|
||||||
if (IS_ERR(s)) {
|
if (IS_ERR(s)) {
|
||||||
error = PTR_ERR(s);
|
error = PTR_ERR(s);
|
||||||
@ -1383,8 +1374,6 @@ static void nfs4_kill_super(struct super_block *sb)
|
|||||||
|
|
||||||
destroy_nfsv4_state(server);
|
destroy_nfsv4_state(server);
|
||||||
|
|
||||||
rpciod_down();
|
|
||||||
|
|
||||||
nfs_free_iostats(server->io_stats);
|
nfs_free_iostats(server->io_stats);
|
||||||
kfree(server->hostname);
|
kfree(server->hostname);
|
||||||
kfree(server);
|
kfree(server);
|
||||||
|
@ -586,6 +586,7 @@ extern void * nfs_root_data(void);
|
|||||||
#define NFSDBG_FILE 0x0040
|
#define NFSDBG_FILE 0x0040
|
||||||
#define NFSDBG_ROOT 0x0080
|
#define NFSDBG_ROOT 0x0080
|
||||||
#define NFSDBG_CALLBACK 0x0100
|
#define NFSDBG_CALLBACK 0x0100
|
||||||
|
#define NFSDBG_CLIENT 0x0200
|
||||||
#define NFSDBG_ALL 0xFFFF
|
#define NFSDBG_ALL 0xFFFF
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
@ -6,6 +6,66 @@
|
|||||||
|
|
||||||
struct nfs_iostats;
|
struct nfs_iostats;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The nfs_client identifies our client state to the server.
|
||||||
|
*/
|
||||||
|
struct nfs_client {
|
||||||
|
atomic_t cl_count;
|
||||||
|
int cl_cons_state; /* current construction state (-ve: init error) */
|
||||||
|
#define NFS_CS_READY 0 /* ready to be used */
|
||||||
|
#define NFS_CS_INITING 1 /* busy initialising */
|
||||||
|
int cl_nfsversion; /* NFS protocol version */
|
||||||
|
unsigned long cl_res_state; /* NFS resources state */
|
||||||
|
#define NFS_CS_RPCIOD 0 /* - rpciod started */
|
||||||
|
#define NFS_CS_CALLBACK 1 /* - callback started */
|
||||||
|
#define NFS_CS_IDMAP 2 /* - idmap started */
|
||||||
|
struct sockaddr_in cl_addr; /* server identifier */
|
||||||
|
char * cl_hostname; /* hostname of server */
|
||||||
|
struct list_head cl_share_link; /* link in global client list */
|
||||||
|
struct list_head cl_superblocks; /* List of nfs_server structs */
|
||||||
|
|
||||||
|
struct rpc_clnt * cl_rpcclient;
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
u64 cl_clientid; /* constant */
|
||||||
|
nfs4_verifier cl_confirm;
|
||||||
|
unsigned long cl_state;
|
||||||
|
|
||||||
|
u32 cl_lockowner_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following rwsem ensures exclusive access to the server
|
||||||
|
* while we recover the state following a lease expiration.
|
||||||
|
*/
|
||||||
|
struct rw_semaphore cl_sem;
|
||||||
|
|
||||||
|
struct list_head cl_delegations;
|
||||||
|
struct list_head cl_state_owners;
|
||||||
|
struct list_head cl_unused;
|
||||||
|
int cl_nunused;
|
||||||
|
spinlock_t cl_lock;
|
||||||
|
|
||||||
|
unsigned long cl_lease_time;
|
||||||
|
unsigned long cl_last_renewal;
|
||||||
|
struct work_struct cl_renewd;
|
||||||
|
struct work_struct cl_recoverd;
|
||||||
|
|
||||||
|
struct rpc_wait_queue cl_rpcwaitq;
|
||||||
|
|
||||||
|
/* used for the setclientid verifier */
|
||||||
|
struct timespec cl_boot_time;
|
||||||
|
|
||||||
|
/* idmapper */
|
||||||
|
struct idmap * cl_idmap;
|
||||||
|
|
||||||
|
/* Our own IP address, as a null-terminated string.
|
||||||
|
* This is used to generate the clientid, and the callback address.
|
||||||
|
*/
|
||||||
|
char cl_ipaddr[16];
|
||||||
|
unsigned char cl_id_uniquifier;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NFS client parameters stored in the superblock.
|
* NFS client parameters stored in the superblock.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user