aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2009-04-01 09:22:29 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 15:23:57 -0400
commit99fe60d062cfecf382c036065b3278b82b6c5eff (patch)
treeb4451fc4bb42c0915c4f736cc5fdae9e818b55d4 /fs/nfs
parent938e10109115a71cc69d475122f21cf75e5046cd (diff)
nfs41: exchange_id operation
Implement the exchange_id operation conforming to http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26 Unlike NFSv4.0, NFSv4.1 requires machine credentials. RPC_AUTH_GSS machine credentials will be passed into the kernel at mount time to be available for the exchange_id operation. RPC_AUTH_UNIX root mounts can use the UNIX root credential. Store the root credential in the nfs_client struct. Without a credential, NFSv4.1 state renewal fails. [nfs41: establish clientid via exchange id only if cred != NULL] Signed-off-by: Andy Adamson<andros@umich.edu> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfsd41: move nfstime4 from under CONFIG_NFS_V4_1] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: do not wait a lease time in exchange id] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: pass *session in seq_args and seq_res] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> [nfs41: Ignoring impid in decode_exchange_id is missing a READ_BUF] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: fix Xcode_exchange_id's xdr Xcoding pointer type] [nfs41: get rid of unused struct nfs41_exchange_id_res members] Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c61
-rw-r--r--fs/nfs/nfs4xdr.c139
2 files changed, 200 insertions, 0 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 = {