login
Header Space

 
 

[PATCH 20/52] CRED: Pass credentials into rpc_init_task()

Score:
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <viro@...>
Cc: <kwc@...>, <Trond.Myklebust@...>, <linux-kernel@...>, <dhowells@...>
Date: Friday, October 12, 2007 - 12:07 pm

Pass credentials into rpc_init_task().

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/lockd/clntlock.c            |    2 
 fs/lockd/clntproc.c            |   34 ++-
 fs/lockd/host.c                |    6 
 fs/lockd/mon.c                 |   21 +-
 fs/lockd/svc.c                 |    2 
 fs/lockd/svc4proc.c            |    6 
 fs/lockd/svclock.c             |   13 +
 fs/lockd/svcproc.c             |    7 -
 fs/nfs/callback.c              |    2 
 fs/nfs/callback.h              |    2 
 fs/nfs/client.c                |  103 +++++---
 fs/nfs/delegation.c            |   24 +-
 fs/nfs/delegation.h            |   10 +
 fs/nfs/dir.c                   |  111 ++++++---
 fs/nfs/direct.c                |   29 +-
 fs/nfs/file.c                  |   14 +
 fs/nfs/getroot.c               |   22 +-
 fs/nfs/inode.c                 |   45 +++-
 fs/nfs/internal.h              |   24 +-
 fs/nfs/mount_clnt.c            |    7 -
 fs/nfs/namespace.c             |    5 
 fs/nfs/nfs3acl.c               |   43 ++-
 fs/nfs/nfs3proc.c              |  130 ++++++----
 fs/nfs/nfs4_fs.h               |   30 ++
 fs/nfs/nfs4namespace.c         |    7 -
 fs/nfs/nfs4proc.c              |  496 ++++++++++++++++++++++++----------------
 fs/nfs/nfs4renewd.c            |    2 
 fs/nfs/nfs4state.c             |   16 +
 fs/nfs/proc.c                  |   99 ++++----
 fs/nfs/read.c                  |    7 -
 fs/nfs/super.c                 |   41 ++-
 fs/nfs/symlink.c               |   24 ++
 fs/nfs/unlink.c                |   18 +
 fs/nfs/write.c                 |   17 +
 include/linux/lockd/bind.h     |    5 
 include/linux/lockd/lockd.h    |    5 
 include/linux/lockd/sm_inter.h |    4 
 include/linux/nfs_fs.h         |   38 ++-
 include/linux/nfs_xdr.h        |   54 +++-
 include/linux/sunrpc/clnt.h    |   10 -
 include/linux/sunrpc/sched.h   |   13 +
 net/sunrpc/auth_gss/auth_gss.c |    2 
 net/sunrpc/clnt.c              |   50 +++-
 net/sunrpc/rpcb_clnt.c         |   14 +
 net/sunrpc/sched.c             |   22 +-
 net/sunrpc/svc.c               |    5 
 46 files changed, 980 insertions(+), 661 deletions(-)

diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index d070b18..653a83e 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -174,7 +174,7 @@ reclaimer(void *ptr)
 	/* This one ensures that our parent doesn't terminate while the
 	 * reclaim is in progress */
 	lock_kernel();
-	lockd_up(0); /* note: this cannot fail as lockd is already running */
+	lockd_up(0, &init_cred); /* note: this cannot fail as lockd is already running */
 
 	dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
 
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index a10343b..fde8f25 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -28,7 +28,8 @@ static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
 static int	nlm_stat_to_errno(__be32 stat);
 static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
-static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
+static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *,
+			       struct cred *);
 
 static const struct rpc_call_ops nlmclnt_unlock_ops;
 static const struct rpc_call_ops nlmclnt_cancel_ops;
@@ -149,7 +150,8 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
  * This is the main entry point for the NLM client.
  */
 int
-nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
+nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl,
+	     struct cred *acred)
 {
 	struct rpc_clnt		*client = NFS_CLIENT(inode);
 	struct sockaddr_in	addr;
@@ -173,7 +175,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 	if (host == NULL)
 		return -ENOLCK;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return -ENOMEM;
 
@@ -227,7 +229,7 @@ EXPORT_SYMBOL(nlmclnt_proc);
  * Note: the caller must hold a reference to host. In case of failure,
  * this reference will be released.
  */
-struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+struct nlm_rqst *nlm_alloc_call(struct nlm_host *host, struct cred *acred)
 {
 	struct nlm_rqst	*call;
 
@@ -237,6 +239,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 			locks_init_lock(&call->a_args.lock.fl);
 			locks_init_lock(&call->a_res.lock.fl);
 			call->a_host = host;
+			call->a_acred = get_cred(acred);
 			return call;
 		}
 		if (signalled())
@@ -252,10 +255,11 @@ void nlm_release_call(struct nlm_rqst *call)
 {
 	nlm_release_host(call->a_host);
 	nlmclnt_release_lockargs(call);
+	put_cred(call->a_acred);
 	kfree(call);
 }
 
-static void nlmclnt_rpc_release(void *data)
+static void nlmclnt_rpc_release(struct cred *acred, void *data)
 {
 	return nlm_release_call(data);
 }
@@ -300,12 +304,12 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
 			goto in_grace_period;
 
 		/* If we have no RPC client yet, create one. */
-		if ((clnt = nlm_bind_host(host)) == NULL)
+		if ((clnt = nlm_bind_host(host, req->a_acred)) == NULL)
 			return -ENOLCK;
 		msg.rpc_proc = &clnt->cl_procinfo[proc];
 
 		/* Perform the RPC call. If an error occurs, try again */
-		if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
+		if ((status = rpc_call_sync(clnt, &msg, 0, req->a_acred)) < 0) {
 			dprintk("lockd: rpc_call returned error %d\n", -status);
 			switch (status) {
 			case -EPROTONOSUPPORT:
@@ -365,15 +369,16 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *
 			(int)proc, host->h_name);
 
 	/* If we have no RPC client yet, create one. */
-	clnt = nlm_bind_host(host);
+	clnt = nlm_bind_host(host, req->a_acred);
 	if (clnt == NULL)
 		goto out_err;
 	msg->rpc_proc = &clnt->cl_procinfo[proc];
 
         /* bootstrap and kick off the async RPC call */
-        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
+        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req,
+			      req->a_acred);
 out_err:
-	tk_ops->rpc_release(req);
+	tk_ops->rpc_release(req->a_acred, req);
 	return -ENOLCK;
 }
 
@@ -499,7 +504,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 	unsigned char fl_flags = fl->fl_flags;
 	int status = -ENOLCK;
 
-	if (nsm_monitor(host) < 0) {
+	if (nsm_monitor(host, req->a_acred) < 0) {
 		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
 					host->h_name);
 		goto out;
@@ -553,7 +558,7 @@ out_unblock:
 	nlmclnt_finish_block(block);
 	/* Cancel the blocked request if it is still pending */
 	if (resp->status == nlm_lck_blocked)
-		nlmclnt_cancel(host, req->a_args.block, fl);
+		nlmclnt_cancel(host, req->a_args.block, fl, req->a_acred);
 out:
 	nlm_release_call(req);
 	fl->fl_flags = fl_flags;
@@ -681,7 +686,8 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = {
  * We always use an async RPC call for this in order not to hang a
  * process that has been Ctrl-C'ed.
  */
-static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
+static int nlmclnt_cancel(struct nlm_host *host, int block,
+			  struct file_lock *fl, struct cred *acred)
 {
 	struct nlm_rqst	*req;
 	unsigned long	flags;
@@ -695,7 +701,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
 	recalc_sigpending();
 	spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
-	req = nlm_alloc_call(nlm_get_host(host));
+	req = nlm_alloc_call(nlm_get_host(host), acred);
 	if (!req)
 		return -ENOMEM;
 	req->a_flags = RPC_TASK_ASYNC;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 572601e..15071a2 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -163,7 +163,7 @@ nlm_destroy_host(struct nlm_host *host)
 	/*
 	 * Release NSM handle and unmonitor host.
 	 */
-	nsm_unmonitor(host);
+	nsm_unmonitor(host, current->cred);
 
 	clnt = host->h_rpcclnt;
 	if (clnt != NULL)
@@ -203,7 +203,7 @@ nlmsvc_lookup_host(struct svc_rqst *rqstp,
  * Create the NLM RPC client for an NLM peer
  */
 struct rpc_clnt *
-nlm_bind_host(struct nlm_host *host)
+nlm_bind_host(struct nlm_host *host, struct cred *acred)
 {
 	struct rpc_clnt	*clnt;
 
@@ -246,7 +246,7 @@ nlm_bind_host(struct nlm_host *host)
 					   RPC_CLNT_CREATE_AUTOBIND),
 		};
 
-		clnt = rpc_create(&args);
+		clnt = rpc_create(&args, acred);
 		if (!IS_ERR(clnt))
 			host->h_rpcclnt = clnt;
 		else {
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3353ed8..f2ca99f 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -17,7 +17,7 @@
 
 #define NLMDBG_FACILITY		NLMDBG_MONITOR
 
-static struct rpc_clnt *	nsm_create(void);
+static struct rpc_clnt *	nsm_create(struct cred *);
 
 static struct rpc_program	nsm_program;
 
@@ -30,7 +30,8 @@ int				nsm_local_state;
  * Common procedure for SM_MON/SM_UNMON calls
  */
 static int
-nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
+nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
+	      struct cred *acred)
 {
 	struct rpc_clnt	*clnt;
 	int		status;
@@ -40,7 +41,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
 		.rpc_resp	= res,
 	};
 
-	clnt = nsm_create();
+	clnt = nsm_create(acred);
 	if (IS_ERR(clnt)) {
 		status = PTR_ERR(clnt);
 		goto out;
@@ -55,7 +56,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
 	memset(res, 0, sizeof(*res));
 
 	msg.rpc_proc = &clnt->cl_procinfo[proc];
-	status = rpc_call_sync(clnt, &msg, 0);
+	status = rpc_call_sync(clnt, &msg, 0, acred);
 	if (status < 0)
 		printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n",
 			status);
@@ -70,7 +71,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
  * Set up monitoring of a remote host
  */
 int
-nsm_monitor(struct nlm_host *host)
+nsm_monitor(struct nlm_host *host, struct cred *acred)
 {
 	struct nsm_handle *nsm = host->h_nsmhandle;
 	struct nsm_res	res;
@@ -82,7 +83,7 @@ nsm_monitor(struct nlm_host *host)
 	if (nsm->sm_monitored)
 		return 0;
 
-	status = nsm_mon_unmon(nsm, SM_MON, &res);
+	status = nsm_mon_unmon(nsm, SM_MON, &res, acred);
 
 	if (status < 0 || res.status != 0)
 		printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name);
@@ -95,7 +96,7 @@ nsm_monitor(struct nlm_host *host)
  * Cease to monitor remote host
  */
 int
-nsm_unmonitor(struct nlm_host *host)
+nsm_unmonitor(struct nlm_host *host, struct cred *acred)
 {
 	struct nsm_handle *nsm = host->h_nsmhandle;
 	struct nsm_res	res;
@@ -109,7 +110,7 @@ nsm_unmonitor(struct nlm_host *host)
 	 && nsm->sm_monitored && !nsm->sm_sticky) {
 		dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name);
 
-		status = nsm_mon_unmon(nsm, SM_UNMON, &res);
+		status = nsm_mon_unmon(nsm, SM_UNMON, &res, acred);
 		if (status < 0)
 			printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
 					host->h_name);
@@ -124,7 +125,7 @@ nsm_unmonitor(struct nlm_host *host)
  * Create NSM client for the local host
  */
 static struct rpc_clnt *
-nsm_create(void)
+nsm_create(struct cred *acred)
 {
 	struct sockaddr_in	sin = {
 		.sin_family	= AF_INET,
@@ -141,7 +142,7 @@ nsm_create(void)
 		.authflavor	= RPC_AUTH_NULL,
 	};
 
-	return rpc_create(&args);
+	return rpc_create(&args, acred);
 }
 
 /*
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 82e2192..d4fd193 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -264,7 +264,7 @@ static int make_socks(struct svc_serv *serv, int proto)
  * Bring up the lockd process if it's not already up.
  */
 int
-lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+lockd_up(int proto, struct cred *acred) /* Maybe add a 'family' option when IPv6 is supported ?? */
 {
 	struct svc_serv *	serv;
 	int			error = 0;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index bf27b6c..16efd5a 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -39,7 +39,7 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
 	/* Obtain host handle */
 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
-	 || (argp->monitor && nsm_monitor(host) < 0))
+	 || (argp->monitor && nsm_monitor(host, current->cred) < 0))
 		goto no_locks;
 	*hostp = host;
 
@@ -242,7 +242,7 @@ static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
 			-task->tk_status);
 }
 
-static void nlm4svc_callback_release(void *data)
+static void nlm4svc_callback_release(struct cred *acred, void *data)
 {
 	nlm_release_call(data);
 }
