Commit b4454fe1a7cb76a248d0641c9d68a44a1b8d9a1f

Authored by Trond Myklebust
1 parent 58d9714a44

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>

Showing 4 changed files with 41 additions and 25 deletions Side-by-side Diff

... ... @@ -213,8 +213,8 @@
213 213 extern int nfs4_map_errors(int err);
214 214 extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
215 215 extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
216   -extern int nfs4_proc_async_renew(struct nfs4_client *);
217   -extern int nfs4_proc_renew(struct nfs4_client *);
  216 +extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *);
  217 +extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *);
218 218 extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
219 219 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
220 220 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
... ... @@ -240,6 +240,7 @@
240 240 extern void nfs4_put_client(struct nfs4_client *clp);
241 241 extern int nfs4_init_client(struct nfs4_client *clp);
242 242 extern struct nfs4_client *nfs4_find_client(struct in_addr *);
  243 +struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp);
243 244 extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
244 245  
245 246 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
... ... @@ -850,9 +850,14 @@
850 850 int open_flags = flags & (FMODE_READ|FMODE_WRITE);
851 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 858 err = nfs4_recover_expired_lease(server);
854 859 if (err != 0)
855   - return err;
  860 + goto out_put_state_owner;
856 861 /* Protect against reboot recovery - NOTE ORDER! */
857 862 down_read(&clp->cl_sem);
858 863 /* Protect against delegation recall */
... ... @@ -862,10 +867,6 @@
862 867 if (delegation == NULL || (delegation->type & open_flags) != open_flags)
863 868 goto out_err;
864 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 870 state = nfs4_get_open_state(inode, sp);
870 871 if (state == NULL)
871 872 goto out_err;
872 873  
... ... @@ -877,13 +878,13 @@
877 878 spin_unlock(&inode->i_lock);
878 879 goto out_ok;
879 880 } else if (state->state != 0)
880   - goto out_err;
  881 + goto out_put_open_state;
881 882  
882 883 lock_kernel();
883 884 err = _nfs4_do_access(inode, cred, open_flags);
884 885 unlock_kernel();
885 886 if (err != 0)
886   - goto out_err;
  887 + goto out_put_open_state;
887 888 set_bit(NFS_DELEGATED_STATE, &state->flags);
888 889 update_open_stateid(state, &delegation->stateid, open_flags);
889 890 out_ok:
890 891  
891 892  
... ... @@ -891,17 +892,16 @@
891 892 up_read(&nfsi->rwsem);
892 893 up_read(&clp->cl_sem);
893 894 *res = state;
894   - return 0;
  895 + return 0;
  896 +out_put_open_state:
  897 + nfs4_put_open_state(state);
895 898 out_err:
896   - if (sp != NULL) {
897   - if (state != NULL)
898   - nfs4_put_open_state(state);
899   - nfs4_put_state_owner(sp);
900   - }
901 899 up_read(&nfsi->rwsem);
902 900 up_read(&clp->cl_sem);
903 901 if (err != -EACCES)
904 902 nfs_inode_return_delegation(inode);
  903 +out_put_state_owner:
  904 + nfs4_put_state_owner(sp);
905 905 return err;
906 906 }
907 907  
... ... @@ -941,7 +941,7 @@
941 941 }
942 942 status = nfs4_recover_expired_lease(server);
943 943 if (status != 0)
944   - goto out_err;
  944 + goto err_put_state_owner;
945 945 down_read(&clp->cl_sem);
946 946 status = -ENOMEM;
947 947 opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
948 948  
949 949  
950 950  
... ... @@ -2518,26 +2518,24 @@
2518 2518 .rpc_call_done = nfs4_renew_done,
2519 2519 };
2520 2520  
2521   -int
2522   -nfs4_proc_async_renew(struct nfs4_client *clp)
  2521 +int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred)
2523 2522 {
2524 2523 struct rpc_message msg = {
2525 2524 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2526 2525 .rpc_argp = clp,
2527   - .rpc_cred = clp->cl_cred,
  2526 + .rpc_cred = cred,
2528 2527 };
2529 2528  
2530 2529 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
2531 2530 &nfs4_renew_ops, (void *)jiffies);
2532 2531 }
2533 2532  
2534   -int
2535   -nfs4_proc_renew(struct nfs4_client *clp)
  2533 +int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred)
2536 2534 {
2537 2535 struct rpc_message msg = {
2538 2536 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
2539 2537 .rpc_argp = clp,
2540   - .rpc_cred = clp->cl_cred,
  2538 + .rpc_cred = cred,
2541 2539 };
2542 2540 unsigned long now = jiffies;
2543 2541 int status;
... ... @@ -62,6 +62,7 @@
62 62 nfs4_renew_state(void *data)
63 63 {
64 64 struct nfs4_client *clp = (struct nfs4_client *)data;
  65 + struct rpc_cred *cred;
65 66 long lease, timeout;
66 67 unsigned long last, now;
67 68  
... ... @@ -77,7 +78,8 @@
77 78 timeout = (2 * lease) / 3 + (long)last - (long)now;
78 79 /* Are we close to a lease timeout? */
79 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 83 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
82 84 spin_unlock(&clp->cl_lock);
83 85 nfs_expire_all_delegations(clp);
... ... @@ -85,7 +87,8 @@
85 87 }
86 88 spin_unlock(&clp->cl_lock);
87 89 /* Queue an asynchronous RENEW. */
88   - nfs4_proc_async_renew(clp);
  90 + nfs4_proc_async_renew(clp, cred);
  91 + put_rpccred(cred);
89 92 timeout = (2 * lease) / 3;
90 93 spin_lock(&clp->cl_lock);
91 94 } else
... ... @@ -232,6 +232,20 @@
232 232 return sp;
233 233 }
234 234  
  235 +struct 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 +
235 249 static struct nfs4_state_owner *
236 250 nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred)
237 251 {
... ... @@ -899,7 +913,7 @@
899 913 if (list_empty(&clp->cl_superblocks))
900 914 goto out;
901 915 restart_loop:
902   - status = nfs4_proc_renew(clp);
  916 + status = nfs4_proc_renew(clp, clp->cl_cred);
903 917 switch (status) {
904 918 case 0:
905 919 case -NFS4ERR_CB_PATH_DOWN: