diff options
-rw-r--r-- | fs/nfs/nfs4_fs.h | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 38 | ||||
-rw-r--r-- | fs/nfs/nfs4renewd.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 16 |
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); | |||
213 | extern int nfs4_map_errors(int err); | 213 | extern int nfs4_map_errors(int err); |
214 | extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); | 214 | extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); |
215 | extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); | 215 | extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); |
216 | extern int nfs4_proc_async_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 *); | 217 | extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *); |
218 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); | 218 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); |
219 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 219 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
220 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 220 | extern 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 *); | |||
240 | extern void nfs4_put_client(struct nfs4_client *clp); | 240 | extern void nfs4_put_client(struct nfs4_client *clp); |
241 | extern int nfs4_init_client(struct nfs4_client *clp); | 241 | extern int nfs4_init_client(struct nfs4_client *clp); |
242 | extern struct nfs4_client *nfs4_find_client(struct in_addr *); | 242 | extern struct nfs4_client *nfs4_find_client(struct in_addr *); |
243 | struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp); | ||
243 | extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); | 244 | extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); |
244 | 245 | ||
245 | extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); | 246 | extern 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); |
889 | out_ok: | 890 | out_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; |
896 | out_put_open_state: | ||
897 | nfs4_put_open_state(state); | ||
895 | out_err: | 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 | 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); |
903 | out_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 | ||
2521 | int | 2521 | int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred) |
2522 | nfs4_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 | ||
2534 | int | 2533 | int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred) |
2535 | nfs4_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 | |||
62 | nfs4_renew_state(void *data) | 62 | nfs4_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 | ||
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 | static struct nfs4_state_owner * | 249 | static struct nfs4_state_owner * |
236 | nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) | 250 | nfs4_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; |
901 | restart_loop: | 915 | restart_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: |