aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c61
-rw-r--r--fs/nfs/nfs4xdr.c139
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_fs_sb.h6
-rw-r--r--include/linux/nfs_xdr.h40
-rw-r--r--include/linux/nfsd/state.h1
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 */
4142static 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 */
4132static void nfs4_destroy_slot_table(struct nfs4_session *session) 4193static 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
598static const umode_t nfs_type2fmt[] = { 627static 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 */
1489static 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
1459static void encode_sequence(struct xdr_stream *xdr, 1510static 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 */
2220static 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)
3952static 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
3880static int decode_sequence(struct xdr_stream *xdr, 3997static 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 */
4898static 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
4948struct rpc_version nfs_version4 = { 5087struct 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
882struct nfstime4 {
883 u64 seconds;
884 u32 nseconds;
885};
886
887#ifdef CONFIG_NFS_V4_1
888struct 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)
897struct 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
905struct server_owner {
906 uint64_t minor_id;
907 uint32_t major_id_sz;
908 char major_id[NFS4_OPAQUE_LIMIT];
909};
910
911struct server_scope {
912 uint32_t server_scope_sz;
913 char server_scope[NFS4_OPAQUE_LIMIT];
914};
915
916struct nfs41_exchange_id_res {
917 struct nfs_client *client;
918 u32 flags;
919};
920#endif /* CONFIG_NFS_V4_1 */
921
882struct nfs_page; 922struct 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
45typedef struct { 44typedef struct {
46 u32 cl_boot; 45 u32 cl_boot;
47 u32 cl_id; 46 u32 cl_id;