@@ -270,7 +270,7 @@ static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
 	if (host == NULL)
 		return rpc_system_err;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, current->cred);
 	if (call == NULL)
 		return rpc_system_err;
 
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d120ec3..50d89ea 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -174,12 +174,12 @@ found:
 static struct nlm_block *
 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
 		    struct nlm_file *file, struct nlm_lock *lock,
-		    struct nlm_cookie *cookie)
+		    struct nlm_cookie *cookie, struct cred *acred)
 {
 	struct nlm_block	*block;
 	struct nlm_rqst		*call = NULL;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return NULL;
 
@@ -360,6 +360,7 @@ __be32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 			struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
+	struct cred		*acred = current->cred;
 	struct nlm_block	*block = NULL;
 	struct nlm_host		*host;
 	int			error;
@@ -386,7 +387,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 	block = nlmsvc_lookup_block(file, lock);
 	if (block == NULL) {
 		block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
-				lock, cookie);
+				lock, cookie, acred);
 		ret = nlm_lck_denied_nolocks;
 		if (block == NULL)
 			goto out;
@@ -463,6 +464,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
 		struct nlm_lock *lock, struct nlm_lock *conflock,
 		struct nlm_cookie *cookie)
 {
+	struct cred		*acred = current->cred;
 	struct nlm_block 	*block = NULL;
 	int			error;
 	__be32			ret;
@@ -489,7 +491,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
 			kfree(conf);
 			return nlm_lck_denied_nolocks;
 		}
-		block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
+		block = nlmsvc_create_block(rqstp, host, file, lock, cookie,
+					    acred);
 		if (block == NULL) {
 			kfree(conf);
 			return nlm_granted;
@@ -796,7 +799,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
 	svc_wake_up(block->b_daemon);
 }
 
-static void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(struct cred *acred, void *data)
 {
 	struct nlm_rqst		*call = data;
 
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 9cd5c8b..f3265ed 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -68,7 +68,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
 	/* Obtain host handle */
 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
-	 || (argp->monitor && nsm_monitor(host) < 0))
+	 || (argp->monitor && nsm_monitor(host, current->cred) < 0))
 		goto no_locks;
 	*hostp = host;
 
@@ -272,7 +272,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 			-task->tk_status);
 }
 
-static void nlmsvc_callback_release(void *data)
+static void nlmsvc_callback_release(struct cred *acred, void *data)
 {
 	nlm_release_call(data);
 }
@@ -290,6 +290,7 @@ static const struct rpc_call_ops nlmsvc_callback_ops = {
 static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
 		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
 {
+	struct cred *acred = current->cred;
 	struct nlm_host	*host;
 	struct nlm_rqst	*call;
 	__be32 stat;
@@ -300,7 +301,7 @@ static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
 	if (host == NULL)
 		return rpc_system_err;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return rpc_system_err;
 
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a796be5..bca7d28 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -107,7 +107,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
 /*
  * Bring up the server process if it is not already up.
  */
-int nfs_callback_up(void)
+int nfs_callback_up(struct cred *acred)
 {
 	struct svc_serv *serv;
 	int ret = 0;
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index c2bb14e..8425611 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getat
 extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
 
 #ifdef CONFIG_NFS_V4
-extern int nfs_callback_up(void);
+extern int nfs_callback_up(struct cred *acred);
 extern void nfs_callback_down(void);
 #else
 #define nfs_callback_up()	(0)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a204484..61a1b20 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -99,7 +99,8 @@ struct rpc_program		nfsacl_program = {
  */
 static struct nfs_client *nfs_alloc_client(const char *hostname,
 					   const struct sockaddr_in *addr,
-					   int nfsversion)
+					   int nfsversion,
+					   struct cred *acred)
 {
 	struct nfs_client *clp;
 
@@ -107,7 +108,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
 		goto error_0;
 
 	if (nfsversion == 4) {
-		if (nfs_callback_up() < 0)
+		if (nfs_callback_up(acred) < 0)
 			goto error_2;
 		__set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
 	}
@@ -257,7 +258,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio
  */
 static struct nfs_client *nfs_get_client(const char *hostname,
 					 const struct sockaddr_in *addr,
-					 int nfsversion)
+					 int nfsversion,
+					 struct cred *acred)
 {
 	struct nfs_client *clp, *new = NULL;
 	int error;
@@ -278,7 +280,7 @@ static struct nfs_client *nfs_get_client(const char *hostname,
 
 		spin_unlock(&nfs_client_lock);
 
-		new = nfs_alloc_client(hostname, addr, nfsversion);
+		new = nfs_alloc_client(hostname, addr, nfsversion, acred);
 	} while (new);
 
 	return ERR_PTR(-ENOMEM);
@@ -368,7 +370,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
 						unsigned int timeo,
 						unsigned int retrans,
 						rpc_authflavor_t flavor,
-						int flags)
+						int flags,
+						struct cred *acred)
 {
 	struct rpc_timeout	timeparms;
 	struct rpc_clnt		*clnt = NULL;
@@ -391,7 +394,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
 	clp->retrans_timeo = timeparms.to_initval;
 	clp->retrans_count = timeparms.to_retries;
 
-	clnt = rpc_create(&args);
+	clnt = rpc_create(&args, acred);
 	if (IS_ERR(clnt)) {
 		dprintk("%s: cannot create RPC client. Error = %ld\n",
 				__FUNCTION__, PTR_ERR(clnt));
@@ -417,7 +420,7 @@ static void nfs_destroy_server(struct nfs_server *server)
 /*
  * Version 2 or 3 lockd setup
  */
-static int nfs_start_lockd(struct nfs_server *server)
+static int nfs_start_lockd(struct nfs_server *server, struct cred *acred)
 {
 	int error = 0;
 
@@ -426,7 +429,7 @@ static int nfs_start_lockd(struct nfs_server *server)
 	if (server->flags & NFS_MOUNT_NONLM)
 		goto out;
 	error = lockd_up((server->flags & NFS_MOUNT_TCP) ?
-			IPPROTO_TCP : IPPROTO_UDP);
+			IPPROTO_TCP : IPPROTO_UDP, acred);
 	if (error < 0)
 		server->flags |= NFS_MOUNT_NONLM;
 	else
@@ -439,14 +442,16 @@ out:
  * Initialise an NFSv3 ACL client connection
  */
 #ifdef CONFIG_NFS_V3_ACL
-static void nfs_init_server_aclclient(struct nfs_server *server)
+static void nfs_init_server_aclclient(struct nfs_server *server,
+				      struct cred *acred)
 {
 	if (server->nfs_client->cl_nfsversion != 3)
 		goto out_noacl;
 	if (server->flags & NFS_MOUNT_NOACL)
 		goto out_noacl;
 
-	server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+	server->client_acl = rpc_bind_new_program(server->client,
+						  &nfsacl_program, 3, acred);
 	if (IS_ERR(server->client_acl))
 		goto out_noacl;
 
@@ -501,7 +506,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t
 /*
  * Initialise an NFS2 or NFS3 client
  */
-static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
+static int nfs_init_client(struct nfs_client *clp,
+			   const struct nfs_mount_data *data,
+			   struct cred *acred)
 {
 	int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
 	int error;
@@ -523,7 +530,7 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *
 	 * - RFC 2623, sec 2.3.2
 	 */
 	error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
-					RPC_AUTH_UNIX, 0);
+					RPC_AUTH_UNIX, 0, acred);
 	if (error < 0)
 		goto error;
 	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -538,7 +545,9 @@ error:
 /*
  * Create a version 2 or 3 client
  */
-static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
+static int nfs_init_server(struct nfs_server *server,
+			   const struct nfs_mount_data *data,
+			   struct cred *acred)
 {
 	struct nfs_client *clp;
 	int error, nfsvers = 2;
@@ -551,13 +560,13 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 #endif
 
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
+	clp = nfs_get_client(data->hostname, &data->addr, nfsvers, acred);
 	if (IS_ERR(clp)) {
 		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
 		return PTR_ERR(clp);
 	}
 
-	error = nfs_init_client(clp, data);
+	error = nfs_init_client(clp, data, acred);
 	if (error < 0)
 		goto error;
 
@@ -577,7 +586,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 	server->acdirmax = data->acdirmax * HZ;
 
 	/* Start lockd here, before we might error out */
-	error = nfs_start_lockd(server);
+	error = nfs_start_lockd(server, acred);
 	if (error < 0)
 		goto error;
 
@@ -587,7 +596,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 
 	server->namelen  = data->namlen;
 	/* Create a client RPC handle for the NFSv3 ACL management interface */
-	nfs_init_server_aclclient(server);
+	nfs_init_server_aclclient(server, acred);
 	dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
 	return 0;
 
@@ -651,7 +660,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
 /*
  * Probe filesystem information, including the FSID on v2/v3
  */
-static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh,
+			    struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct nfs_fsinfo fsinfo;
 	struct nfs_client *clp = server->nfs_client;
@@ -660,14 +670,14 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
 	dprintk("--> nfs_probe_fsinfo()\n");
 
 	if (clp->rpc_ops->set_capabilities != NULL) {
-		error = clp->rpc_ops->set_capabilities(server, mntfh);
+		error = clp->rpc_ops->set_capabilities(server, mntfh, acred);
 		if (error < 0)
 			goto out_error;
 	}
 
 	fsinfo.fattr = fattr;
 	nfs_fattr_init(fattr);
-	error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
+	error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo, acred);
 	if (error < 0)
 		goto out_error;
 
@@ -680,7 +690,8 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
 		pathinfo.fattr = fattr;
 		nfs_fattr_init(fattr);
 
-		if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
+		if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo,
+					   acred) >= 0)
 			server->namelen = pathinfo.max_namelen;
 	}
 
