aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-03 03:55:25 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:47 -0500
commitb4454fe1a7cb76a248d0641c9d68a44a1b8d9a1f (patch)
tree50ddc265e9700b1924e45ffce0f4583ba1013177
parent58d9714a44a79bba9b414da3ffbf3c753dc5915f (diff)
NFSv4: Remove requirement for machine creds for the "renew" operation
In RFC3530, the RENEW operation is allowed to use either the same principal, RPC security flavour and (if RPCSEC_GSS), the same mechanism and service that was used for SETCLIENTID_CONFIRM OR Any principal, RPC security flavour and service combination that currently has an OPEN file on the server. Choose the latter since that doesn't require us to keep credentials for the same principal for the entire duration of the mount. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4_fs.h5
-rw-r--r--fs/nfs/nfs4proc.c38
-rw-r--r--fs/nfs/nfs4renewd.c7
-rw-r--r--fs/nfs/nfs4state.c16
4 files changed, 41 insertions, 25 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 75fe646c28ab..4a9c53e0793c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -213,8 +213,8 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
213extern int nfs4_map_errors(int err); 213extern int nfs4_map_errors(int err);
214extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); 214extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
215extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); 215extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
216extern int nfs4_proc_async_renew(struct nfs4_client *); 216extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *);
217extern int nfs4_proc_renew(struct nfs4_client *); 217extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *);
218extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); 218extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
219extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 219extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
220extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 220extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
@@ -240,6 +240,7 @@ extern struct nfs4_client *nfs4_get_client(struct in_addr *);
240extern void nfs4_put_client(struct nfs4_client *clp); 240extern void nfs4_put_client(struct nfs4_client *clp);
241extern int nfs4_init_client(struct nfs4_client *clp); 241extern int nfs4_init_client(struct nfs4_client *clp);
242extern struct nfs4_client *nfs4_find_client(struct in_addr *); 242extern struct nfs4_client *nfs4_find_client(struct in_addr *);
243struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp);
243extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); 244extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
244 245
245extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); 246extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index cc33a1c32cfb..e38401931291 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -850,9 +850,14 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
850 int open_flags = flags & (FMODE_READ|FMODE_WRITE); 850 int open_flags = flags & (FMODE_READ|FMODE_WRITE);
851 int err; 851 int err;
852 852
853 err = -ENOMEM;
854 if (!(sp = nfs4_get_state_owner(server, cred))) {
855 dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
856 return err;
857 }
853 err = nfs4_recover_expired_lease(server); 858 err = nfs4_recover_expired_lease(server);
854 if (err != 0) 859 if (err != 0)
855 return err; 860 goto out_put_state_owner;
856 /* Protect against reboot recovery - NOTE ORDER! */ 861 /* Protect against reboot recovery - NOTE ORDER! */
857 down_read(&clp->cl_sem); 862 down_read(&clp->cl_sem);
858 /* Protect against delegation recall */ 863 /* Protect against delegation recall */
@@ -862,10 +867,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
862 if (delegation == NULL || (delegation->type & open_flags) != open_flags) 867 if (delegation == NULL || (delegation->type & open_flags) != open_flags)
863 goto out_err; 868 goto out_err;
864 err = -ENOMEM; 869 err = -ENOMEM;
865 if (!(sp = nfs4_get_state_owner(server, cred))) {
866 dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
867 goto out_err;
868 }
869 state = nfs4_get_open_state(inode, sp); 870 state = nfs4_get_open_state(inode, sp);
870 if (state == NULL) 871 if (state == NULL)
871 goto out_err; 872 goto out_err;
@@ -877,13 +878,13 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
877 spin_unlock(&inode->i_lock); 878 spin_unlock(&inode->i_lock);
878 goto out_ok; 879 goto out_ok;
879 } else if (state->state != 0) 880 } else if (state->state != 0)
880 goto out_err; 881 goto out_put_open_state;
881 882
882 lock_kernel(); 883 lock_kernel();
883 err = _nfs4_do_access(inode, cred, open_flags); 884 err = _nfs4_do_access(inode, cred, open_flags);
884 unlock_kernel(); 885 unlock_kernel();
885 if (err != 0) 886 if (err != 0)
886 goto out_err; 887 goto out_put_open_state;
887 set_bit(NFS_DELEGATED_STATE, &state->flags); 888 set_bit(NFS_DELEGATED_STATE, &state->flags);
888 update_open_stateid(state, &delegation->stateid, open_flags); 889 update_open_stateid(state, &delegation->stateid, open_flags);
889out_ok: 890out_ok:
@@ -891,17 +892,16 @@ out_ok:
891 up_read(&nfsi->rwsem); 892 up_read(&nfsi->rwsem);
892 up_read(&clp->cl_sem); 893 up_read(&clp->cl_sem);
893 *res = state; 894 *res = state;
894 return 0; 895 return 0;
896out_put_open_state:
897 nfs4_put_open_state(state);
895out_err: 898out_err:
896 if (sp != NULL) {
897 if (state != NULL)
898 nfs4_put_open_state(state);
899 nfs4_put_state_owner(sp);
900 }
901 up_read(&nfsi->rwsem); 899 up_read(&nfsi->rwsem);
902 up_read(&clp->cl_sem); 900 up_read(&clp->cl_sem);
903 if (err != -EACCES) 901 if (err != -EACCES)
904 nfs_inode_return_delegation(inode); 902 nfs_inode_return_delegation(inode);
903out_put_state_owner:
904 nfs4_put_state_owner(sp);
905 return err; 905 return err;
906} 906}
907 907
@@ -941,7 +941,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
941 } 941 }
942 status = nfs4_recover_expired_lease(server); 942 status = nfs4_recover_expired_lease(server);
943 if (status != 0) 943 if (status != 0)
944 goto out_err; 944 goto err_put_state_owner;
945 down_read(&clp->cl_sem); 945 down_read(&clp->cl_sem);
946 status = -ENOMEM; 946 status = -ENOMEM;
947 opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr); 947 opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
@@ -2518,26 +2518,24 @@ static const struct rpc_call_ops nfs4_renew_ops = {
2518 .rpc_call_done = nfs4_renew_done, 2518 .rpc_call_done = nfs4_renew_done,
2519}; 2519};
2520 2520
2521int 2521int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred)
2522nfs4_proc_async_renew(struct nfs4_client *clp)
2523{ 2522{
2524 struct rpc_message msg = { 2523 struct rpc_message msg = {
2525 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], 2524 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2526 .rpc_argp = clp, 2525 .rpc_argp = clp,
2527 .rpc_cred = clp->cl_cred, 2526 .rpc_cred = cred,
2528 }; 2527 };
2529 2528
2530 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, 2529 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
2531 &nfs4_renew_ops, (void *)jiffies); 2530 &nfs4_renew_ops, (void *)jiffies);
2532} 2531}
2533 2532
2534int 2533int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred)
2535nfs4_proc_renew(struct nfs4_client *clp)
2536{ 2534{
2537 struct rpc_message msg = { 2535 struct rpc_message msg = {
2538 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], 2536 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2539 .rpc_argp = clp, 2537 .rpc_argp = clp,
2540 .rpc_cred = clp->cl_cred, 2538 .rpc_cred = cred,
2541 }; 2539 };
2542 unsigned long now = jiffies; 2540 unsigned long now = jiffies;
2543 int status; 2541 int status;
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index f62c2f7a4ffb..5d764d8e6d8a 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -62,6 +62,7 @@ void
62nfs4_renew_state(void *data) 62nfs4_renew_state(void *data)
63{ 63{
64 struct nfs4_client *clp = (struct nfs4_client *)data; 64 struct nfs4_client *clp = (struct nfs4_client *)data;
65 struct rpc_cred *cred;
65 long lease, timeout; 66 long lease, timeout;
66 unsigned long last, now; 67 unsigned long last, now;
67 68
@@ -77,7 +78,8 @@ nfs4_renew_state(void *data)
77 timeout = (2 * lease) / 3 + (long)last - (long)now; 78 timeout = (2 * lease) / 3 + (long)last - (long)now;
78 /* Are we close to a lease timeout? */ 79 /* Are we close to a lease timeout? */
79 if (time_after(now, last + lease/3)) { 80 if (time_after(now, last + lease/3)) {
80 if (list_empty(&clp->cl_state_owners)) { 81 cred = nfs4_get_renew_cred(clp);
82 if (cred == NULL) {
81 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 83 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
82 spin_unlock(&clp->cl_lock); 84 spin_unlock(&clp->cl_lock);
83 nfs_expire_all_delegations(clp); 85 nfs_expire_all_delegations(clp);
@@ -85,7 +87,8 @@ nfs4_renew_state(void *data)
85 } 87 }
86 spin_unlock(&clp->cl_lock); 88 spin_unlock(&clp->cl_lock);
87 /* Queue an asynchronous RENEW. */ 89 /* Queue an asynchronous RENEW. */
88 nfs4_proc_async_renew(clp); 90 nfs4_proc_async_renew(clp, cred);
91 put_rpccred(cred);
89 timeout = (2 * lease) / 3; 92 timeout = (2 * lease) / 3;
90 spin_lock(&clp->cl_lock); 93 spin_lock(&clp->cl_lock);
91 } else 94 } else
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index f2148376f1a7..18f6ed1a0b54 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -232,6 +232,20 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred)
232 return sp; 232 return sp;
233} 233}
234 234
235struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp)
236{
237 struct nfs4_state_owner *sp;
238 struct rpc_cred *cred = NULL;
239
240 list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
241 if (list_empty(&sp->so_states))
242 continue;
243 cred = get_rpccred(sp->so_cred);
244 break;
245 }
246 return cred;
247}
248
235static struct nfs4_state_owner * 249static struct nfs4_state_owner *
236nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) 250nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred)
237{ 251{
@@ -899,7 +913,7 @@ static int reclaimer(void *ptr)
899 if (list_empty(&clp->cl_superblocks)) 913 if (list_empty(&clp->cl_superblocks))
900 goto out; 914 goto out;
901restart_loop: 915restart_loop:
902 status = nfs4_proc_renew(clp); 916 status = nfs4_proc_renew(clp, clp->cl_cred);
903 switch (status) { 917 switch (status) {
904 case 0: 918 case 0:
905 case -NFS4ERR_CB_PATH_DOWN: 919 case -NFS4ERR_CB_PATH_DOWN: