aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c60
-rw-r--r--fs/nfs/internal.h12
-rw-r--r--fs/nfs/nfs4_fs.h4
-rw-r--r--fs/nfs/nfs4proc.c34
-rw-r--r--include/linux/nfs_fs_sb.h49
-rw-r--r--include/linux/nfs_xdr.h15
6 files changed, 174 insertions, 0 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a736160046c3..f1506f148521 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -184,12 +184,27 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
184} 184}
185 185
186/* 186/*
187 * Clears/puts all minor version specific parts from an nfs_client struct
188 * reverting it to minorversion 0.
189 */
190static void nfs4_clear_client_minor_version(struct nfs_client *clp)
191{
192#ifdef CONFIG_NFS_V4_1
193 if (nfs4_has_session(clp)) {
194 nfs4_destroy_session(clp->cl_session);
195 clp->cl_session = NULL;
196 }
197#endif /* CONFIG_NFS_V4_1 */
198}
199
200/*
187 * Destroy a shared client record 201 * Destroy a shared client record
188 */ 202 */
189static void nfs_free_client(struct nfs_client *clp) 203static void nfs_free_client(struct nfs_client *clp)
190{ 204{
191 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); 205 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
192 206
207 nfs4_clear_client_minor_version(clp);
193 nfs4_shutdown_client(clp); 208 nfs4_shutdown_client(clp);
194 209
195 nfs_fscache_release_client_cookie(clp); 210 nfs_fscache_release_client_cookie(clp);
@@ -1054,6 +1069,30 @@ error:
1054 1069
1055#ifdef CONFIG_NFS_V4 1070#ifdef CONFIG_NFS_V4
1056/* 1071/*
1072 * Initialize the minor version specific parts of an NFS4 client record
1073 */
1074static int nfs4_init_client_minor_version(struct nfs_client *clp)
1075{
1076#if defined(CONFIG_NFS_V4_1)
1077 if (clp->cl_minorversion) {
1078 struct nfs4_session *session = NULL;
1079 /*
1080 * Create the session and mark it expired.
1081 * When a SEQUENCE operation encounters the expired session
1082 * it will do session recovery to initialize it.
1083 */
1084 session = nfs4_alloc_session(clp);
1085 if (!session)
1086 return -ENOMEM;
1087
1088 clp->cl_session = session;
1089 }
1090#endif /* CONFIG_NFS_V4_1 */
1091
1092 return 0;
1093}
1094
1095/*
1057 * Initialise an NFS4 client record 1096 * Initialise an NFS4 client record
1058 */ 1097 */
1059static int nfs4_init_client(struct nfs_client *clp, 1098static int nfs4_init_client(struct nfs_client *clp,
@@ -1087,6 +1126,10 @@ static int nfs4_init_client(struct nfs_client *clp,
1087 } 1126 }
1088 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); 1127 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
1089 1128
1129 error = nfs4_init_client_minor_version(clp);
1130 if (error < 0)
1131 goto error;
1132
1090 nfs_mark_client_ready(clp, NFS_CS_READY); 1133 nfs_mark_client_ready(clp, NFS_CS_READY);
1091 return 0; 1134 return 0;
1092 1135
@@ -1144,6 +1187,21 @@ error:
1144} 1187}
1145 1188
1146/* 1189/*
1190 * Initialize a session.
1191 * Note: save the mount rsize and wsize for create_server negotiation.
1192 */
1193static void nfs4_init_session(struct nfs_client *clp,
1194 unsigned int wsize, unsigned int rsize)
1195{
1196#if defined(CONFIG_NFS_V4_1)
1197 if (nfs4_has_session(clp)) {
1198 clp->cl_session->fc_attrs.max_rqst_sz = wsize;
1199 clp->cl_session->fc_attrs.max_resp_sz = rsize;
1200 }
1201#endif /* CONFIG_NFS_V4_1 */
1202}
1203
1204/*
1147 * Create a version 4 volume record 1205 * Create a version 4 volume record
1148 */ 1206 */
1149static int nfs4_init_server(struct nfs_server *server, 1207static int nfs4_init_server(struct nfs_server *server,
@@ -1221,6 +1279,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1221 BUG_ON(!server->nfs_client->rpc_ops); 1279 BUG_ON(!server->nfs_client->rpc_ops);
1222 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1280 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
1223 1281
1282 nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
1283
1224 /* Probe the root fh to retrieve its FSID */ 1284 /* Probe the root fh to retrieve its FSID */
1225 error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); 1285 error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
1226 if (error < 0) 1286 if (error < 0)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ffa6bd54d439..7cef45db9257 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -207,6 +207,18 @@ extern int nfs4_path_walk(struct nfs_server *server,
207#endif 207#endif
208 208
209/* 209/*
210 * Determine if sessions are in use.
211 */
212static inline int nfs4_has_session(const struct nfs_client *clp)
213{
214#ifdef CONFIG_NFS_V4_1
215 if (clp->cl_session)
216 return 1;
217#endif /* CONFIG_NFS_V4_1 */
218 return 0;
219}
220
221/*
210 * Determine the device name as a string 222 * Determine the device name as a string
211 */ 223 */
212static inline char *nfs_devname(const struct vfsmount *mnt_parent, 224static inline char *nfs_devname(const struct vfsmount *mnt_parent,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 84345deab26f..acac6f8c3d39 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -202,6 +202,10 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
202 202
203extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; 203extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
204extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops; 204extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops;
205#if defined(CONFIG_NFS_V4_1)
206extern void nfs4_destroy_session(struct nfs4_session *session);
207extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
208#endif /* CONFIG_NFS_V4_1 */
205 209
206extern const u32 nfs4_fattr_bitmap[2]; 210extern const u32 nfs4_fattr_bitmap[2];
207extern const u32 nfs4_statfs_bitmap[2]; 211extern const u32 nfs4_statfs_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4674f8092da8..cdd8e74c47d0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3723,6 +3723,40 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
3723 return status; 3723 return status;
3724} 3724}
3725 3725
3726#ifdef CONFIG_NFS_V4_1
3727/* Destroy the slot table */
3728static void nfs4_destroy_slot_table(struct nfs4_session *session)
3729{
3730 if (session->fc_slot_table.slots == NULL)
3731 return;
3732 kfree(session->fc_slot_table.slots);
3733 session->fc_slot_table.slots = NULL;
3734 return;
3735}
3736
3737struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
3738{
3739 struct nfs4_session *session;
3740 struct nfs4_slot_table *tbl;
3741
3742 session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL);
3743 if (!session)
3744 return NULL;
3745 tbl = &session->fc_slot_table;
3746 spin_lock_init(&tbl->slot_tbl_lock);
3747 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table");
3748 session->clp = clp;
3749 return session;
3750}
3751
3752void nfs4_destroy_session(struct nfs4_session *session)
3753{
3754 nfs4_destroy_slot_table(session);
3755 kfree(session);
3756}
3757
3758#endif /* CONFIG_NFS_V4_1 */
3759
3726struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { 3760struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
3727 .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, 3761 .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
3728 .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, 3762 .state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index e9a51fe46aa3..b47c0fc55d42 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -4,9 +4,12 @@
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/backing-dev.h> 5#include <linux/backing-dev.h>
6#include <linux/wait.h> 6#include <linux/wait.h>
7#include <linux/nfs_xdr.h>
8#include <linux/sunrpc/xprt.h>
7 9
8#include <asm/atomic.h> 10#include <asm/atomic.h>
9 11
12struct nfs4_session;
10struct nfs_iostats; 13struct nfs_iostats;
11struct nlm_host; 14struct nlm_host;
12 15
@@ -66,6 +69,10 @@ struct nfs_client {
66 unsigned char cl_id_uniquifier; 69 unsigned char cl_id_uniquifier;
67#endif /* CONFIG_NFS_V4 */ 70#endif /* CONFIG_NFS_V4 */
68 71
72#ifdef CONFIG_NFS_V4_1
73 struct nfs4_session *cl_session; /* sharred session */
74#endif /* CONFIG_NFS_V4_1 */
75
69#ifdef CONFIG_NFS_FSCACHE 76#ifdef CONFIG_NFS_FSCACHE
70 struct fscache_cookie *fscache; /* client index cache cookie */ 77 struct fscache_cookie *fscache; /* client index cache cookie */
71#endif 78#endif
@@ -146,4 +153,46 @@ struct nfs_server {
146#define NFS_CAP_ACLS (1U << 3) 153#define NFS_CAP_ACLS (1U << 3)
147#define NFS_CAP_ATOMIC_OPEN (1U << 4) 154#define NFS_CAP_ATOMIC_OPEN (1U << 4)
148 155
156
157/* maximum number of slots to use */
158#define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE
159
160#if defined(CONFIG_NFS_V4_1)
161
162/* Sessions */
163#define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
164struct nfs4_slot_table {
165 struct nfs4_slot *slots; /* seqid per slot */
166 unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
167 spinlock_t slot_tbl_lock;
168 struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
169 int max_slots; /* # slots in table */
170 int highest_used_slotid; /* sent to server on each SEQ.
171 * op for dynamic resizing */
172};
173
174static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
175{
176 return sp - tbl->slots;
177}
178
179/*
180 * Session related parameters
181 */
182struct nfs4_session {
183 struct nfs4_sessionid sess_id;
184 u32 flags;
185 unsigned long session_state;
186 u32 hash_alg;
187 u32 ssv_len;
188
189 /* The fore and back channel */
190 struct nfs4_channel_attrs fc_attrs;
191 struct nfs4_slot_table fc_slot_table;
192 struct nfs4_channel_attrs bc_attrs;
193 /* back channel has one slot */
194 struct nfs_client *clp;
195};
196
197#endif /* CONFIG_NFS_V4_1 */
149#endif 198#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index f2c5700c7b6e..8f8c026c558e 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -146,6 +146,21 @@ struct nfs4_change_info {
146 146
147struct nfs_seqid; 147struct nfs_seqid;
148 148
149/* nfs41 sessions channel attributes */
150struct nfs4_channel_attrs {
151 u32 headerpadsz;
152 u32 max_rqst_sz;
153 u32 max_resp_sz;
154 u32 max_resp_sz_cached;
155 u32 max_ops;
156 u32 max_reqs;
157};
158
159/* nfs41 sessions slot seqid */
160struct nfs4_slot {
161 u32 seq_nr;
162};
163
149struct nfs4_sequence_args { 164struct nfs4_sequence_args {
150 /* stub */ 165 /* stub */
151}; 166};