@@ -761,7 +772,7 @@ void nfs_free_server(struct nfs_server *server)
  * - keyed on server and FSID
  */
 struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
-				     struct nfs_fh *mntfh)
+				     struct nfs_fh *mntfh, struct cred *acred)
 {
 	struct nfs_server *server;
 	struct nfs_fattr fattr;
@@ -772,7 +783,7 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 		return ERR_PTR(-ENOMEM);
 
 	/* Get a client representation */
-	error = nfs_init_server(server, data);
+	error = nfs_init_server(server, data, acred);
 	if (error < 0)
 		goto error;
 
@@ -781,7 +792,7 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID */
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 	if (server->nfs_client->rpc_ops->version == 3) {
@@ -795,7 +806,8 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 	}
 
 	if (!(fattr.valid & NFS_ATTR_FATTR)) {
-		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, mntfh,
+							     &fattr, acred);
 		if (error < 0) {
 			dprintk("nfs_create_server: getattr error = %d\n", -error);
 			goto error;
@@ -831,7 +843,8 @@ error:
 static int nfs4_init_client(struct nfs_client *clp,
 		int proto, int timeo, int retrans,
 		const char *ip_addr,
-		rpc_authflavor_t authflavour)
+		rpc_authflavor_t authflavour,
+		struct cred *acred)
 {
 	int error;
 
@@ -845,7 +858,7 @@ static int nfs4_init_client(struct nfs_client *clp,
 	clp->rpc_ops = &nfs_v4_clientops;
 
 	error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour,
-					RPC_CLNT_CREATE_DISCRTRY);
+					RPC_CLNT_CREATE_DISCRTRY, acred);
 	if (error < 0)
 		goto error;
 	memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -874,7 +887,8 @@ static int nfs4_set_client(struct nfs_server *server,
 		const char *hostname, const struct sockaddr_in *addr,
 		const char *ip_addr,
 		rpc_authflavor_t authflavour,
-		int proto, int timeo, int retrans)
+		int proto, int timeo, int retrans,
+		struct cred *acred)
 {
 	struct nfs_client *clp;
 	int error;
@@ -882,12 +896,13 @@ static int nfs4_set_client(struct nfs_server *server,
 	dprintk("--> nfs4_set_client()\n");
 
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(hostname, addr, 4);
+	clp = nfs_get_client(hostname, addr, 4, acred);
 	if (IS_ERR(clp)) {
 		error = PTR_ERR(clp);
 		goto error;
 	}
-	error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour);
+	error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr,
+				 authflavour, acred);
 	if (error < 0)
 		goto error_put;
 
@@ -943,7 +958,8 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 				      const char *mntpath,
 				      const char *ip_addr,
 				      rpc_authflavor_t authflavour,
-				      struct nfs_fh *mntfh)
+				      struct nfs_fh *mntfh,
+				      struct cred *acred)
 {
 	struct nfs_fattr fattr;
 	struct nfs_server *server;
@@ -957,7 +973,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 
 	/* Get a client record */
 	error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour,
-			data->proto, data->timeo, data->retrans);
+			data->proto, data->timeo, data->retrans, acred);
 	if (error < 0)
 		goto error;
 
@@ -971,7 +987,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID */
-	error = nfs4_path_walk(server, mntfh, mntpath);
+	error = nfs4_path_walk(server, mntfh, mntpath, acred);
 	if (error < 0)
 		goto error;
 
@@ -980,7 +996,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 		(unsigned long long) server->fsid.minor);
 	dprintk("Mount FH: %d\n", mntfh->size);
 
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 
@@ -1010,7 +1026,8 @@ error:
  * Create an NFS4 referral server record
  */
 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
-					       struct nfs_fh *mntfh)
+					       struct nfs_fh *mntfh,
+					       struct cred *acred)
 {
 	struct nfs_client *parent_client;
 	struct nfs_server *server, *parent_server;
@@ -1033,7 +1050,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 			data->authflavor,
 			parent_server->client->cl_xprt->prot,
 			parent_client->retrans_timeo,
-			parent_client->retrans_count);
+			parent_client->retrans_count,
+			acred);
 	if (error < 0)
 		goto error;
 
@@ -1050,12 +1068,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID and filehandle */
-	error = nfs4_path_walk(server, mntfh, data->mnt_path);
+	error = nfs4_path_walk(server, mntfh, data->mnt_path, acred);
 	if (error < 0)
 		goto error;
 
 	/* probe the filesystem info for this server filesystem */
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 
@@ -1089,7 +1107,8 @@ error:
  */
 struct nfs_server *nfs_clone_server(struct nfs_server *source,
 				    struct nfs_fh *fh,
-				    struct nfs_fattr *fattr)
+				    struct nfs_fattr *fattr,
+				    struct cred *acred)
 {
 	struct nfs_server *server;
 	struct nfs_fattr fattr_fsinfo;
@@ -1114,10 +1133,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 	if (error < 0)
 		goto out_free_server;
 	if (!IS_ERR(source->client_acl))
-		nfs_init_server_aclclient(server);
+		nfs_init_server_aclclient(server, acred);
 
 	/* probe the filesystem info for this server filesystem */
-	error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
+	error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo, acred);
 	if (error < 0)
 		goto out_free_server;
 
@@ -1128,7 +1147,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 		(unsigned long long) server->fsid.major,
 		(unsigned long long) server->fsid.minor);
 
-	error = nfs_start_lockd(server);
+	error = nfs_start_lockd(server, acred);
 	if (error < 0)
 		goto out_free_server;
 
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index c55a761..3686cc0 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -29,6 +29,7 @@ static void nfs_free_delegation_callback(struct rcu_head *head)
 {
 	struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
 
+	put_cred(delegation->acred);
 	nfs_do_free_delegation(delegation);
 }
 
@@ -106,7 +107,8 @@ again:
 /*
  * Set up a delegation on an inode
  */
-void nfs_inode_reclaim_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, struct cred *acred)
 {
 	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
 
@@ -118,6 +120,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
 	delegation->maxsize = res->maxsize;
 	put_rpccred(cred);
 	delegation->cred = get_rpccred(cred);
+	put_cred(delegation->acred);
+	delegation->acred = get_cred(acred);
 	delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
 	NFS_I(inode)->delegation_state = delegation->type;
 	smp_wmb();
@@ -126,7 +130,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
 /*
  * Set up a delegation on an inode
  */
-int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
+			     struct nfs_openres *res, struct cred *acred)
 {
 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -142,6 +147,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
 	delegation->maxsize = res->maxsize;
 	delegation->change_attr = nfsi->change_attr;
 	delegation->cred = get_rpccred(cred);
+	delegation->acred = get_cred(acred);
 	delegation->inode = inode;
 
 	spin_lock(&clp->cl_lock);
@@ -170,11 +176,14 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
 	return status;
 }
 
-static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+static int nfs_do_return_delegation(struct inode *inode,
+				    struct nfs_delegation *delegation,
+				    struct cred *acred)
 {
 	int res = 0;
 
-	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
+	res = nfs4_proc_delegreturn(inode, delegation->cred,
+				    &delegation->stateid, acred);
 	nfs_free_delegation(delegation);
 	return res;
 }
@@ -190,7 +199,8 @@ static void nfs_msync_inode(struct inode *inode)
 /*
  * Basic procedure for returning a delegation to the server
  */
-static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+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);
@@ -204,7 +214,7 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
 	up_read(&clp->cl_sem);
 	nfs_msync_inode(inode);
 
-	return nfs_do_return_delegation(inode, delegation);
+	return nfs_do_return_delegation(inode, delegation, delegation->acred);
 }
 
 static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
@@ -383,7 +393,7 @@ static int recall_thread(void *data)
 	nfs_msync_inode(inode);
 
 	if (delegation != NULL)
-		nfs_do_return_delegation(inode, delegation);
+		nfs_do_return_delegation(inode, delegation, &init_cred);
 	iput(inode);
 	module_put_and_exit(0);
 }
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 5874ce7..6319594 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -15,6 +15,7 @@
 struct nfs_delegation {
 	struct list_head super_list;
 	struct rpc_cred *cred;
+	struct cred *acred;
 	struct inode *inode;
 	nfs4_stateid stateid;
 	int type;
@@ -25,8 +26,10 @@ struct nfs_delegation {
 	struct rcu_head rcu;
 };
 
-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_set_delegation(struct inode *inode, struct rpc_cred *cred,
+			     struct nfs_openres *res, struct cred *acred);
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
+				  struct nfs_openres *res, struct cred *acred);
 int nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
@@ -39,7 +42,8 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp);
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
-int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred,
+			  const nfs4_stateid *stateid, struct cred *acred);
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 53b9e24..35a63cf 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -175,6 +175,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 {
 	struct file	*file = desc->file;
 	struct inode	*inode = file->f_path.dentry->d_inode;
+	struct cred	*acred = file->f_cred;
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	unsigned long	timestamp;
 	int		error;
@@ -186,7 +187,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
  again:
 	timestamp = jiffies;
 	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
-					  NFS_SERVER(inode)->dtsize, desc->plus);
+					  NFS_SERVER(inode)->dtsize, desc->plus,
+					  acred);
 	if (error < 0) {
 		/* We requested READDIRPLUS, but the server doesn't grok it */
 		if (error == -ENOTSUPP && desc->plus) {
@@ -472,6 +474,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 {
 	struct file	*file = desc->file;
 	struct inode	*inode = file->f_path.dentry->d_inode;
+	struct cred	*acred = file->f_cred;
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	struct page	*page = NULL;
 	int		status;
@@ -489,7 +492,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 	desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
 						page,
 						NFS_SERVER(inode)->dtsize,
-						desc->plus);
+						desc->plus, acred);
 	spin_lock(&inode->i_lock);
 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
 	spin_unlock(&inode->i_lock);
@@ -527,6 +530,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
  */
 static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
+	struct cred	*acred = filp->f_cred;
 	struct dentry	*dentry = filp->f_path.dentry;
 	struct inode	*inode = dentry->d_inode;
 	nfs_readdir_descriptor_t my_desc,
@@ -543,7 +547,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 	lock_kernel();
 
-	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping, acred);
 	if (res < 0) {
 		unlock_kernel();
 		return res;
@@ -703,7 +707,8 @@ static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigne
  *
  */
 static inline
-int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
+int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd,
+			    struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 
@@ -718,9 +723,9 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
 				 S_ISDIR(inode->i_mode)))
 			goto out_force;
 	}
-	return nfs_revalidate_inode(server, inode);
+	return nfs_revalidate_inode(server, inode, acred);
 out_force:
-	return __nfs_revalidate_inode(server, inode);
+	return __nfs_revalidate_inode(server, inode, acred);
 }
 
 /*
@@ -753,6 +758,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
  */
 static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct inode *dir;
 	struct inode *inode;
 	struct dentry *parent;
@@ -768,7 +774,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	inode = dentry->d_inode;
 
 	/* Revalidate parent directory attribute cache */
-	if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+	if (nfs_revalidate_inode(NFS_SERVER(dir), dir, acred) < 0)
 		goto out_zap_parent;
 
 	if (!inode) {
@@ -786,7 +792,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 
 	/* Force a full look up iff the parent directory has changed */
 	if (nfs_check_verifier(dir, dentry)) {
-		if (nfs_lookup_verify_inode(inode, nd))
+		if (nfs_lookup_verify_inode(inode, nd, acred))
 			goto out_zap_parent;
 		goto out_valid;
 	}
@@ -795,7 +801,8 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 		goto out_bad;
 
 	verifier = nfs_save_change_attribute(dir);
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr,
+				       acred);
 	if (error)
 		goto out_bad;
 	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
@@ -869,7 +876,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		lock_kernel();
 		drop_nlink(inode);
-		nfs_complete_unlink(dentry, inode);
+		nfs_complete_unlink(dentry, inode, &init_cred);
 		unlock_kernel();
 	}
 	/* When creating a negative dentry, we want to renew d_time */
@@ -897,18 +904,20 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
 	return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
-static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr,
+				 struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 
 	if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
 		/* Revalidate fsid using the parent directory */
-		return __nfs_revalidate_inode(server, dir);
+		return __nfs_revalidate_inode(server, dir, acred);
 	return 0;
 }
 
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *res;
 	struct inode *inode = NULL;
 	int error;
@@ -938,14 +947,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 		goto out_unlock;
 	}
 
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr,
+				       acred);
 	if (error == -ENOENT)
 		goto no_entry;
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unlock;
 	}
-	error = nfs_reval_fsid(dir, &fattr);
+	error = nfs_reval_fsid(dir, &fattr, acred);
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unlock;
@@ -1004,6 +1014,7 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
 
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *res = NULL;
 	int error;
 
@@ -1029,7 +1040,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 	/* Open the file on the server */
 	lock_kernel();
 	/* Revalidate parent directory attribute cache */
-	error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	error = nfs_revalidate_inode(NFS_SERVER(dir), dir, acred);
 	if (error < 0) {
 		res = ERR_PTR(error);
 		unlock_kernel();
@@ -1038,10 +1049,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 
 	if (nd->intent.open.flags & O_CREAT) {
 		nfs_begin_data_update(dir);
-		res = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd, acred);
 		nfs_end_data_update(dir);
 	} else
-		res = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd, acred);
 	unlock_kernel();
 	if (IS_ERR(res)) {
 		error = PTR_ERR(res);
@@ -1073,6 +1084,7 @@ no_open:
 
 static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
 	struct inode *dir;
@@ -1105,7 +1117,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	 */
 	lock_kernel();
 	verifier = nfs_save_change_attribute(dir);
-	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+	ret = nfs4_open_revalidate(dir, dentry, openflags, nd, acred);
 	if (!ret)
 		nfs_refresh_verifier(dentry, verifier);
 	unlock_kernel();
@@ -1196,7 +1208,7 @@ out_renew:
  * Code common to create, mkdir, and mknod.
  */
 int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
-				struct nfs_fattr *fattr)
+				struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct inode *inode;
 	int error = -EACCES;
@@ -1206,13 +1218,15 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 		return 0;
 	if (fhandle->size == 0) {
 		struct inode *dir = dentry->d_parent->d_inode;
-		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle,
+					       fattr, acred);
 		if (error)
 			return error;
 	}
 	if (!(fattr->valid & NFS_ATTR_FATTR)) {
 		struct nfs_server *server = NFS_SB(dentry->d_sb);
-		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, fhandle,
+							     fattr, acred);
 		if (error < 0)
 			return error;
 	}
@@ -1235,6 +1249,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 	int open_flags = 0;
@@ -1250,7 +1265,8 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd,
+				       acred);
 	nfs_end_data_update(dir);
 	if (error != 0)
 		goto out_err;
@@ -1270,6 +1286,7 @@ out_err:
 static int
 nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int status;
 
@@ -1284,7 +1301,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
+	status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev, acred);
 	nfs_end_data_update(dir);
 	if (status != 0)
 		goto out_err;
@@ -1303,6 +1320,7 @@ out_err:
  */
 static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 
@@ -1314,7 +1332,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
+	error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr, acred);
 	nfs_end_data_update(dir);
 	if (error != 0)
 		goto out_err;
@@ -1330,6 +1348,7 @@ out_err:
 
 static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	int error;
 
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
@@ -1337,7 +1356,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
+	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name, acred);
 	/* Ensure the VFS deletes this inode */
 	if (error == 0 && dentry->d_inode != NULL)
 		clear_nlink(dentry->d_inode);
@@ -1347,7 +1366,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 	return error;
 }
 
-static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
+static int nfs_sillyrename(struct inode *dir, struct dentry *dentry,
+			   struct cred *acred)
 {
 	static unsigned int sillycounter;
 	const int      i_inosize  = sizeof(dir->i_ino)*2;
@@ -1402,18 +1422,18 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 	if (dentry->d_inode) {
 		nfs_begin_data_update(dentry->d_inode);
 		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
+				dir, &qsilly, acred);
 		nfs_mark_for_revalidate(dentry->d_inode);
 		nfs_end_data_update(dentry->d_inode);
 	} else
 		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
+				dir, &qsilly, acred);
 	nfs_end_data_update(dir);
 	if (!error) {
 		nfs_renew_times(dentry);
 		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 		d_move(dentry, sdentry);
-		error = nfs_async_unlink(dir, dentry);
+		error = nfs_async_unlink(dir, dentry, acred);
  		/* If we return 0 we don't unlink */
 	}
 	dput(sdentry);
