diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 3e2f19b04c06..f575a3126737 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -40,12 +40,13 @@ | |||
40 | 40 | ||
41 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/smp_lock.h> | 43 | #include <linux/fs.h> |
44 | #include <linux/nfs_fs.h> | 44 | #include <linux/nfs_fs.h> |
45 | #include <linux/nfs_idmap.h> | 45 | #include <linux/nfs_idmap.h> |
46 | #include <linux/kthread.h> | 46 | #include <linux/kthread.h> |
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/random.h> | 48 | #include <linux/random.h> |
49 | #include <linux/ratelimit.h> | ||
49 | #include <linux/workqueue.h> | 50 | #include <linux/workqueue.h> |
50 | #include <linux/bitops.h> | 51 | #include <linux/bitops.h> |
51 | 52 | ||
@@ -53,6 +54,7 @@ | |||
53 | #include "callback.h" | 54 | #include "callback.h" |
54 | #include "delegation.h" | 55 | #include "delegation.h" |
55 | #include "internal.h" | 56 | #include "internal.h" |
57 | #include "pnfs.h" | ||
56 | 58 | ||
57 | #define OPENOWNER_POOL_SIZE 8 | 59 | #define OPENOWNER_POOL_SIZE 8 |
58 | 60 | ||
@@ -970,13 +972,13 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ | |||
970 | /* Guard against delegation returns and new lock/unlock calls */ | 972 | /* Guard against delegation returns and new lock/unlock calls */ |
971 | down_write(&nfsi->rwsem); | 973 | down_write(&nfsi->rwsem); |
972 | /* Protect inode->i_flock using the BKL */ | 974 | /* Protect inode->i_flock using the BKL */ |
973 | lock_kernel(); | 975 | lock_flocks(); |
974 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 976 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
975 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 977 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
976 | continue; | 978 | continue; |
977 | if (nfs_file_open_context(fl->fl_file)->state != state) | 979 | if (nfs_file_open_context(fl->fl_file)->state != state) |
978 | continue; | 980 | continue; |
979 | unlock_kernel(); | 981 | unlock_flocks(); |
980 | status = ops->recover_lock(state, fl); | 982 | status = ops->recover_lock(state, fl); |
981 | switch (status) { | 983 | switch (status) { |
982 | case 0: | 984 | case 0: |
@@ -1003,9 +1005,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ | |||
1003 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 1005 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
1004 | status = 0; | 1006 | status = 0; |
1005 | } | 1007 | } |
1006 | lock_kernel(); | 1008 | lock_flocks(); |
1007 | } | 1009 | } |
1008 | unlock_kernel(); | 1010 | unlock_flocks(); |
1009 | out: | 1011 | out: |
1010 | up_write(&nfsi->rwsem); | 1012 | up_write(&nfsi->rwsem); |
1011 | return status; | 1013 | return status; |
@@ -1063,6 +1065,14 @@ restart: | |||
1063 | /* Mark the file as being 'closed' */ | 1065 | /* Mark the file as being 'closed' */ |
1064 | state->state = 0; | 1066 | state->state = 0; |
1065 | break; | 1067 | break; |
1068 | case -EKEYEXPIRED: | ||
1069 | /* | ||
1070 | * User RPCSEC_GSS context has expired. | ||
1071 | * We cannot recover this stateid now, so | ||
1072 | * skip it and allow recovery thread to | ||
1073 | * proceed. | ||
1074 | */ | ||
1075 | break; | ||
1066 | case -NFS4ERR_ADMIN_REVOKED: | 1076 | case -NFS4ERR_ADMIN_REVOKED: |
1067 | case -NFS4ERR_STALE_STATEID: | 1077 | case -NFS4ERR_STALE_STATEID: |
1068 | case -NFS4ERR_BAD_STATEID: | 1078 | case -NFS4ERR_BAD_STATEID: |
@@ -1138,16 +1148,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp, | |||
1138 | (void)ops->reclaim_complete(clp); | 1148 | (void)ops->reclaim_complete(clp); |
1139 | } | 1149 | } |
1140 | 1150 | ||
1141 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | 1151 | static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) |
1142 | { | 1152 | { |
1143 | struct nfs4_state_owner *sp; | 1153 | struct nfs4_state_owner *sp; |
1144 | struct rb_node *pos; | 1154 | struct rb_node *pos; |
1145 | struct nfs4_state *state; | 1155 | struct nfs4_state *state; |
1146 | 1156 | ||
1147 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1157 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
1148 | return; | 1158 | return 0; |
1149 | |||
1150 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | ||
1151 | 1159 | ||
1152 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { | 1160 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { |
1153 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); | 1161 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); |
@@ -1161,6 +1169,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | |||
1161 | } | 1169 | } |
1162 | 1170 | ||
1163 | nfs_delegation_reap_unclaimed(clp); | 1171 | nfs_delegation_reap_unclaimed(clp); |
1172 | return 1; | ||
1173 | } | ||
1174 | |||
1175 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | ||
1176 | { | ||
1177 | if (!nfs4_state_clear_reclaim_reboot(clp)) | ||
1178 | return; | ||
1179 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | ||
1164 | } | 1180 | } |
1165 | 1181 | ||
1166 | static void nfs_delegation_clear_all(struct nfs_client *clp) | 1182 | static void nfs_delegation_clear_all(struct nfs_client *clp) |
@@ -1175,6 +1191,14 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) | |||
1175 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); | 1191 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); |
1176 | } | 1192 | } |
1177 | 1193 | ||
1194 | static void nfs4_warn_keyexpired(const char *s) | ||
1195 | { | ||
1196 | printk_ratelimited(KERN_WARNING "Error: state manager" | ||
1197 | " encountered RPCSEC_GSS session" | ||
1198 | " expired against NFSv4 server %s.\n", | ||
1199 | s); | ||
1200 | } | ||
1201 | |||
1178 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | 1202 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) |
1179 | { | 1203 | { |
1180 | switch (error) { | 1204 | switch (error) { |
@@ -1187,7 +1211,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1187 | case -NFS4ERR_STALE_CLIENTID: | 1211 | case -NFS4ERR_STALE_CLIENTID: |
1188 | case -NFS4ERR_LEASE_MOVED: | 1212 | case -NFS4ERR_LEASE_MOVED: |
1189 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1213 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1190 | nfs4_state_end_reclaim_reboot(clp); | 1214 | nfs4_state_clear_reclaim_reboot(clp); |
1191 | nfs4_state_start_reclaim_reboot(clp); | 1215 | nfs4_state_start_reclaim_reboot(clp); |
1192 | break; | 1216 | break; |
1193 | case -NFS4ERR_EXPIRED: | 1217 | case -NFS4ERR_EXPIRED: |
@@ -1204,6 +1228,10 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1204 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | 1228 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
1205 | /* Zero session reset errors */ | 1229 | /* Zero session reset errors */ |
1206 | return 0; | 1230 | return 0; |
1231 | case -EKEYEXPIRED: | ||
1232 | /* Nothing we can do */ | ||
1233 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1234 | return 0; | ||
1207 | } | 1235 | } |
1208 | return error; | 1236 | return error; |
1209 | } | 1237 | } |
@@ -1414,9 +1442,10 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status) | |||
1414 | case -NFS4ERR_DELAY: | 1442 | case -NFS4ERR_DELAY: |
1415 | case -NFS4ERR_CLID_INUSE: | 1443 | case -NFS4ERR_CLID_INUSE: |
1416 | case -EAGAIN: | 1444 | case -EAGAIN: |
1417 | case -EKEYEXPIRED: | ||
1418 | break; | 1445 | break; |
1419 | 1446 | ||
1447 | case -EKEYEXPIRED: | ||
1448 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1420 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | 1449 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery |
1421 | * in nfs4_exchange_id */ | 1450 | * in nfs4_exchange_id */ |
1422 | default: | 1451 | default: |
@@ -1447,6 +1476,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1447 | } | 1476 | } |
1448 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | 1477 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
1449 | set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); | 1478 | set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); |
1479 | pnfs_destroy_all_layouts(clp); | ||
1450 | } | 1480 | } |
1451 | 1481 | ||
1452 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { | 1482 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { |