diff options
-rw-r--r-- | fs/nfs/client.c | 60 | ||||
-rw-r--r-- | fs/nfs/internal.h | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 34 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 49 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 15 |
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 | */ | ||
190 | static 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 | */ |
189 | static void nfs_free_client(struct nfs_client *clp) | 203 | static 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 | */ | ||
1074 | static 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 | */ |
1059 | static int nfs4_init_client(struct nfs_client *clp, | 1098 | static 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 | */ | ||
1193 | static 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 | */ |
1149 | static int nfs4_init_server(struct nfs_server *server, | 1207 | static 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 | */ | ||
212 | static 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 | */ |
212 | static inline char *nfs_devname(const struct vfsmount *mnt_parent, | 224 | static 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 | ||
203 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; | 203 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; |
204 | extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops; | 204 | extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops; |
205 | #if defined(CONFIG_NFS_V4_1) | ||
206 | extern void nfs4_destroy_session(struct nfs4_session *session); | ||
207 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | ||
208 | #endif /* CONFIG_NFS_V4_1 */ | ||
205 | 209 | ||
206 | extern const u32 nfs4_fattr_bitmap[2]; | 210 | extern const u32 nfs4_fattr_bitmap[2]; |
207 | extern const u32 nfs4_statfs_bitmap[2]; | 211 | extern 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 */ | ||
3728 | static 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 | |||
3737 | struct 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 | |||
3752 | void 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 | |||
3726 | struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { | 3760 | struct 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 | ||
12 | struct nfs4_session; | ||
10 | struct nfs_iostats; | 13 | struct nfs_iostats; |
11 | struct nlm_host; | 14 | struct 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))) | ||
164 | struct 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 | |||
174 | static 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 | */ | ||
182 | struct 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 | ||
147 | struct nfs_seqid; | 147 | struct nfs_seqid; |
148 | 148 | ||
149 | /* nfs41 sessions channel attributes */ | ||
150 | struct 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 */ | ||
160 | struct nfs4_slot { | ||
161 | u32 seq_nr; | ||
162 | }; | ||
163 | |||
149 | struct nfs4_sequence_args { | 164 | struct nfs4_sequence_args { |
150 | /* stub */ | 165 | /* stub */ |
151 | }; | 166 | }; |