@@ -1428,7 +1448,7 @@ out:
  * We invalidate the attribute cache and free the inode prior to the operation
  * to avoid possible races if the server reuses the inode.
  */
-static int nfs_safe_remove(struct dentry *dentry)
+static int nfs_safe_remove(struct dentry *dentry, struct cred *acred)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	struct inode *inode = dentry->d_inode;
@@ -1447,14 +1467,14 @@ static int nfs_safe_remove(struct dentry *dentry)
 	if (inode != NULL) {
 		nfs_inode_return_delegation(inode);
 		nfs_begin_data_update(inode);
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, acred);
 		/* The VFS may want to delete this inode */
 		if (error == 0)
 			drop_nlink(inode);
 		nfs_mark_for_revalidate(inode);
 		nfs_end_data_update(inode);
 	} else
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, acred);
 	nfs_end_data_update(dir);
 out:
 	return error;
@@ -1467,6 +1487,7 @@ out:
  */
 static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	int error;
 	int need_rehash = 0;
 
@@ -1481,7 +1502,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 		spin_unlock(&dcache_lock);
 		/* Start asynchronous writeout of the inode */
 		write_inode_now(dentry->d_inode, 0);
-		error = nfs_sillyrename(dir, dentry);
+		error = nfs_sillyrename(dir, dentry, acred);
 		unlock_kernel();
 		return error;
 	}
@@ -1491,7 +1512,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 	}
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
-	error = nfs_safe_remove(dentry);
+	error = nfs_safe_remove(dentry, acred);
 	if (!error) {
 		nfs_renew_times(dentry);
 		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -1518,6 +1539,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
  */
 static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
+	struct cred *acred = current->cred;
 	struct pagevec lru_pvec;
 	struct page *page;
 	char *kaddr;
@@ -1549,7 +1571,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 	kunmap_atomic(kaddr, KM_USER0);
 
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
+	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr,
+					acred);
 	nfs_end_data_update(dir);
 	if (error != 0) {
 		dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
@@ -1582,6 +1605,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 static int 
 nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int error;
 
@@ -1592,7 +1616,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 	lock_kernel();
 	nfs_begin_data_update(dir);
 	nfs_begin_data_update(inode);
-	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name, acred);
 	if (error == 0) {
 		atomic_inc(&inode->i_count);
 		d_instantiate(dentry, inode);
@@ -1630,6 +1654,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		      struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *acred = current->cred;
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL, *rehash = NULL;
@@ -1673,7 +1698,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			goto out;
 
 		/* silly-rename the existing target ... */
-		err = nfs_sillyrename(new_dir, new_dentry);
+		err = nfs_sillyrename(new_dir, new_dentry, acred);
 		if (!err) {
 			new_dentry = rehash = dentry;
 			new_inode = NULL;
@@ -1705,7 +1730,8 @@ go_ahead:
 	nfs_begin_data_update(new_dir);
 	nfs_begin_data_update(old_inode);
 	error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
-					   new_dir, &new_dentry->d_name);
+					   new_dir, &new_dentry->d_name,
+					   acred);
 	nfs_mark_for_revalidate(old_inode);
 	nfs_end_data_update(old_inode);
 	nfs_end_data_update(new_dir);
@@ -1934,7 +1960,8 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
 	}
 }
 
-static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask,
+			 struct cred *acred)
 {
 	struct nfs_access_entry cache;
 	int status;
@@ -1947,7 +1974,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
 	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
 	cache.cred = cred;
 	cache.jiffies = jiffies;
-	status = NFS_PROTO(inode)->access(inode, &cache);
+	status = NFS_PROTO(inode)->access(inode, &cache, acred);
 	if (status != 0)
 		return status;
 	nfs_access_add_cache(inode, &cache);
@@ -1998,7 +2025,7 @@ force_lookup:
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, acred);
 	if (!IS_ERR(cred)) {
-		res = nfs_do_access(inode, cred, mask);
+		res = nfs_do_access(inode, cred, mask, acred);
 		put_rpccred(cred);
 	} else
 		res = PTR_ERR(cred);
@@ -2008,7 +2035,7 @@ out:
 		inode->i_sb->s_id, inode->i_ino, mask, res);
 	return res;
 out_notsup:
-	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 	if (res == 0)
 		res = generic_permission(inode, mask, NULL);
 	unlock_kernel();
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index fcf4d38..6c9491b 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -291,14 +291,14 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
 					data->npages, 1, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
 		if (result < 0) {
-			nfs_readdata_release(data);
+			nfs_readdata_release(ctx->acred, data);
 			break;
 		}
 		if ((unsigned)result < data->npages) {
 			bytes = result * PAGE_SIZE;
 			if (bytes <= pgbase) {
 				nfs_direct_release_pages(data->pagevec, result);
-				nfs_readdata_release(data);
+				nfs_readdata_release(ctx->acred, data);
 				break;
 			}
 			bytes -= pgbase;
@@ -321,8 +321,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
 		data->res.count = bytes;
 
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_read_direct_ops, data);
-		NFS_PROTO(inode)->read_setup(data);
+			      &nfs_read_direct_ops, data, ctx->acred);
+		NFS_PROTO(inode)->read_setup(data, ctx->acred);
 
 		data->task.tk_cookie = (unsigned long) inode;
 
@@ -389,7 +389,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
 		struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
 		list_del(&data->pages);
 		nfs_direct_release_pages(data->pagevec, data->npages);
-		nfs_writedata_release(data);
+		nfs_writedata_release(dreq->ctx->acred, data);
 	}
 }
 
@@ -420,8 +420,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 		 * since the original request was sent.
 		 */
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_write_direct_ops, data);
-		NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE);
+				&nfs_write_direct_ops, data, dreq->ctx->acred);
+		NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE,
+					      dreq->ctx->acred);
 
 		data->task.tk_priority = RPC_PRIORITY_NORMAL;
 		data->task.tk_cookie = (unsigned long) inode;
@@ -484,8 +485,8 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 	data->res.verf = &data->verf;
 
 	rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC,
-				&nfs_commit_direct_ops, data);
-	NFS_PROTO(data->inode)->commit_setup(data, 0);
+				&nfs_commit_direct_ops, data, dreq->ctx->acred);
+	NFS_PROTO(data->inode)->commit_setup(data, 0, dreq->ctx->acred);
 
 	data->task.tk_priority = RPC_PRIORITY_NORMAL;
 	data->task.tk_cookie = (unsigned long)data->inode;
@@ -582,7 +583,7 @@ out_unlock:
  * NB: Return the value of the first error return code.  Subsequent
  *     errors after the first one are ignored.
  */
-static void nfs_direct_write_release(void *calldata)
+static void nfs_direct_write_release(struct cred *acred, void *calldata)
 {
 	struct nfs_write_data *data = calldata;
 	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
@@ -631,14 +632,14 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
 					data->npages, 0, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
 		if (result < 0) {
-			nfs_writedata_release(data);
+			nfs_writedata_release(ctx->acred, data);
 			break;
 		}
 		if ((unsigned)result < data->npages) {
 			bytes = result * PAGE_SIZE;
 			if (bytes <= pgbase) {
 				nfs_direct_release_pages(data->pagevec, result);
-				nfs_writedata_release(data);
+				nfs_writedata_release(ctx->acred, data);
 				break;
 			}
 			bytes -= pgbase;
@@ -663,8 +664,8 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
 		data->res.verf = &data->verf;
 
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_write_direct_ops, data);
-		NFS_PROTO(inode)->write_setup(data, sync);
+				&nfs_write_direct_ops, data, ctx->acred);
+		NFS_PROTO(inode)->write_setup(data, sync, ctx->acred);
 
 		data->task.tk_priority = RPC_PRIORITY_NORMAL;
 		data->task.tk_cookie = (unsigned long) inode;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 579cf8a..72f0850 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -158,7 +158,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
 	if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
 		return 0;
 force_reval:
-	return __nfs_revalidate_inode(server, inode);
+	return __nfs_revalidate_inode(server, inode, filp->f_cred);
 }
 
 static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
@@ -196,7 +196,8 @@ nfs_file_flush(struct file *file, fl_owner_t id)
 		status = ctx->error;
 		ctx->error = 0;
 		if (!status)
-			nfs_revalidate_inode(NFS_SERVER(inode), inode);
+			nfs_revalidate_inode(NFS_SERVER(inode), inode,
+					     ctx->acred);
 	}
 	unlock_kernel();
 	return status;
@@ -208,6 +209,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
 {
 	struct dentry * dentry = iocb->ki_filp->f_path.dentry;
 	struct inode * inode = dentry->d_inode;
+	struct cred *acred = iocb->ki_filp->f_cred;
 	ssize_t result;
 	size_t count = iov_length(iov, nr_segs);
 
@@ -220,7 +222,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long) pos);
 
-	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
+	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping, acred);
 	nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
 	if (!result)
 		result = generic_file_aio_read(iocb, iov, nr_segs, pos);
@@ -234,13 +236,14 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
+	struct cred *acred = filp->f_cred;
 	ssize_t res;
 
 	dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
-	res = nfs_revalidate_mapping(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping(inode, filp->f_mapping, acred);
 	if (!res)
 		res = generic_file_splice_read(filp, ppos, pipe, count, flags);
 	return res;
@@ -251,12 +254,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
+	struct cred *acred = file->f_cred;
 	int	status;
 
 	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	status = nfs_revalidate_mapping(inode, file->f_mapping);
+	status = nfs_revalidate_mapping(inode, file->f_mapping, acred);
 	if (!status)
 		status = generic_file_mmap(file, vma);
 	return status;
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 93d1479..17a0ac8 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -45,7 +45,8 @@
 /*
  * get an NFS2/NFS3 root dentry from the root filehandle
  */
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			    struct cred *acred)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fsinfo fsinfo;
@@ -84,7 +85,8 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	/* get the actual root for this mount */
 	fsinfo.fattr = &fattr;
 
-	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo,
+						     acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
 		return ERR_PTR(error);
@@ -126,7 +128,8 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
  */
 int nfs4_path_walk(struct nfs_server *server,
 		   struct nfs_fh *mntfh,
-		   const char *path)
+		   const char *path,
+		   struct cred *acred)
 {
 	struct nfs_fsinfo fsinfo;
 	struct nfs_fattr fattr;
@@ -144,7 +147,8 @@ int nfs4_path_walk(struct nfs_server *server,
 		path++;
 
 	/* Start by getting the root filehandle from the server */
-	ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+	ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo,
+						   acred);
 	if (ret < 0) {
 		dprintk("nfs4_get_root: getroot error = %d\n", -ret);
 		return ret;
@@ -201,7 +205,7 @@ eat_dot_dir:
 	dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path);
 
 	ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name,
-						    mntfh, &fattr);
+						    mntfh, &fattr, acred);
 	if (ret < 0) {
 		dprintk("nfs4_get_root: getroot error = %d\n", -ret);
 		return ret;
@@ -231,7 +235,8 @@ path_walk_complete:
 /*
  * get an NFS4 root dentry from the root filehandle
  */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			     struct cred *acred)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fattr fattr;
@@ -269,7 +274,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	/* get the info about the server and filesystem */
-	error = nfs4_server_capabilities(server, mntfh);
+	error = nfs4_server_capabilities(server, mntfh, acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getcaps error = %d\n",
 			-error);
@@ -277,7 +282,8 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	/* get the actual root for this mount */
-	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr,
+						     acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
 		return ERR_PTR(error);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0dd2ac3..300560f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -321,6 +321,7 @@ out_no_inode:
 int
 nfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct nfs_fattr fattr;
 	int error;
@@ -349,7 +350,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 	 */
 	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
 		nfs_inode_return_delegation(inode);
-	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+	error =
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 00/52] Introduce credential record, David Howells, (Fri Oct 12, 12:05 pm)
Re: [PATCH 00/52] Introduce credential record, Theodore Tso, (Sat Oct 13, 2:11 pm)
Re: [PATCH 00/52] Introduce credential record, David Howells, (Sat Oct 13, 5:46 pm)
Re: [PATCH 00/52] Introduce credential record, Al Viro, (Sat Oct 13, 2:19 pm)
[PATCH 52/52] CRED: Pass credentials through vfs_mkdir(), David Howells, (Fri Oct 12, 12:09 pm)
[PATCH 20/52] CRED: Pass credentials into rpc_init_task(), David Howells, (Fri Oct 12, 12:07 pm)
[PATCH 14/52] CRED: Provide a writeback credentials record, David Howells, (Fri Oct 12, 12:06 pm)
[PATCH 06/52] CRED: Prepare RAMFS for cred passing, David Howells, (Fri Oct 12, 12:05 pm)
[PATCH 05/52] CRED: Prepare TMPFS for cred passing, David Howells, (Fri Oct 12, 12:05 pm)
[PATCH 01/52] CRED: Introduce a COW credentials record, David Howells, (Fri Oct 12, 12:05 pm)
[PATCH 02/52] CRED: Give in_group_p() a cred pointer, David Howells, (Fri Oct 12, 12:05 pm)
speck-geostationary