aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c10
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c10
-rw-r--r--fs/nfs/nfs4state.c35
-rw-r--r--include/linux/nfs_fs_sb.h1
6 files changed, 54 insertions, 5 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bb7432d83b5a..d28a987f569e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -366,7 +366,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
366 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 366 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
367 367
368 /* Don't match clients that failed to initialise properly */ 368 /* Don't match clients that failed to initialise properly */
369 if (clp->cl_cons_state != NFS_CS_READY) 369 if (!(clp->cl_cons_state == NFS_CS_READY ||
370 clp->cl_cons_state == NFS_CS_SESSION_INITING))
370 continue; 371 continue;
371 372
372 /* Different NFS versions cannot share the same nfs_client */ 373 /* Different NFS versions cannot share the same nfs_client */
@@ -499,7 +500,7 @@ found_client:
499 nfs_free_client(new); 500 nfs_free_client(new);
500 501
501 error = wait_event_killable(nfs_client_active_wq, 502 error = wait_event_killable(nfs_client_active_wq,
502 clp->cl_cons_state != NFS_CS_INITING); 503 clp->cl_cons_state < NFS_CS_INITING);
503 if (error < 0) { 504 if (error < 0) {
504 nfs_put_client(clp); 505 nfs_put_client(clp);
505 return ERR_PTR(-ERESTARTSYS); 506 return ERR_PTR(-ERESTARTSYS);
@@ -520,7 +521,7 @@ found_client:
520/* 521/*
521 * Mark a server as ready or failed 522 * Mark a server as ready or failed
522 */ 523 */
523static void nfs_mark_client_ready(struct nfs_client *clp, int state) 524void nfs_mark_client_ready(struct nfs_client *clp, int state)
524{ 525{
525 clp->cl_cons_state = state; 526 clp->cl_cons_state = state;
526 wake_up_all(&nfs_client_active_wq); 527 wake_up_all(&nfs_client_active_wq);
@@ -1135,7 +1136,8 @@ static int nfs4_init_client(struct nfs_client *clp,
1135 if (error < 0) 1136 if (error < 0)
1136 goto error; 1137 goto error;
1137 1138
1138 nfs_mark_client_ready(clp, NFS_CS_READY); 1139 if (!nfs4_has_session(clp))
1140 nfs_mark_client_ready(clp, NFS_CS_READY);
1139 return 0; 1141 return 0;
1140 1142
1141error: 1143error:
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index f62bc5226155..f3b310e8ea03 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -100,6 +100,7 @@ extern void nfs_free_server(struct nfs_server *server);
100extern struct nfs_server *nfs_clone_server(struct nfs_server *, 100extern struct nfs_server *nfs_clone_server(struct nfs_server *,
101 struct nfs_fh *, 101 struct nfs_fh *,
102 struct nfs_fattr *); 102 struct nfs_fattr *);
103extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
103#ifdef CONFIG_PROC_FS 104#ifdef CONFIG_PROC_FS
104extern int __init nfs_fs_proc_init(void); 105extern int __init nfs_fs_proc_init(void);
105extern void nfs_fs_proc_exit(void); 106extern void nfs_fs_proc_exit(void);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index eccf4e93e7d7..288717abaddc 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -44,6 +44,7 @@ enum nfs4_client_state {
44 NFS4CLNT_RECLAIM_REBOOT, 44 NFS4CLNT_RECLAIM_REBOOT,
45 NFS4CLNT_RECLAIM_NOGRACE, 45 NFS4CLNT_RECLAIM_NOGRACE,
46 NFS4CLNT_DELEGRETURN, 46 NFS4CLNT_DELEGRETURN,
47 NFS4CLNT_SESSION_SETUP,
47}; 48};
48 49
49/* 50/*
@@ -208,6 +209,7 @@ extern int nfs4_setup_sequence(struct nfs_client *clp,
208 int cache_reply, struct rpc_task *task); 209 int cache_reply, struct rpc_task *task);
209extern void nfs4_destroy_session(struct nfs4_session *session); 210extern void nfs4_destroy_session(struct nfs4_session *session);
210extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); 211extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
212extern int nfs4_proc_create_session(struct nfs_client *, int reset);
211#else /* CONFIG_NFS_v4_1 */ 213#else /* CONFIG_NFS_v4_1 */
212static inline int nfs4_setup_sequence(struct nfs_client *clp, 214static inline int nfs4_setup_sequence(struct nfs_client *clp,
213 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, 215 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0b1214740248..7fc0c9c8f5e3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4382,6 +4382,16 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
4382 session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL); 4382 session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL);
4383 if (!session) 4383 if (!session)
4384 return NULL; 4384 return NULL;
4385
4386 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
4387 /*
4388 * The create session reply races with the server back
4389 * channel probe. Mark the client NFS_CS_SESSION_INITING
4390 * so that the client back channel can find the
4391 * nfs_client struct
4392 */
4393 clp->cl_cons_state = NFS_CS_SESSION_INITING;
4394
4385 tbl = &session->fc_slot_table; 4395 tbl = &session->fc_slot_table;
4386 spin_lock_init(&tbl->slot_tbl_lock); 4396 spin_lock_init(&tbl->slot_tbl_lock);
4387 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table"); 4397 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table");
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index bc683ed477e1..df5b4807daa7 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1113,6 +1113,27 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
1113 return status; 1113 return status;
1114} 1114}
1115 1115
1116#ifdef CONFIG_NFS_V4_1
1117
1118static int nfs4_initialize_session(struct nfs_client *clp)
1119{
1120 int status;
1121
1122 status = nfs4_proc_create_session(clp, 0);
1123 if (!status) {
1124 nfs_mark_client_ready(clp, NFS_CS_READY);
1125 } else if (status == -NFS4ERR_STALE_CLIENTID) {
1126 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1127 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
1128 } else {
1129 nfs_mark_client_ready(clp, status);
1130 }
1131 return status;
1132}
1133#else /* CONFIG_NFS_V4_1 */
1134static int nfs4_initialize_session(struct nfs_client *clp) { return 0; }
1135#endif /* CONFIG_NFS_V4_1 */
1136
1116static void nfs4_state_manager(struct nfs_client *clp) 1137static void nfs4_state_manager(struct nfs_client *clp)
1117{ 1138{
1118 int status = 0; 1139 int status = 0;
@@ -1126,6 +1147,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
1126 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1147 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1127 if (status == -EAGAIN) 1148 if (status == -EAGAIN)
1128 continue; 1149 continue;
1150 if (clp->cl_cons_state ==
1151 NFS_CS_SESSION_INITING)
1152 nfs_mark_client_ready(clp, status);
1129 goto out_error; 1153 goto out_error;
1130 } 1154 }
1131 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); 1155 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
@@ -1136,7 +1160,16 @@ static void nfs4_state_manager(struct nfs_client *clp)
1136 if (status != 0) 1160 if (status != 0)
1137 continue; 1161 continue;
1138 } 1162 }
1139 1163 /* Setup the session */
1164 if (nfs4_has_session(clp) &&
1165 test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
1166 status = nfs4_initialize_session(clp);
1167 if (status) {
1168 if (status == -NFS4ERR_STALE_CLIENTID)
1169 continue;
1170 goto out_error;
1171 }
1172 }
1140 /* First recover reboot state... */ 1173 /* First recover reboot state... */
1141 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { 1174 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
1142 status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops); 1175 status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 435ed556efb5..d0902ccec9ce 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -24,6 +24,7 @@ struct nfs_client {
24 int cl_cons_state; /* current construction state (-ve: init error) */ 24 int cl_cons_state; /* current construction state (-ve: init error) */
25#define NFS_CS_READY 0 /* ready to be used */ 25#define NFS_CS_READY 0 /* ready to be used */
26#define NFS_CS_INITING 1 /* busy initialising */ 26#define NFS_CS_INITING 1 /* busy initialising */
27#define NFS_CS_SESSION_INITING 2 /* busy initialising session */
27 unsigned long cl_res_state; /* NFS resources state */ 28 unsigned long cl_res_state; /* NFS resources state */
28#define NFS_CS_CALLBACK 1 /* - callback started */ 29#define NFS_CS_CALLBACK 1 /* - callback started */
29#define NFS_CS_IDMAP 2 /* - idmap started */ 30#define NFS_CS_IDMAP 2 /* - idmap started */