[pnfs] [PATCH 21/23] 2.6-latest sessions exchange_id AUTH_SYS root cred
andros at umich.edu
andros at umich.edu
Thu Dec 13 15:51:47 EST 2007
From: Andy Adamson <andros at umich.edu>
Unlike NFSv4.0, NFSv4.1 requires machine credentials. RPC_AUTH_GSS machine
credentials will be passed into the kernel at mount time to be available for
the exchange_id operation.
RPC_AUTH_UNIX root mounts can use the UNIX root credential. Store the root
credential in the nfs_client struct.
Without a credential, NFSv4.1 state renewal fails.
Signed-off by: Andy Adamson<andros at umich.edu>
---
fs/nfs/client.c | 5 +++++
fs/nfs/nfs4_fs.h | 4 ++++
fs/nfs/nfs4proc.c | 27 +++++++++++++++++++++++++++
fs/nfs/nfs4renewd.c | 10 ++--------
fs/nfs/nfs4state.c | 10 +++++++++-
include/linux/nfs_fs_sb.h | 1 +
6 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index dee739c..4e7cd62 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -183,6 +183,11 @@ static void nfs_free_client(struct nfs_client *clp)
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
nfs_callback_down();
+#ifdef CONFIG_NFS_V4_1
+ if (clp->cl_ex_cred)
+ put_rpccred(clp->cl_ex_cred);
+#endif /* CONFIG_NFS_V4_1 */
+
kfree(clp->cl_hostname);
kfree(clp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index e47a6d1..c5a4d5b 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -167,6 +167,7 @@ struct nfs4_state_recovery_ops {
struct nfs4_state_maintenance_ops {
int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *);
+ struct rpc_cred * (*get_state_renewal_cred)(struct nfs_client *);
};
extern struct dentry_operations nfs4_dentry_operations;
@@ -219,6 +220,9 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
+#ifdef CONFIG_NFS_V4_1
+struct rpc_cred *nfs41_get_state_renewal_cred(struct nfs_client *clp);
+#endif /* CONFIG_NFS_V4_1 */
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 *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index cef988f..f3aa86e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3757,6 +3757,31 @@ int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
else if (++clp->cl_id_uniquifier == 0)
break;
}
+ if (status == 0) {
+ struct rpc_clnt *clnt = clp->cl_rpcclient;
+
+ /* NFSv4.1 will use machine creds acquired at mount, and will
+ * need to remember which creds were used for the EXCHANGE_ID.
+ * Add an rpc cred pointer to struct nfs_client to hold
+ * the EXCHANGE_ID cred, and enable AUTH_UNIX mounts.
+ */
+ if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX &&
+ current->fsuid == 0) {
+
+ dprintk("%s cl_ex_cred %p [NULL]\n", __func__,
+ clp->cl_ex_cred);
+
+ clp->cl_ex_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+ atomic_inc(&clp->cl_ex_cred->cr_count);
+
+ dprintk("%s set cl_ex_cred %p\n",
+ __func__, clp->cl_ex_cred);
+
+ } else {
+ dprintk("%s not AUTH_SYS don't save EXCHANGE_ID cred\n",
+ __func__);
+ }
+ }
dprintk("<-- %s status= %d\n", __FUNCTION__, status);
return status;
@@ -5144,11 +5169,13 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {
struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
.sched_state_renewal = nfs4_proc_async_renew,
+ .get_state_renewal_cred = nfs41_get_state_renewal_cred,
};
#if defined (CONFIG_NFS_V4_1)
struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
.sched_state_renewal = nfs41_proc_async_sequence,
+ .get_state_renewal_cred = nfs4_get_renew_cred,
};
#endif
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index cf7f46b..20667d8 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -64,7 +64,7 @@ nfs4_renew_state(struct work_struct *work)
struct nfs4_state_maintenance_ops *ops;
struct nfs_client *clp =
container_of(work, struct nfs_client, cl_renewd.work);
- struct rpc_cred *cred;
+ struct rpc_cred *cred = NULL;
long lease, timeout;
unsigned long last, now;
@@ -81,13 +81,7 @@ 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)) {
-#if defined CONFIG_NFS_V4_1
- dprintk("%s NO STATE RENEWAL: ops->sched_state_renewal()",
- "not implemented\n", __func__);
- cred = NULL;
-#else
- cred = nfs4_get_renew_cred(clp);
-#endif /* CONFIG_NFS_V4_1 */
+ cred = ops->get_state_renewal_cred(clp);
if (cred == NULL) {
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
spin_unlock(&clp->cl_lock);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c70983a..4df00b9 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -90,7 +90,15 @@ u64 nfs41_clientid(struct nfs_client *clp)
{
return 0;
}
-#endif
+
+struct rpc_cred * nfs41_get_state_renewal_cred(struct nfs_client *clp)
+{
+
+ if (clp->cl_ex_cred)
+ get_rpccred(clp->cl_ex_cred);
+ return (clp->cl_ex_cred);
+}
+#endif /* CONFIG_NFS_V4_1 */
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
{
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c36b6dd..be3cd86 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -78,6 +78,7 @@ struct nfs_client {
u32 cl_seqid;
/* The flags used for obtaining the clientid during EXCHANGE_ID */
u32 cl_exchange_flags;
+ struct rpc_cred * cl_ex_cred; /* exchange_id credential */
#endif
#ifdef CONFIG_PNFS
struct nfs4_session * cl_ds_session; /* pNFS data server session */
--
1.5.0.2
More information about the pNFS
mailing list