mirror of
https://github.com/suyu-emu/horinux.git
synced 2026-09-21 14:15:21 -07:00
Merge git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (70 commits) fs/nfs/nfs4proc.c: make nfs4_map_errors() static rpc: add service field to new upcall rpc: add target field to new upcall nfsd: support callbacks with gss flavors rpc: allow gss callbacks to client rpc: pass target name down to rpc level on callbacks nfsd: pass client principal name in rsc downcall rpc: implement new upcall rpc: store pointer to pipe inode in gss upcall message rpc: use count of pipe openers to wait for first open rpc: track number of users of the gss upcall pipe rpc: call release_pipe only on last close rpc: add an rpc_pipe_open method rpc: minor gss_alloc_msg cleanup rpc: factor out warning code from gss_pipe_destroy_msg rpc: remove unnecessary assignment NFS: remove unused status from encode routines NFS: increment number of operations in each encode routine NFS: fix comment placement in nfs4xdr.c NFS: fix tabs in nfs4xdr.c ...
This commit is contained in:
+16
-7
@@ -14,6 +14,7 @@
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <linux/lockd/lockd.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#define NLMDBG_FACILITY NLMDBG_CLIENT
|
||||
|
||||
@@ -60,7 +61,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
|
||||
|
||||
host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen,
|
||||
nlm_init->protocol, nlm_version,
|
||||
nlm_init->hostname);
|
||||
nlm_init->hostname, nlm_init->noresvport);
|
||||
if (host == NULL) {
|
||||
lockd_down();
|
||||
return ERR_PTR(-ENOLCK);
|
||||
@@ -191,11 +192,15 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
|
||||
void
|
||||
nlmclnt_recovery(struct nlm_host *host)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
if (!host->h_reclaiming++) {
|
||||
nlm_get_host(host);
|
||||
__module_get(THIS_MODULE);
|
||||
if (kernel_thread(reclaimer, host, CLONE_FS | CLONE_FILES) < 0)
|
||||
module_put(THIS_MODULE);
|
||||
task = kthread_run(reclaimer, host, "%s-reclaim", host->h_name);
|
||||
if (IS_ERR(task))
|
||||
printk(KERN_ERR "lockd: unable to spawn reclaimer "
|
||||
"thread. Locks for %s won't be reclaimed! "
|
||||
"(%ld)\n", host->h_name, PTR_ERR(task));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +212,6 @@ reclaimer(void *ptr)
|
||||
struct file_lock *fl, *next;
|
||||
u32 nsmstate;
|
||||
|
||||
daemonize("%s-reclaim", host->h_name);
|
||||
allow_signal(SIGKILL);
|
||||
|
||||
down_write(&host->h_rwsem);
|
||||
@@ -233,7 +237,12 @@ restart:
|
||||
list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
|
||||
list_del_init(&fl->fl_u.nfs_fl.list);
|
||||
|
||||
/* Why are we leaking memory here? --okir */
|
||||
/*
|
||||
* sending this thread a SIGKILL will result in any unreclaimed
|
||||
* locks being removed from the h_granted list. This means that
|
||||
* the kernel will not attempt to reclaim them again if a new
|
||||
* reclaimer thread is spawned for this host.
|
||||
*/
|
||||
if (signalled())
|
||||
continue;
|
||||
if (nlmclnt_reclaim(host, fl) != 0)
|
||||
@@ -261,5 +270,5 @@ restart:
|
||||
nlm_release_host(host);
|
||||
lockd_down();
|
||||
unlock_kernel();
|
||||
module_put_and_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+9
-1
@@ -48,6 +48,7 @@ struct nlm_lookup_host_info {
|
||||
const size_t hostname_len; /* it's length */
|
||||
const struct sockaddr *src_sap; /* our address (optional) */
|
||||
const size_t src_len; /* it's length */
|
||||
const int noresvport; /* use non-priv port */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -222,6 +223,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
|
||||
host->h_nsmstate = 0; /* real NSM state */
|
||||
host->h_nsmhandle = nsm;
|
||||
host->h_server = ni->server;
|
||||
host->h_noresvport = ni->noresvport;
|
||||
hlist_add_head(&host->h_hash, chain);
|
||||
INIT_LIST_HEAD(&host->h_lockowners);
|
||||
spin_lock_init(&host->h_lock);
|
||||
@@ -272,6 +274,7 @@ nlm_destroy_host(struct nlm_host *host)
|
||||
* @protocol: transport protocol to use
|
||||
* @version: NLM protocol version
|
||||
* @hostname: '\0'-terminated hostname of server
|
||||
* @noresvport: 1 if non-privileged port should be used
|
||||
*
|
||||
* Returns an nlm_host structure that matches the passed-in
|
||||
* [server address, transport protocol, NLM version, server hostname].
|
||||
@@ -281,7 +284,9 @@ nlm_destroy_host(struct nlm_host *host)
|
||||
struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
|
||||
const size_t salen,
|
||||
const unsigned short protocol,
|
||||
const u32 version, const char *hostname)
|
||||
const u32 version,
|
||||
const char *hostname,
|
||||
int noresvport)
|
||||
{
|
||||
const struct sockaddr source = {
|
||||
.sa_family = AF_UNSPEC,
|
||||
@@ -296,6 +301,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
|
||||
.hostname_len = strlen(hostname),
|
||||
.src_sap = &source,
|
||||
.src_len = sizeof(source),
|
||||
.noresvport = noresvport,
|
||||
};
|
||||
|
||||
dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
|
||||
@@ -417,6 +423,8 @@ nlm_bind_host(struct nlm_host *host)
|
||||
*/
|
||||
if (!host->h_server)
|
||||
args.flags |= RPC_CLNT_CREATE_HARDRTRY;
|
||||
if (host->h_noresvport)
|
||||
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
|
||||
|
||||
clnt = rpc_create(&args);
|
||||
if (!IS_ERR(clnt))
|
||||
|
||||
+3
-3
@@ -45,7 +45,7 @@
|
||||
static struct svc_program nlmsvc_program;
|
||||
|
||||
struct nlmsvc_binding * nlmsvc_ops;
|
||||
EXPORT_SYMBOL(nlmsvc_ops);
|
||||
EXPORT_SYMBOL_GPL(nlmsvc_ops);
|
||||
|
||||
static DEFINE_MUTEX(nlmsvc_mutex);
|
||||
static unsigned int nlmsvc_users;
|
||||
@@ -300,7 +300,7 @@ out:
|
||||
mutex_unlock(&nlmsvc_mutex);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(lockd_up);
|
||||
EXPORT_SYMBOL_GPL(lockd_up);
|
||||
|
||||
/*
|
||||
* Decrement the user count and bring down lockd if we're the last.
|
||||
@@ -329,7 +329,7 @@ lockd_down(void)
|
||||
out:
|
||||
mutex_unlock(&nlmsvc_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(lockd_down);
|
||||
EXPORT_SYMBOL_GPL(lockd_down);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
|
||||
+31
-5
@@ -16,6 +16,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sunrpc/svcauth_gss.h>
|
||||
|
||||
#include <net/inet_sock.h>
|
||||
|
||||
@@ -182,10 +183,34 @@ void nfs_callback_down(void)
|
||||
mutex_unlock(&nfs_callback_mutex);
|
||||
}
|
||||
|
||||
static int check_gss_callback_principal(struct nfs_client *clp,
|
||||
struct svc_rqst *rqstp)
|
||||
{
|
||||
struct rpc_clnt *r = clp->cl_rpcclient;
|
||||
char *p = svc_gss_principal(rqstp);
|
||||
|
||||
/*
|
||||
* It might just be a normal user principal, in which case
|
||||
* userspace won't bother to tell us the name at all.
|
||||
*/
|
||||
if (p == NULL)
|
||||
return SVC_DENIED;
|
||||
|
||||
/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
|
||||
|
||||
if (memcmp(p, "nfs@", 4) != 0)
|
||||
return SVC_DENIED;
|
||||
p += 4;
|
||||
if (strcmp(p, r->cl_server) != 0)
|
||||
return SVC_DENIED;
|
||||
return SVC_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -194,21 +219,22 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
|
||||
|
||||
dprintk("%s: %s NFSv4 callback!\n", __func__,
|
||||
svc_print_addr(rqstp, buf, sizeof(buf)));
|
||||
nfs_put_client(clp);
|
||||
|
||||
switch (rqstp->rq_authop->flavour) {
|
||||
case RPC_AUTH_NULL:
|
||||
if (rqstp->rq_proc != CB_NULL)
|
||||
return SVC_DENIED;
|
||||
ret = SVC_DENIED;
|
||||
break;
|
||||
case RPC_AUTH_UNIX:
|
||||
break;
|
||||
case RPC_AUTH_GSS:
|
||||
/* FIXME: RPCSEC_GSS handling? */
|
||||
ret = check_gss_callback_principal(clp, rqstp);
|
||||
break;
|
||||
default:
|
||||
return SVC_DENIED;
|
||||
ret = SVC_DENIED;
|
||||
}
|
||||
return SVC_OK;
|
||||
nfs_put_client(clp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+61
-34
@@ -143,7 +143,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
|
||||
clp->cl_proto = cl_init->proto;
|
||||
|
||||
#ifdef CONFIG_NFS_V4
|
||||
init_rwsem(&clp->cl_sem);
|
||||
INIT_LIST_HEAD(&clp->cl_delegations);
|
||||
spin_lock_init(&clp->cl_lock);
|
||||
INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
|
||||
@@ -224,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped)
|
||||
{
|
||||
switch (sa->sa_family) {
|
||||
default:
|
||||
return NULL;
|
||||
case AF_INET6:
|
||||
return &((const struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
break;
|
||||
case AF_INET:
|
||||
ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr,
|
||||
addr_mapped);
|
||||
return addr_mapped;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
|
||||
const struct sockaddr *sa2)
|
||||
{
|
||||
const struct in6_addr *addr1;
|
||||
const struct in6_addr *addr2;
|
||||
struct in6_addr addr1_mapped;
|
||||
struct in6_addr addr2_mapped;
|
||||
|
||||
addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped);
|
||||
if (likely(addr1 != NULL)) {
|
||||
addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped);
|
||||
if (likely(addr2 != NULL))
|
||||
return ipv6_addr_equal(addr1, addr2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
|
||||
const struct sockaddr_in *sa2)
|
||||
{
|
||||
return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1,
|
||||
const struct sockaddr_in6 *sa2)
|
||||
{
|
||||
return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr);
|
||||
}
|
||||
|
||||
static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
|
||||
const struct sockaddr *sa2)
|
||||
{
|
||||
switch (sa1->sa_family) {
|
||||
case AF_INET:
|
||||
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
|
||||
(const struct sockaddr_in *)sa2);
|
||||
case AF_INET6:
|
||||
return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1,
|
||||
(const struct sockaddr_in6 *)sa2);
|
||||
}
|
||||
BUG();
|
||||
if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET))
|
||||
return 0;
|
||||
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
|
||||
(const struct sockaddr_in *)sa2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find a client by IP address and protocol version
|
||||
@@ -270,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
|
||||
if (clp->rpc_ops->version != nfsversion)
|
||||
continue;
|
||||
|
||||
if (addr->sa_family != clap->sa_family)
|
||||
continue;
|
||||
/* Match only the IP address, not the port number */
|
||||
if (!nfs_sockaddr_match_ipaddr(addr, clap))
|
||||
continue;
|
||||
@@ -305,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
|
||||
if (clp->rpc_ops->version != nfsvers)
|
||||
continue;
|
||||
|
||||
if (sap->sa_family != clap->sa_family)
|
||||
continue;
|
||||
/* Match only the IP address, not the port number */
|
||||
if (!nfs_sockaddr_match_ipaddr(sap, clap))
|
||||
continue;
|
||||
@@ -470,7 +488,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
|
||||
static int nfs_create_rpc_client(struct nfs_client *clp,
|
||||
const struct rpc_timeout *timeparms,
|
||||
rpc_authflavor_t flavor,
|
||||
int flags)
|
||||
int discrtry, int noresvport)
|
||||
{
|
||||
struct rpc_clnt *clnt = NULL;
|
||||
struct rpc_create_args args = {
|
||||
@@ -482,9 +500,13 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
|
||||
.program = &nfs_program,
|
||||
.version = clp->rpc_ops->version,
|
||||
.authflavor = flavor,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
if (discrtry)
|
||||
args.flags |= RPC_CLNT_CREATE_DISCRTRY;
|
||||
if (noresvport)
|
||||
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
|
||||
|
||||
if (!IS_ERR(clp->cl_rpcclient))
|
||||
return 0;
|
||||
|
||||
@@ -522,6 +544,8 @@ static int nfs_start_lockd(struct nfs_server *server)
|
||||
.protocol = server->flags & NFS_MOUNT_TCP ?
|
||||
IPPROTO_TCP : IPPROTO_UDP,
|
||||
.nfs_version = clp->rpc_ops->version,
|
||||
.noresvport = server->flags & NFS_MOUNT_NORESVPORT ?
|
||||
1 : 0,
|
||||
};
|
||||
|
||||
if (nlm_init.nfs_version > 3)
|
||||
@@ -623,7 +647,8 @@ static int nfs_init_client(struct nfs_client *clp,
|
||||
* Create a client RPC handle for doing FSSTAT with UNIX auth only
|
||||
* - RFC 2623, sec 2.3.2
|
||||
*/
|
||||
error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0);
|
||||
error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
|
||||
0, data->flags & NFS_MOUNT_NORESVPORT);
|
||||
if (error < 0)
|
||||
goto error;
|
||||
nfs_mark_client_ready(clp, NFS_CS_READY);
|
||||
@@ -965,7 +990,8 @@ error:
|
||||
static int nfs4_init_client(struct nfs_client *clp,
|
||||
const struct rpc_timeout *timeparms,
|
||||
const char *ip_addr,
|
||||
rpc_authflavor_t authflavour)
|
||||
rpc_authflavor_t authflavour,
|
||||
int flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
@@ -979,7 +1005,7 @@ static int nfs4_init_client(struct nfs_client *clp,
|
||||
clp->rpc_ops = &nfs_v4_clientops;
|
||||
|
||||
error = nfs_create_rpc_client(clp, timeparms, authflavour,
|
||||
RPC_CLNT_CREATE_DISCRTRY);
|
||||
1, flags & NFS_MOUNT_NORESVPORT);
|
||||
if (error < 0)
|
||||
goto error;
|
||||
memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
|
||||
@@ -1030,7 +1056,8 @@ static int nfs4_set_client(struct nfs_server *server,
|
||||
error = PTR_ERR(clp);
|
||||
goto error;
|
||||
}
|
||||
error = nfs4_init_client(clp, timeparms, ip_addr, authflavour);
|
||||
error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,
|
||||
server->flags);
|
||||
if (error < 0)
|
||||
goto error_put;
|
||||
|
||||
@@ -1059,6 +1086,10 @@ static int nfs4_init_server(struct nfs_server *server,
|
||||
nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
|
||||
data->timeo, data->retrans);
|
||||
|
||||
/* Initialise the client representation from the mount data */
|
||||
server->flags = data->flags;
|
||||
server->caps |= NFS_CAP_ATOMIC_OPEN;
|
||||
|
||||
/* Get a client record */
|
||||
error = nfs4_set_client(server,
|
||||
data->nfs_server.hostname,
|
||||
@@ -1071,10 +1102,6 @@ static int nfs4_init_server(struct nfs_server *server,
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
||||
/* Initialise the client representation from the mount data */
|
||||
server->flags = data->flags;
|
||||
server->caps |= NFS_CAP_ATOMIC_OPEN;
|
||||
|
||||
if (data->rsize)
|
||||
server->rsize = nfs_block_size(data->rsize, NULL);
|
||||
if (data->wsize)
|
||||
@@ -1177,6 +1204,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
|
||||
parent_server = NFS_SB(data->sb);
|
||||
parent_client = parent_server->nfs_client;
|
||||
|
||||
/* Initialise the client representation from the parent server */
|
||||
nfs_server_copy_userdata(server, parent_server);
|
||||
server->caps |= NFS_CAP_ATOMIC_OPEN;
|
||||
|
||||
/* Get a client representation.
|
||||
* Note: NFSv4 always uses TCP, */
|
||||
error = nfs4_set_client(server, data->hostname,
|
||||
@@ -1189,10 +1220,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
||||
/* Initialise the client representation from the parent server */
|
||||
nfs_server_copy_userdata(server, parent_server);
|
||||
server->caps |= NFS_CAP_ATOMIC_OPEN;
|
||||
|
||||
error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
||||
+138
-134
@@ -43,6 +43,27 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
|
||||
put_rpccred(cred);
|
||||
}
|
||||
|
||||
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
|
||||
{
|
||||
set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
|
||||
}
|
||||
|
||||
int nfs_have_delegation(struct inode *inode, fmode_t flags)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
int ret = 0;
|
||||
|
||||
flags &= FMODE_READ|FMODE_WRITE;
|
||||
rcu_read_lock();
|
||||
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
||||
if (delegation != NULL && (delegation->type & flags) == flags) {
|
||||
nfs_mark_delegation_referenced(delegation);
|
||||
ret = 1;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
|
||||
{
|
||||
struct inode *inode = state->inode;
|
||||
@@ -119,7 +140,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
|
||||
delegation->maxsize = res->maxsize;
|
||||
oldcred = delegation->cred;
|
||||
delegation->cred = get_rpccred(cred);
|
||||
delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
|
||||
clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
|
||||
NFS_I(inode)->delegation_state = delegation->type;
|
||||
smp_wmb();
|
||||
put_rpccred(oldcred);
|
||||
@@ -134,19 +155,35 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
|
||||
spin_lock(&delegation->lock);
|
||||
if (delegation->inode != NULL)
|
||||
inode = igrab(delegation->inode);
|
||||
spin_unlock(&delegation->lock);
|
||||
return inode;
|
||||
}
|
||||
|
||||
static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
|
||||
{
|
||||
struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
|
||||
|
||||
if (delegation == NULL)
|
||||
goto nomatch;
|
||||
spin_lock(&delegation->lock);
|
||||
if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
|
||||
sizeof(delegation->stateid.data)) != 0)
|
||||
goto nomatch;
|
||||
goto nomatch_unlock;
|
||||
list_del_rcu(&delegation->super_list);
|
||||
delegation->inode = NULL;
|
||||
nfsi->delegation_state = 0;
|
||||
rcu_assign_pointer(nfsi->delegation, NULL);
|
||||
spin_unlock(&delegation->lock);
|
||||
return delegation;
|
||||
nomatch_unlock:
|
||||
spin_unlock(&delegation->lock);
|
||||
nomatch:
|
||||
return NULL;
|
||||
}
|
||||
@@ -172,6 +209,8 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
|
||||
delegation->change_attr = nfsi->change_attr;
|
||||
delegation->cred = get_rpccred(cred);
|
||||
delegation->inode = inode;
|
||||
delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
|
||||
spin_lock_init(&delegation->lock);
|
||||
|
||||
spin_lock(&clp->cl_lock);
|
||||
if (rcu_dereference(nfsi->delegation) != NULL) {
|
||||
@@ -226,21 +265,46 @@ static void nfs_msync_inode(struct inode *inode)
|
||||
*/
|
||||
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
|
||||
{
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
nfs_msync_inode(inode);
|
||||
down_read(&clp->cl_sem);
|
||||
/* Guard against new delegated open calls */
|
||||
down_write(&nfsi->rwsem);
|
||||
nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||
up_write(&nfsi->rwsem);
|
||||
up_read(&clp->cl_sem);
|
||||
nfs_msync_inode(inode);
|
||||
|
||||
return nfs_do_return_delegation(inode, delegation, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return all delegations that have been marked for return
|
||||
*/
|
||||
void nfs_client_return_marked_delegations(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
struct inode *inode;
|
||||
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
|
||||
continue;
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL)
|
||||
continue;
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL)
|
||||
__nfs_inode_return_delegation(inode, delegation);
|
||||
iput(inode);
|
||||
goto restart;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the delegation without reclaiming opens
|
||||
* or protecting against delegation reclaims.
|
||||
@@ -279,83 +343,55 @@ int nfs_inode_return_delegation(struct inode *inode)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation)
|
||||
{
|
||||
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
|
||||
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return all delegations associated to a super block
|
||||
*/
|
||||
void nfs_return_all_delegations(struct super_block *sb)
|
||||
void nfs_super_return_all_delegations(struct super_block *sb)
|
||||
{
|
||||
struct nfs_client *clp = NFS_SB(sb)->nfs_client;
|
||||
struct nfs_delegation *delegation;
|
||||
struct inode *inode;
|
||||
|
||||
if (clp == NULL)
|
||||
return;
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
if (delegation->inode->i_sb != sb)
|
||||
continue;
|
||||
inode = igrab(delegation->inode);
|
||||
if (inode == NULL)
|
||||
continue;
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL)
|
||||
__nfs_inode_return_delegation(inode, delegation);
|
||||
iput(inode);
|
||||
goto restart;
|
||||
spin_lock(&delegation->lock);
|
||||
if (delegation->inode != NULL && delegation->inode->i_sb == sb)
|
||||
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
|
||||
spin_unlock(&delegation->lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
nfs_client_return_marked_delegations(clp);
|
||||
}
|
||||
|
||||
static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
|
||||
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int nfs_do_expire_all_delegations(void *ptr)
|
||||
static void nfs_delegation_run_state_manager(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_client *clp = ptr;
|
||||
struct nfs_delegation *delegation;
|
||||
struct inode *inode;
|
||||
|
||||
allow_signal(SIGKILL);
|
||||
restart:
|
||||
if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
|
||||
goto out;
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
|
||||
goto out;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
inode = igrab(delegation->inode);
|
||||
if (inode == NULL)
|
||||
continue;
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation)
|
||||
__nfs_inode_return_delegation(inode, delegation);
|
||||
iput(inode);
|
||||
goto restart;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
nfs_put_client(clp);
|
||||
module_put_and_exit(0);
|
||||
if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
|
||||
nfs4_schedule_state_manager(clp);
|
||||
}
|
||||
|
||||
void nfs_expire_all_delegations(struct nfs_client *clp)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
atomic_inc(&clp->cl_count);
|
||||
task = kthread_run(nfs_do_expire_all_delegations, clp,
|
||||
"%s-delegreturn",
|
||||
rpc_peeraddr2str(clp->cl_rpcclient,
|
||||
RPC_DISPLAY_ADDR));
|
||||
if (!IS_ERR(task))
|
||||
return;
|
||||
nfs_put_client(clp);
|
||||
module_put(THIS_MODULE);
|
||||
nfs_client_mark_return_all_delegations(clp);
|
||||
nfs_delegation_run_state_manager(clp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,68 +399,29 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
|
||||
*/
|
||||
void nfs_handle_cb_pathdown(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
struct inode *inode;
|
||||
|
||||
if (clp == NULL)
|
||||
return;
|
||||
restart:
|
||||
nfs_client_mark_return_all_delegations(clp);
|
||||
}
|
||||
|
||||
static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
inode = igrab(delegation->inode);
|
||||
if (inode == NULL)
|
||||
if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
|
||||
continue;
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL)
|
||||
__nfs_inode_return_delegation(inode, delegation);
|
||||
iput(inode);
|
||||
goto restart;
|
||||
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
|
||||
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
struct recall_threadargs {
|
||||
struct inode *inode;
|
||||
struct nfs_client *clp;
|
||||
const nfs4_stateid *stateid;
|
||||
|
||||
struct completion started;
|
||||
int result;
|
||||
};
|
||||
|
||||
static int recall_thread(void *data)
|
||||
void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
|
||||
{
|
||||
struct recall_threadargs *args = (struct recall_threadargs *)data;
|
||||
struct inode *inode = igrab(args->inode);
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
daemonize("nfsv4-delegreturn");
|
||||
|
||||
nfs_msync_inode(inode);
|
||||
down_read(&clp->cl_sem);
|
||||
down_write(&nfsi->rwsem);
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
|
||||
if (delegation != NULL)
|
||||
args->result = 0;
|
||||
else
|
||||
args->result = -ENOENT;
|
||||
spin_unlock(&clp->cl_lock);
|
||||
complete(&args->started);
|
||||
nfs_delegation_claim_opens(inode, args->stateid);
|
||||
up_write(&nfsi->rwsem);
|
||||
up_read(&clp->cl_sem);
|
||||
nfs_msync_inode(inode);
|
||||
|
||||
if (delegation != NULL)
|
||||
nfs_do_return_delegation(inode, delegation, 1);
|
||||
iput(inode);
|
||||
module_put_and_exit(0);
|
||||
nfs_client_mark_return_unreferenced_delegations(clp);
|
||||
nfs_delegation_run_state_manager(clp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -432,22 +429,20 @@ static int recall_thread(void *data)
|
||||
*/
|
||||
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
|
||||
{
|
||||
struct recall_threadargs data = {
|
||||
.inode = inode,
|
||||
.stateid = stateid,
|
||||
};
|
||||
int status;
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
init_completion(&data.started);
|
||||
__module_get(THIS_MODULE);
|
||||
status = kernel_thread(recall_thread, &data, CLONE_KERNEL);
|
||||
if (status < 0)
|
||||
goto out_module_put;
|
||||
wait_for_completion(&data.started);
|
||||
return data.result;
|
||||
out_module_put:
|
||||
module_put(THIS_MODULE);
|
||||
return status;
|
||||
rcu_read_lock();
|
||||
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
||||
if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data,
|
||||
sizeof(delegation->stateid.data)) != 0) {
|
||||
rcu_read_unlock();
|
||||
return -ENOENT;
|
||||
}
|
||||
nfs_mark_return_delegation(clp, delegation);
|
||||
rcu_read_unlock();
|
||||
nfs_delegation_run_state_manager(clp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,10 +454,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
|
||||
struct inode *res = NULL;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
|
||||
spin_lock(&delegation->lock);
|
||||
if (delegation->inode != NULL &&
|
||||
nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
|
||||
res = igrab(delegation->inode);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&delegation->lock);
|
||||
if (res != NULL)
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
@@ -476,7 +475,7 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
|
||||
struct nfs_delegation *delegation;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
|
||||
delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
|
||||
set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -486,17 +485,22 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
|
||||
void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
struct inode *inode;
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
|
||||
if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
|
||||
if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0)
|
||||
continue;
|
||||
inode = nfs_delegation_grab_inode(delegation);
|
||||
if (inode == NULL)
|
||||
continue;
|
||||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
|
||||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL)
|
||||
nfs_free_delegation(delegation);
|
||||
iput(inode);
|
||||
goto restart;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
+15
-18
@@ -17,14 +17,20 @@ struct nfs_delegation {
|
||||
struct rpc_cred *cred;
|
||||
struct inode *inode;
|
||||
nfs4_stateid stateid;
|
||||
int type;
|
||||
#define NFS_DELEGATION_NEED_RECLAIM 1
|
||||
long flags;
|
||||
fmode_t type;
|
||||
loff_t maxsize;
|
||||
__u64 change_attr;
|
||||
unsigned long flags;
|
||||
spinlock_t lock;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
enum {
|
||||
NFS_DELEGATION_NEED_RECLAIM = 0,
|
||||
NFS_DELEGATION_RETURN,
|
||||
NFS_DELEGATION_REFERENCED,
|
||||
};
|
||||
|
||||
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
|
||||
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
|
||||
int nfs_inode_return_delegation(struct inode *inode);
|
||||
@@ -32,9 +38,11 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
|
||||
void nfs_inode_return_delegation_noreclaim(struct inode *inode);
|
||||
|
||||
struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
|
||||
void nfs_return_all_delegations(struct super_block *sb);
|
||||
void nfs_super_return_all_delegations(struct super_block *sb);
|
||||
void nfs_expire_all_delegations(struct nfs_client *clp);
|
||||
void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
|
||||
void nfs_handle_cb_pathdown(struct nfs_client *clp);
|
||||
void nfs_client_return_marked_delegations(struct nfs_client *clp);
|
||||
|
||||
void nfs_delegation_mark_reclaim(struct nfs_client *clp);
|
||||
void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
|
||||
@@ -45,22 +53,11 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
|
||||
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
|
||||
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
|
||||
|
||||
static inline int nfs_have_delegation(struct inode *inode, int flags)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
int ret = 0;
|
||||
|
||||
flags &= FMODE_READ|FMODE_WRITE;
|
||||
rcu_read_lock();
|
||||
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
||||
if (delegation != NULL && (delegation->type & flags) == flags)
|
||||
ret = 1;
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
|
||||
int nfs_have_delegation(struct inode *inode, fmode_t flags);
|
||||
|
||||
#else
|
||||
static inline int nfs_have_delegation(struct inode *inode, int flags)
|
||||
static inline int nfs_have_delegation(struct inode *inode, fmode_t flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+14
-10
@@ -799,6 +799,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if (nfs_have_delegation(inode, FMODE_READ))
|
||||
goto out_set_verifier;
|
||||
|
||||
/* Force a full look up iff the parent directory has changed */
|
||||
if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
|
||||
if (nfs_lookup_verify_inode(inode, nd))
|
||||
@@ -817,6 +820,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
|
||||
if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
|
||||
goto out_bad;
|
||||
|
||||
out_set_verifier:
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
out_valid:
|
||||
dput(parent);
|
||||
@@ -973,7 +977,7 @@ struct dentry_operations nfs4_dentry_operations = {
|
||||
* Use intent information to determine whether we need to substitute
|
||||
* the NFSv4-style stateful OPEN for the LOOKUP call
|
||||
*/
|
||||
static int is_atomic_open(struct inode *dir, struct nameidata *nd)
|
||||
static int is_atomic_open(struct nameidata *nd)
|
||||
{
|
||||
if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
|
||||
return 0;
|
||||
@@ -996,7 +1000,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
||||
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
|
||||
|
||||
/* Check that we are indeed trying to open this file */
|
||||
if (!is_atomic_open(dir, nd))
|
||||
if (!is_atomic_open(nd))
|
||||
goto no_open;
|
||||
|
||||
if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
|
||||
@@ -1047,10 +1051,10 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
struct inode *dir;
|
||||
int openflags, ret = 0;
|
||||
|
||||
if (!is_atomic_open(nd))
|
||||
goto no_open;
|
||||
parent = dget_parent(dentry);
|
||||
dir = parent->d_inode;
|
||||
if (!is_atomic_open(dir, nd))
|
||||
goto no_open;
|
||||
/* We can't create new files in nfs_open_revalidate(), so we
|
||||
* optimize away revalidation of negative dentries.
|
||||
*/
|
||||
@@ -1062,11 +1066,11 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
|
||||
/* NFS only supports OPEN on regular files */
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
goto no_open;
|
||||
goto no_open_dput;
|
||||
openflags = nd->intent.open.flags;
|
||||
/* We cannot do exclusive creation on a positive dentry */
|
||||
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
||||
goto no_open;
|
||||
goto no_open_dput;
|
||||
/* We can't create new files, or truncate existing ones here */
|
||||
openflags &= ~(O_CREAT|O_TRUNC);
|
||||
|
||||
@@ -1081,10 +1085,9 @@ out:
|
||||
if (!ret)
|
||||
d_drop(dentry);
|
||||
return ret;
|
||||
no_open:
|
||||
no_open_dput:
|
||||
dput(parent);
|
||||
if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
|
||||
return 1;
|
||||
no_open:
|
||||
return nfs_lookup_revalidate(dentry, nd);
|
||||
}
|
||||
#endif /* CONFIG_NFSV4 */
|
||||
@@ -1794,7 +1797,8 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
|
||||
cache = nfs_access_search_rbtree(inode, cred);
|
||||
if (cache == NULL)
|
||||
goto out;
|
||||
if (!time_in_range(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
|
||||
if (!nfs_have_delegation(inode, FMODE_READ) &&
|
||||
!time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
|
||||
goto out_stale;
|
||||
res->jiffies = cache->jiffies;
|
||||
res->cred = cache->cred;
|
||||
|
||||
+3
-10
@@ -592,7 +592,7 @@ static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context
|
||||
/*
|
||||
* Given an inode, search for an open context with the desired characteristics
|
||||
*/
|
||||
struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode)
|
||||
struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct nfs_open_context *pos, *ctx = NULL;
|
||||
@@ -712,14 +712,7 @@ int nfs_attribute_timeout(struct inode *inode)
|
||||
|
||||
if (nfs_have_delegation(inode, FMODE_READ))
|
||||
return 0;
|
||||
/*
|
||||
* Special case: if the attribute timeout is set to 0, then always
|
||||
* treat the cache as having expired (unless holding
|
||||
* a delegation).
|
||||
*/
|
||||
if (nfsi->attrtimeo == 0)
|
||||
return 1;
|
||||
return !time_in_range(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
|
||||
return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1182,7 +1175,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
||||
nfsi->attrtimeo_timestamp = now;
|
||||
nfsi->attr_gencount = nfs_inc_attr_generation_counter();
|
||||
} else {
|
||||
if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
|
||||
if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
|
||||
if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
|
||||
nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
|
||||
nfsi->attrtimeo_timestamp = now;
|
||||
|
||||
@@ -63,6 +63,20 @@ struct nfs_parsed_mount_data {
|
||||
struct security_mnt_opts lsm_opts;
|
||||
};
|
||||
|
||||
/* mount_clnt.c */
|
||||
struct nfs_mount_request {
|
||||
struct sockaddr *sap;
|
||||
size_t salen;
|
||||
char *hostname;
|
||||
char *dirpath;
|
||||
u32 version;
|
||||
unsigned short protocol;
|
||||
struct nfs_fh *fh;
|
||||
int noresvport;
|
||||
};
|
||||
|
||||
extern int nfs_mount(struct nfs_mount_request *info);
|
||||
|
||||
/* client.c */
|
||||
extern struct rpc_program nfs_program;
|
||||
|
||||
|
||||
+15
-19
@@ -29,47 +29,43 @@ struct mnt_fhstatus {
|
||||
|
||||
/**
|
||||
* nfs_mount - Obtain an NFS file handle for the given host and path
|
||||
* @addr: pointer to server's address
|
||||
* @len: size of server's address
|
||||
* @hostname: name of server host, or NULL
|
||||
* @path: pointer to string containing export path to mount
|
||||
* @version: mount version to use for this request
|
||||
* @protocol: transport protocol to use for thie request
|
||||
* @fh: pointer to location to place returned file handle
|
||||
* @info: pointer to mount request arguments
|
||||
*
|
||||
* Uses default timeout parameters specified by underlying transport.
|
||||
*/
|
||||
int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
|
||||
int version, int protocol, struct nfs_fh *fh)
|
||||
int nfs_mount(struct nfs_mount_request *info)
|
||||
{
|
||||
struct mnt_fhstatus result = {
|
||||
.fh = fh
|
||||
.fh = info->fh
|
||||
};
|
||||
struct rpc_message msg = {
|
||||
.rpc_argp = path,
|
||||
.rpc_argp = info->dirpath,
|
||||
.rpc_resp = &result,
|
||||
};
|
||||
struct rpc_create_args args = {
|
||||
.protocol = protocol,
|
||||
.address = addr,
|
||||
.addrsize = len,
|
||||
.servername = hostname,
|
||||
.protocol = info->protocol,
|
||||
.address = info->sap,
|
||||
.addrsize = info->salen,
|
||||
.servername = info->hostname,
|
||||
.program = &mnt_program,
|
||||
.version = version,
|
||||
.version = info->version,
|
||||
.authflavor = RPC_AUTH_UNIX,
|
||||
.flags = 0,
|
||||
};
|
||||
struct rpc_clnt *mnt_clnt;
|
||||
int status;
|
||||
|
||||
dprintk("NFS: sending MNT request for %s:%s\n",
|
||||
(hostname ? hostname : "server"), path);
|
||||
(info->hostname ? info->hostname : "server"),
|
||||
info->dirpath);
|
||||
|
||||
if (info->noresvport)
|
||||
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
|
||||
|
||||
mnt_clnt = rpc_create(&args);
|
||||
if (IS_ERR(mnt_clnt))
|
||||
goto out_clnt_err;
|
||||
|
||||
if (version == NFS_MNT3_VERSION)
|
||||
if (info->version == NFS_MNT3_VERSION)
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
|
||||
else
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
|
||||
|
||||
+24
-8
@@ -38,8 +38,12 @@ struct idmap;
|
||||
((err) != NFSERR_NOFILEHANDLE))
|
||||
|
||||
enum nfs4_client_state {
|
||||
NFS4CLNT_STATE_RECOVER = 0,
|
||||
NFS4CLNT_MANAGER_RUNNING = 0,
|
||||
NFS4CLNT_CHECK_LEASE,
|
||||
NFS4CLNT_LEASE_EXPIRED,
|
||||
NFS4CLNT_RECLAIM_REBOOT,
|
||||
NFS4CLNT_RECLAIM_NOGRACE,
|
||||
NFS4CLNT_DELEGRETURN,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -90,12 +94,18 @@ struct nfs4_state_owner {
|
||||
|
||||
spinlock_t so_lock;
|
||||
atomic_t so_count;
|
||||
unsigned long so_flags;
|
||||
struct list_head so_states;
|
||||
struct list_head so_delegations;
|
||||
struct nfs_seqid_counter so_seqid;
|
||||
struct rpc_sequence so_sequence;
|
||||
};
|
||||
|
||||
enum {
|
||||
NFS_OWNER_RECLAIM_REBOOT,
|
||||
NFS_OWNER_RECLAIM_NOGRACE
|
||||
};
|
||||
|
||||
/*
|
||||
* struct nfs4_state maintains the client-side state for a given
|
||||
* (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
|
||||
@@ -128,6 +138,8 @@ enum {
|
||||
NFS_O_RDONLY_STATE, /* OPEN stateid has read-only state */
|
||||
NFS_O_WRONLY_STATE, /* OPEN stateid has write-only state */
|
||||
NFS_O_RDWR_STATE, /* OPEN stateid has read/write state */
|
||||
NFS_STATE_RECLAIM_REBOOT, /* OPEN stateid server rebooted */
|
||||
NFS_STATE_RECLAIM_NOGRACE, /* OPEN stateid needs to recover state */
|
||||
};
|
||||
|
||||
struct nfs4_state {
|
||||
@@ -149,7 +161,7 @@ struct nfs4_state {
|
||||
unsigned int n_rdonly; /* Number of read-only references */
|
||||
unsigned int n_wronly; /* Number of write-only references */
|
||||
unsigned int n_rdwr; /* Number of read/write references */
|
||||
int state; /* State on the server (R,W, or RW) */
|
||||
fmode_t state; /* State on the server (R,W, or RW) */
|
||||
atomic_t count;
|
||||
};
|
||||
|
||||
@@ -157,9 +169,12 @@ struct nfs4_state {
|
||||
struct nfs4_exception {
|
||||
long timeout;
|
||||
int retry;
|
||||
struct nfs4_state *state;
|
||||
};
|
||||
|
||||
struct nfs4_state_recovery_ops {
|
||||
int owner_flag_bit;
|
||||
int state_flag_bit;
|
||||
int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
|
||||
int (*recover_lock)(struct nfs4_state *, struct file_lock *);
|
||||
};
|
||||
@@ -174,7 +189,6 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
|
||||
|
||||
|
||||
/* nfs4proc.c */
|
||||
extern int nfs4_map_errors(int err);
|
||||
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *);
|
||||
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
|
||||
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
|
||||
@@ -187,7 +201,7 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
|
||||
struct nfs4_fs_locations *fs_locations, struct page *page);
|
||||
|
||||
extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
|
||||
extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
|
||||
extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops;
|
||||
|
||||
extern const u32 nfs4_fattr_bitmap[2];
|
||||
extern const u32 nfs4_statfs_bitmap[2];
|
||||
@@ -202,16 +216,18 @@ extern void nfs4_kill_renewd(struct nfs_client *);
|
||||
extern void nfs4_renew_state(struct work_struct *);
|
||||
|
||||
/* nfs4state.c */
|
||||
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
|
||||
struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
|
||||
|
||||
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
|
||||
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
|
||||
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
|
||||
extern void nfs4_put_open_state(struct nfs4_state *);
|
||||
extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
|
||||
extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t);
|
||||
extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
|
||||
extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t);
|
||||
extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t);
|
||||
extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
|
||||
extern void nfs4_schedule_state_recovery(struct nfs_client *);
|
||||
extern void nfs4_schedule_state_manager(struct nfs_client *);
|
||||
extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
|
||||
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
|
||||
extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
|
||||
extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
|
||||
|
||||
+240
-191
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -65,7 +65,6 @@ nfs4_renew_state(struct work_struct *work)
|
||||
long lease, timeout;
|
||||
unsigned long last, now;
|
||||
|
||||
down_read(&clp->cl_sem);
|
||||
dprintk("%s: start\n", __func__);
|
||||
/* Are there any active superblocks? */
|
||||
if (list_empty(&clp->cl_superblocks))
|
||||
@@ -77,17 +76,19 @@ nfs4_renew_state(struct work_struct *work)
|
||||
timeout = (2 * lease) / 3 + (long)last - (long)now;
|
||||
/* Are we close to a lease timeout? */
|
||||
if (time_after(now, last + lease/3)) {
|
||||
cred = nfs4_get_renew_cred(clp);
|
||||
if (cred == NULL) {
|
||||
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
nfs_expire_all_delegations(clp);
|
||||
goto out;
|
||||
}
|
||||
cred = nfs4_get_renew_cred_locked(clp);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
/* Queue an asynchronous RENEW. */
|
||||
nfs4_proc_async_renew(clp, cred);
|
||||
put_rpccred(cred);
|
||||
if (cred == NULL) {
|
||||
if (list_empty(&clp->cl_delegations)) {
|
||||
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
||||
goto out;
|
||||
}
|
||||
nfs_expire_all_delegations(clp);
|
||||
} else {
|
||||
/* Queue an asynchronous RENEW. */
|
||||
nfs4_proc_async_renew(clp, cred);
|
||||
put_rpccred(cred);
|
||||
}
|
||||
timeout = (2 * lease) / 3;
|
||||
spin_lock(&clp->cl_lock);
|
||||
} else
|
||||
@@ -100,12 +101,11 @@ nfs4_renew_state(struct work_struct *work)
|
||||
cancel_delayed_work(&clp->cl_renewd);
|
||||
schedule_delayed_work(&clp->cl_renewd, timeout);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
nfs_expire_unreferenced_delegations(clp);
|
||||
out:
|
||||
up_read(&clp->cl_sem);
|
||||
dprintk("%s: done\n", __func__);
|
||||
}
|
||||
|
||||
/* Must be called with clp->cl_sem locked for writes */
|
||||
void
|
||||
nfs4_schedule_state_renewal(struct nfs_client *clp)
|
||||
{
|
||||
|
||||
+296
-123
File diff suppressed because it is too large
Load Diff
+534
-683
File diff suppressed because it is too large
Load Diff
+17
-10
@@ -86,6 +86,8 @@
|
||||
#include <net/ipconfig.h>
|
||||
#include <linux/parser.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
/* Define this to allow debugging output */
|
||||
#undef NFSROOT_DEBUG
|
||||
#define NFSDBG_FACILITY NFSDBG_ROOT
|
||||
@@ -100,7 +102,7 @@ static char nfs_root_name[256] __initdata = "";
|
||||
static __be32 servaddr __initdata = 0;
|
||||
|
||||
/* Name of directory to mount */
|
||||
static char nfs_path[NFS_MAXPATHLEN] __initdata = { 0, };
|
||||
static char nfs_export_path[NFS_MAXPATHLEN] __initdata = { 0, };
|
||||
|
||||
/* NFS-related data */
|
||||
static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
|
||||
@@ -312,7 +314,7 @@ static int __init root_nfs_name(char *name)
|
||||
printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(nfs_path, buf, cp);
|
||||
sprintf(nfs_export_path, buf, cp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -340,7 +342,7 @@ static int __init root_nfs_addr(void)
|
||||
static void __init root_nfs_print(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
|
||||
nfs_path, nfs_data.hostname);
|
||||
nfs_export_path, nfs_data.hostname);
|
||||
printk(KERN_NOTICE "Root-NFS: rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
|
||||
nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
|
||||
printk(KERN_NOTICE "Root-NFS: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
|
||||
@@ -485,18 +487,23 @@ static int __init root_nfs_get_handle(void)
|
||||
{
|
||||
struct nfs_fh fh;
|
||||
struct sockaddr_in sin;
|
||||
struct nfs_mount_request request = {
|
||||
.sap = (struct sockaddr *)&sin,
|
||||
.salen = sizeof(sin),
|
||||
.dirpath = nfs_export_path,
|
||||
.version = (nfs_data.flags & NFS_MOUNT_VER3) ?
|
||||
NFS_MNT3_VERSION : NFS_MNT_VERSION,
|
||||
.protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
|
||||
XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
|
||||
.fh = &fh,
|
||||
};
|
||||
int status;
|
||||
int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
|
||||
XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP;
|
||||
int version = (nfs_data.flags & NFS_MOUNT_VER3) ?
|
||||
NFS_MNT3_VERSION : NFS_MNT_VERSION;
|
||||
|
||||
set_sockaddr(&sin, servaddr, htons(mount_port));
|
||||
status = nfs_mount((struct sockaddr *) &sin, sizeof(sin), NULL,
|
||||
nfs_path, version, protocol, &fh);
|
||||
status = nfs_mount(&request);
|
||||
if (status < 0)
|
||||
printk(KERN_ERR "Root-NFS: Server returned error %d "
|
||||
"while mounting %s\n", status, nfs_path);
|
||||
"while mounting %s\n", status, nfs_export_path);
|
||||
else {
|
||||
nfs_data.root.size = fh.size;
|
||||
memcpy(nfs_data.root.data, fh.data, fh.size);
|
||||
|
||||
@@ -533,12 +533,6 @@ readpage_async_filler(void *data, struct page *page)
|
||||
unsigned int len;
|
||||
int error;
|
||||
|
||||
error = nfs_wb_page(inode, page);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
if (PageUptodate(page))
|
||||
goto out_unlock;
|
||||
|
||||
len = nfs_page_length(page);
|
||||
if (len == 0)
|
||||
return nfs_return_empty_page(page);
|
||||
|
||||
+28
-16
@@ -75,6 +75,7 @@ enum {
|
||||
Opt_acl, Opt_noacl,
|
||||
Opt_rdirplus, Opt_nordirplus,
|
||||
Opt_sharecache, Opt_nosharecache,
|
||||
Opt_resvport, Opt_noresvport,
|
||||
|
||||
/* Mount options that take integer arguments */
|
||||
Opt_port,
|
||||
@@ -129,6 +130,8 @@ static const match_table_t nfs_mount_option_tokens = {
|
||||
{ Opt_nordirplus, "nordirplus" },
|
||||
{ Opt_sharecache, "sharecache" },
|
||||
{ Opt_nosharecache, "nosharecache" },
|
||||
{ Opt_resvport, "resvport" },
|
||||
{ Opt_noresvport, "noresvport" },
|
||||
|
||||
{ Opt_port, "port=%u" },
|
||||
{ Opt_rsize, "rsize=%u" },
|
||||
@@ -512,7 +515,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
|
||||
{ NFS_MOUNT_NONLM, ",nolock", "" },
|
||||
{ NFS_MOUNT_NOACL, ",noacl", "" },
|
||||
{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
|
||||
{ NFS_MOUNT_UNSHARED, ",nosharecache", ""},
|
||||
{ NFS_MOUNT_UNSHARED, ",nosharecache", "" },
|
||||
{ NFS_MOUNT_NORESVPORT, ",noresvport", "" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
const struct proc_nfs_info *nfs_infop;
|
||||
@@ -1033,6 +1037,12 @@ static int nfs_parse_mount_options(char *raw,
|
||||
case Opt_nosharecache:
|
||||
mnt->flags |= NFS_MOUNT_UNSHARED;
|
||||
break;
|
||||
case Opt_resvport:
|
||||
mnt->flags &= ~NFS_MOUNT_NORESVPORT;
|
||||
break;
|
||||
case Opt_noresvport:
|
||||
mnt->flags |= NFS_MOUNT_NORESVPORT;
|
||||
break;
|
||||
|
||||
/*
|
||||
* options that take numeric values
|
||||
@@ -1327,8 +1337,14 @@ out_security_failure:
|
||||
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||
struct nfs_fh *root_fh)
|
||||
{
|
||||
struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address;
|
||||
char *hostname;
|
||||
struct nfs_mount_request request = {
|
||||
.sap = (struct sockaddr *)
|
||||
&args->mount_server.address,
|
||||
.dirpath = args->nfs_server.export_path,
|
||||
.protocol = args->mount_server.protocol,
|
||||
.fh = root_fh,
|
||||
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
||||
};
|
||||
int status;
|
||||
|
||||
if (args->mount_server.version == 0) {
|
||||
@@ -1337,42 +1353,38 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||
else
|
||||
args->mount_server.version = NFS_MNT_VERSION;
|
||||
}
|
||||
request.version = args->mount_server.version;
|
||||
|
||||
if (args->mount_server.hostname)
|
||||
hostname = args->mount_server.hostname;
|
||||
request.hostname = args->mount_server.hostname;
|
||||
else
|
||||
hostname = args->nfs_server.hostname;
|
||||
request.hostname = args->nfs_server.hostname;
|
||||
|
||||
/*
|
||||
* Construct the mount server's address.
|
||||
*/
|
||||
if (args->mount_server.address.ss_family == AF_UNSPEC) {
|
||||
memcpy(sap, &args->nfs_server.address,
|
||||
memcpy(request.sap, &args->nfs_server.address,
|
||||
args->nfs_server.addrlen);
|
||||
args->mount_server.addrlen = args->nfs_server.addrlen;
|
||||
}
|
||||
request.salen = args->mount_server.addrlen;
|
||||
|
||||
/*
|
||||
* autobind will be used if mount_server.port == 0
|
||||
*/
|
||||
nfs_set_port(sap, args->mount_server.port);
|
||||
nfs_set_port(request.sap, args->mount_server.port);
|
||||
|
||||
/*
|
||||
* Now ask the mount server to map our export path
|
||||
* to a file handle.
|
||||
*/
|
||||
status = nfs_mount(sap,
|
||||
args->mount_server.addrlen,
|
||||
hostname,
|
||||
args->nfs_server.export_path,
|
||||
args->mount_server.version,
|
||||
args->mount_server.protocol,
|
||||
root_fh);
|
||||
status = nfs_mount(&request);
|
||||
if (status == 0)
|
||||
return 0;
|
||||
|
||||
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
|
||||
hostname, status);
|
||||
request.hostname, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -2419,7 +2431,7 @@ static void nfs4_kill_super(struct super_block *sb)
|
||||
{
|
||||
struct nfs_server *server = NFS_SB(sb);
|
||||
|
||||
nfs_return_all_delegations(sb);
|
||||
nfs_super_return_all_delegations(sb);
|
||||
kill_anon_super(sb);
|
||||
|
||||
nfs4_renewd_prepare_shutdown(server);
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(nfsacl_encode);
|
||||
EXPORT_SYMBOL(nfsacl_decode);
|
||||
EXPORT_SYMBOL_GPL(nfsacl_encode);
|
||||
EXPORT_SYMBOL_GPL(nfsacl_decode);
|
||||
|
||||
struct nfsacl_encode_desc {
|
||||
struct xdr_array2_desc desc;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user