diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 61 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 139 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 6 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 40 | ||||
-rw-r--r-- | include/linux/nfsd/state.h | 1 |
6 files changed, 247 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index dc0feb5837b1..6f384e290753 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/smp_lock.h> | 48 | #include <linux/smp_lock.h> |
49 | #include <linux/namei.h> | 49 | #include <linux/namei.h> |
50 | #include <linux/mount.h> | 50 | #include <linux/mount.h> |
51 | #include <linux/module.h> | ||
51 | 52 | ||
52 | #include "nfs4_fs.h" | 53 | #include "nfs4_fs.h" |
53 | #include "delegation.h" | 54 | #include "delegation.h" |
@@ -433,11 +434,13 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
433 | spin_unlock(&tbl->slot_tbl_lock); | 434 | spin_unlock(&tbl->slot_tbl_lock); |
434 | 435 | ||
435 | slot = tbl->slots + slotid; | 436 | slot = tbl->slots + slotid; |
437 | args->sa_session = session; | ||
436 | args->sa_slotid = slotid; | 438 | args->sa_slotid = slotid; |
437 | args->sa_cache_this = cache_reply; | 439 | args->sa_cache_this = cache_reply; |
438 | 440 | ||
439 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); | 441 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); |
440 | 442 | ||
443 | res->sr_session = session; | ||
441 | res->sr_slotid = slotid; | 444 | res->sr_slotid = slotid; |
442 | res->sr_renewal_time = jiffies; | 445 | res->sr_renewal_time = jiffies; |
443 | /* | 446 | /* |
@@ -4128,6 +4131,64 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4128 | } | 4131 | } |
4129 | 4132 | ||
4130 | #ifdef CONFIG_NFS_V4_1 | 4133 | #ifdef CONFIG_NFS_V4_1 |
4134 | /* | ||
4135 | * nfs4_proc_exchange_id() | ||
4136 | * | ||
4137 | * Since the clientid has expired, all compounds using sessions | ||
4138 | * associated with the stale clientid will be returning | ||
4139 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
4140 | * be in some phase of session reset. | ||
4141 | */ | ||
4142 | static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | ||
4143 | { | ||
4144 | nfs4_verifier verifier; | ||
4145 | struct nfs41_exchange_id_args args = { | ||
4146 | .client = clp, | ||
4147 | .flags = clp->cl_exchange_flags, | ||
4148 | }; | ||
4149 | struct nfs41_exchange_id_res res = { | ||
4150 | .client = clp, | ||
4151 | }; | ||
4152 | int status; | ||
4153 | struct rpc_message msg = { | ||
4154 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID], | ||
4155 | .rpc_argp = &args, | ||
4156 | .rpc_resp = &res, | ||
4157 | .rpc_cred = cred, | ||
4158 | }; | ||
4159 | __be32 *p; | ||
4160 | |||
4161 | dprintk("--> %s\n", __func__); | ||
4162 | BUG_ON(clp == NULL); | ||
4163 | p = (u32 *)verifier.data; | ||
4164 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); | ||
4165 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | ||
4166 | args.verifier = &verifier; | ||
4167 | |||
4168 | while (1) { | ||
4169 | args.id_len = scnprintf(args.id, sizeof(args.id), | ||
4170 | "%s/%s %u", | ||
4171 | clp->cl_ipaddr, | ||
4172 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
4173 | RPC_DISPLAY_ADDR), | ||
4174 | clp->cl_id_uniquifier); | ||
4175 | |||
4176 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | ||
4177 | |||
4178 | if (status != NFS4ERR_CLID_INUSE) | ||
4179 | break; | ||
4180 | |||
4181 | if (signalled()) | ||
4182 | break; | ||
4183 | |||
4184 | if (++clp->cl_id_uniquifier == 0) | ||
4185 | break; | ||
4186 | } | ||
4187 | |||
4188 | dprintk("<-- %s status= %d\n", __func__, status); | ||
4189 | return status; | ||
4190 | } | ||
4191 | |||
4131 | /* Destroy the slot table */ | 4192 | /* Destroy the slot table */ |
4132 | static void nfs4_destroy_slot_table(struct nfs4_session *session) | 4193 | static void nfs4_destroy_slot_table(struct nfs4_session *session) |
4133 | { | 4194 | { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5b944cd57218..783c4214dccd 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -246,6 +246,27 @@ static int nfs4_stat_to_errno(int); | |||
246 | (0) | 246 | (0) |
247 | 247 | ||
248 | #if defined(CONFIG_NFS_V4_1) | 248 | #if defined(CONFIG_NFS_V4_1) |
249 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ | ||
250 | encode_verifier_maxsz + \ | ||
251 | 1 /* co_ownerid.len */ + \ | ||
252 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ | ||
253 | 1 /* flags */ + \ | ||
254 | 1 /* spa_how */ + \ | ||
255 | 0 /* SP4_NONE (for now) */ + \ | ||
256 | 1 /* zero implemetation id array */) | ||
257 | #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ | ||
258 | 2 /* eir_clientid */ + \ | ||
259 | 1 /* eir_sequenceid */ + \ | ||
260 | 1 /* eir_flags */ + \ | ||
261 | 1 /* spr_how */ + \ | ||
262 | 0 /* SP4_NONE (for now) */ + \ | ||
263 | 2 /* eir_server_owner.so_minor_id */ + \ | ||
264 | /* eir_server_owner.so_major_id<> */ \ | ||
265 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | ||
266 | /* eir_server_scope<> */ \ | ||
267 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | ||
268 | 1 /* eir_server_impl_id array length */ + \ | ||
269 | 0 /* ignored eir_server_impl_id contents */) | ||
249 | #define encode_sequence_maxsz 0 /* stub */ | 270 | #define encode_sequence_maxsz 0 /* stub */ |
250 | #define decode_sequence_maxsz 0 /* stub */ | 271 | #define decode_sequence_maxsz 0 /* stub */ |
251 | #else /* CONFIG_NFS_V4_1 */ | 272 | #else /* CONFIG_NFS_V4_1 */ |
@@ -594,6 +615,14 @@ static int nfs4_stat_to_errno(int); | |||
594 | decode_putfh_maxsz + \ | 615 | decode_putfh_maxsz + \ |
595 | decode_lookup_maxsz + \ | 616 | decode_lookup_maxsz + \ |
596 | decode_fs_locations_maxsz) | 617 | decode_fs_locations_maxsz) |
618 | #if defined(CONFIG_NFS_V4_1) | ||
619 | #define NFS4_enc_exchange_id_sz \ | ||
620 | (compound_encode_hdr_maxsz + \ | ||
621 | encode_exchange_id_maxsz) | ||
622 | #define NFS4_dec_exchange_id_sz \ | ||
623 | (compound_decode_hdr_maxsz + \ | ||
624 | decode_exchange_id_maxsz) | ||
625 | #endif /* CONFIG_NFS_V4_1 */ | ||
597 | 626 | ||
598 | static const umode_t nfs_type2fmt[] = { | 627 | static const umode_t nfs_type2fmt[] = { |
599 | [NF4BAD] = 0, | 628 | [NF4BAD] = 0, |
@@ -1455,7 +1484,29 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state | |||
1455 | hdr->replen += decode_delegreturn_maxsz; | 1484 | hdr->replen += decode_delegreturn_maxsz; |
1456 | } | 1485 | } |
1457 | 1486 | ||
1487 | #if defined(CONFIG_NFS_V4_1) | ||
1458 | /* NFSv4.1 operations */ | 1488 | /* NFSv4.1 operations */ |
1489 | static void encode_exchange_id(struct xdr_stream *xdr, | ||
1490 | struct nfs41_exchange_id_args *args, | ||
1491 | struct compound_hdr *hdr) | ||
1492 | { | ||
1493 | __be32 *p; | ||
1494 | |||
1495 | RESERVE_SPACE(4 + sizeof(args->verifier->data)); | ||
1496 | WRITE32(OP_EXCHANGE_ID); | ||
1497 | WRITEMEM(args->verifier->data, sizeof(args->verifier->data)); | ||
1498 | |||
1499 | encode_string(xdr, args->id_len, args->id); | ||
1500 | |||
1501 | RESERVE_SPACE(12); | ||
1502 | WRITE32(args->flags); | ||
1503 | WRITE32(0); /* zero length state_protect4_a */ | ||
1504 | WRITE32(0); /* zero length implementation id array */ | ||
1505 | hdr->nops++; | ||
1506 | hdr->replen += decode_exchange_id_maxsz; | ||
1507 | } | ||
1508 | #endif /* CONFIG_NFS_V4_1 */ | ||
1509 | |||
1459 | static void encode_sequence(struct xdr_stream *xdr, | 1510 | static void encode_sequence(struct xdr_stream *xdr, |
1460 | const struct nfs4_sequence_args *args, | 1511 | const struct nfs4_sequence_args *args, |
1461 | struct compound_hdr *hdr) | 1512 | struct compound_hdr *hdr) |
@@ -2162,6 +2213,26 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs | |||
2162 | return 0; | 2213 | return 0; |
2163 | } | 2214 | } |
2164 | 2215 | ||
2216 | #if defined(CONFIG_NFS_V4_1) | ||
2217 | /* | ||
2218 | * EXCHANGE_ID request | ||
2219 | */ | ||
2220 | static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p, | ||
2221 | struct nfs41_exchange_id_args *args) | ||
2222 | { | ||
2223 | struct xdr_stream xdr; | ||
2224 | struct compound_hdr hdr = { | ||
2225 | .minorversion = args->client->cl_minorversion, | ||
2226 | }; | ||
2227 | |||
2228 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
2229 | encode_compound_hdr(&xdr, req, &hdr); | ||
2230 | encode_exchange_id(&xdr, args, &hdr); | ||
2231 | encode_nops(&hdr); | ||
2232 | return 0; | ||
2233 | } | ||
2234 | #endif /* CONFIG_NFS_V4_1 */ | ||
2235 | |||
2165 | /* | 2236 | /* |
2166 | * START OF "GENERIC" DECODE ROUTINES. | 2237 | * START OF "GENERIC" DECODE ROUTINES. |
2167 | * These may look a little ugly since they are imported from a "generic" | 2238 | * These may look a little ugly since they are imported from a "generic" |
@@ -3877,6 +3948,52 @@ static int decode_delegreturn(struct xdr_stream *xdr) | |||
3877 | return decode_op_hdr(xdr, OP_DELEGRETURN); | 3948 | return decode_op_hdr(xdr, OP_DELEGRETURN); |
3878 | } | 3949 | } |
3879 | 3950 | ||
3951 | #if defined(CONFIG_NFS_V4_1) | ||
3952 | static int decode_exchange_id(struct xdr_stream *xdr, | ||
3953 | struct nfs41_exchange_id_res *res) | ||
3954 | { | ||
3955 | __be32 *p; | ||
3956 | uint32_t dummy; | ||
3957 | int status; | ||
3958 | struct nfs_client *clp = res->client; | ||
3959 | |||
3960 | status = decode_op_hdr(xdr, OP_EXCHANGE_ID); | ||
3961 | if (status) | ||
3962 | return status; | ||
3963 | |||
3964 | READ_BUF(8); | ||
3965 | READ64(clp->cl_ex_clid); | ||
3966 | READ_BUF(12); | ||
3967 | READ32(clp->cl_seqid); | ||
3968 | READ32(clp->cl_exchange_flags); | ||
3969 | |||
3970 | /* We ask for SP4_NONE */ | ||
3971 | READ32(dummy); | ||
3972 | if (dummy != SP4_NONE) | ||
3973 | return -EIO; | ||
3974 | |||
3975 | /* Throw away minor_id */ | ||
3976 | READ_BUF(8); | ||
3977 | |||
3978 | /* Throw away Major id */ | ||
3979 | READ_BUF(4); | ||
3980 | READ32(dummy); | ||
3981 | READ_BUF(dummy); | ||
3982 | |||
3983 | /* Throw away server_scope */ | ||
3984 | READ_BUF(4); | ||
3985 | READ32(dummy); | ||
3986 | READ_BUF(dummy); | ||
3987 | |||
3988 | /* Throw away Implementation id array */ | ||
3989 | READ_BUF(4); | ||
3990 | READ32(dummy); | ||
3991 | READ_BUF(dummy); | ||
3992 | |||
3993 | return 0; | ||
3994 | } | ||
3995 | #endif /* CONFIG_NFS_V4_1 */ | ||
3996 | |||
3880 | static int decode_sequence(struct xdr_stream *xdr, | 3997 | static int decode_sequence(struct xdr_stream *xdr, |
3881 | struct nfs4_sequence_res *res, | 3998 | struct nfs4_sequence_res *res, |
3882 | struct rpc_rqst *rqstp) | 3999 | struct rpc_rqst *rqstp) |
@@ -4774,6 +4891,25 @@ out: | |||
4774 | return status; | 4891 | return status; |
4775 | } | 4892 | } |
4776 | 4893 | ||
4894 | #if defined(CONFIG_NFS_V4_1) | ||
4895 | /* | ||
4896 | * EXCHANGE_ID request | ||
4897 | */ | ||
4898 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p, | ||
4899 | void *res) | ||
4900 | { | ||
4901 | struct xdr_stream xdr; | ||
4902 | struct compound_hdr hdr; | ||
4903 | int status; | ||
4904 | |||
4905 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
4906 | status = decode_compound_hdr(&xdr, &hdr); | ||
4907 | if (!status) | ||
4908 | status = decode_exchange_id(&xdr, res); | ||
4909 | return status; | ||
4910 | } | ||
4911 | #endif /* CONFIG_NFS_V4_1 */ | ||
4912 | |||
4777 | __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) | 4913 | __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) |
4778 | { | 4914 | { |
4779 | uint32_t bitmap[2] = {0}; | 4915 | uint32_t bitmap[2] = {0}; |
@@ -4943,6 +5079,9 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
4943 | PROC(GETACL, enc_getacl, dec_getacl), | 5079 | PROC(GETACL, enc_getacl, dec_getacl), |
4944 | PROC(SETACL, enc_setacl, dec_setacl), | 5080 | PROC(SETACL, enc_setacl, dec_setacl), |
4945 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | 5081 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), |
5082 | #if defined(CONFIG_NFS_V4_1) | ||
5083 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), | ||
5084 | #endif /* CONFIG_NFS_V4_1 */ | ||
4946 | }; | 5085 | }; |
4947 | 5086 | ||
4948 | struct rpc_version nfs_version4 = { | 5087 | struct rpc_version nfs_version4 = { |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7c36fcf2dfb7..ad65709ed8d3 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define NFS4_FHSIZE 128 | 21 | #define NFS4_FHSIZE 128 |
22 | #define NFS4_MAXPATHLEN PATH_MAX | 22 | #define NFS4_MAXPATHLEN PATH_MAX |
23 | #define NFS4_MAXNAMLEN NAME_MAX | 23 | #define NFS4_MAXNAMLEN NAME_MAX |
24 | #define NFS4_OPAQUE_LIMIT 1024 | ||
24 | #define NFS4_MAX_SESSIONID_LEN 16 | 25 | #define NFS4_MAX_SESSIONID_LEN 16 |
25 | 26 | ||
26 | #define NFS4_ACCESS_READ 0x0001 | 27 | #define NFS4_ACCESS_READ 0x0001 |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 206485e5082f..435ed556efb5 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -78,6 +78,12 @@ struct nfs_client { | |||
78 | #endif /* CONFIG_NFS_V4 */ | 78 | #endif /* CONFIG_NFS_V4 */ |
79 | 79 | ||
80 | #ifdef CONFIG_NFS_V4_1 | 80 | #ifdef CONFIG_NFS_V4_1 |
81 | /* clientid returned from EXCHANGE_ID, used by session operations */ | ||
82 | u64 cl_ex_clid; | ||
83 | /* The sequence id to use for the next CREATE_SESSION */ | ||
84 | u32 cl_seqid; | ||
85 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ | ||
86 | u32 cl_exchange_flags; | ||
81 | struct nfs4_session *cl_session; /* sharred session */ | 87 | struct nfs4_session *cl_session; /* sharred session */ |
82 | #endif /* CONFIG_NFS_V4_1 */ | 88 | #endif /* CONFIG_NFS_V4_1 */ |
83 | 89 | ||
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 4ac14b40efc9..5d70b924af5e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -879,6 +879,46 @@ struct nfs4_fs_locations_res { | |||
879 | 879 | ||
880 | #endif /* CONFIG_NFS_V4 */ | 880 | #endif /* CONFIG_NFS_V4 */ |
881 | 881 | ||
882 | struct nfstime4 { | ||
883 | u64 seconds; | ||
884 | u32 nseconds; | ||
885 | }; | ||
886 | |||
887 | #ifdef CONFIG_NFS_V4_1 | ||
888 | struct nfs_impl_id4 { | ||
889 | u32 domain_len; | ||
890 | char *domain; | ||
891 | u32 name_len; | ||
892 | char *name; | ||
893 | struct nfstime4 date; | ||
894 | }; | ||
895 | |||
896 | #define NFS4_EXCHANGE_ID_LEN (48) | ||
897 | struct nfs41_exchange_id_args { | ||
898 | struct nfs_client *client; | ||
899 | nfs4_verifier *verifier; | ||
900 | unsigned int id_len; | ||
901 | char id[NFS4_EXCHANGE_ID_LEN]; | ||
902 | u32 flags; | ||
903 | }; | ||
904 | |||
905 | struct server_owner { | ||
906 | uint64_t minor_id; | ||
907 | uint32_t major_id_sz; | ||
908 | char major_id[NFS4_OPAQUE_LIMIT]; | ||
909 | }; | ||
910 | |||
911 | struct server_scope { | ||
912 | uint32_t server_scope_sz; | ||
913 | char server_scope[NFS4_OPAQUE_LIMIT]; | ||
914 | }; | ||
915 | |||
916 | struct nfs41_exchange_id_res { | ||
917 | struct nfs_client *client; | ||
918 | u32 flags; | ||
919 | }; | ||
920 | #endif /* CONFIG_NFS_V4_1 */ | ||
921 | |||
882 | struct nfs_page; | 922 | struct nfs_page; |
883 | 923 | ||
884 | #define NFS_PAGEVEC_SIZE (8U) | 924 | #define NFS_PAGEVEC_SIZE (8U) |
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index 4d61c873feed..7ef4b7ad1214 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/kref.h> | 41 | #include <linux/kref.h> |
42 | #include <linux/sunrpc/clnt.h> | 42 | #include <linux/sunrpc/clnt.h> |
43 | 43 | ||
44 | #define NFS4_OPAQUE_LIMIT 1024 | ||
45 | typedef struct { | 44 | typedef struct { |
46 | u32 cl_boot; | 45 | u32 cl_boot; |
47 | u32 cl_id; | 46 | u32 cl_id; |