aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2011-07-13 10:50:48 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-07-15 18:58:48 -0400
commit17456804546b78a1c13d2b934c8f50bbde141a38 (patch)
treed9585ae98e98101830068c9ab29556795a162942 /fs/nfsd
parente1ca12dfb1be7fe8b82ca723a9b511f7d808bf81 (diff)
NFSD: Added TEST_STATEID operation
This operation is used by the client to check the validity of a list of stateids. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c5
-rw-r--r--fs/nfsd/nfs4state.c38
-rw-r--r--fs/nfsd/nfs4xdr.c87
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/xdr4.h17
5 files changed, 145 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index a27dea50273d..96b69299dcbe 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1417,6 +1417,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
1417 .op_flags = OP_HANDLES_WRONGSEC, 1417 .op_flags = OP_HANDLES_WRONGSEC,
1418 .op_name = "OP_SECINFO_NO_NAME", 1418 .op_name = "OP_SECINFO_NO_NAME",
1419 }, 1419 },
1420 [OP_TEST_STATEID] = {
1421 .op_func = (nfsd4op_func)nfsd4_test_stateid,
1422 .op_flags = ALLOWED_WITHOUT_FH,
1423 .op_name = "OP_TEST_STATEID",
1424 },
1420 [OP_FREE_STATEID] = { 1425 [OP_FREE_STATEID] = {
1421 .op_func = (nfsd4op_func)nfsd4_free_stateid, 1426 .op_func = (nfsd4op_func)nfsd4_free_stateid,
1422 .op_flags = ALLOWED_WITHOUT_FH, 1427 .op_flags = ALLOWED_WITHOUT_FH,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 55c36e267b7d..12244cee1680 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -37,6 +37,7 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/namei.h> 38#include <linux/namei.h>
39#include <linux/swap.h> 39#include <linux/swap.h>
40#include <linux/pagemap.h>
40#include <linux/sunrpc/svcauth_gss.h> 41#include <linux/sunrpc/svcauth_gss.h>
41#include <linux/sunrpc/clnt.h> 42#include <linux/sunrpc/clnt.h>
42#include "xdr4.h" 43#include "xdr4.h"
@@ -3145,6 +3146,32 @@ static int is_open_stateid(struct nfs4_stateid *stateid)
3145 return stateid->st_openstp == NULL; 3146 return stateid->st_openstp == NULL;
3146} 3147}
3147 3148
3149__be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
3150{
3151 struct nfs4_stateid *stp = NULL;
3152 __be32 status = nfserr_stale_stateid;
3153
3154 if (STALE_STATEID(stateid))
3155 goto out;
3156
3157 status = nfserr_expired;
3158 stp = search_for_stateid(stateid);
3159 if (!stp)
3160 goto out;
3161 status = nfserr_bad_stateid;
3162
3163 if (!stp->st_stateowner->so_confirmed)
3164 goto out;
3165
3166 status = check_stateid_generation(stateid, &stp->st_stateid, flags);
3167 if (status)
3168 goto out;
3169
3170 status = nfs_ok;
3171out:
3172 return status;
3173}
3174
3148/* 3175/*
3149* Checks for stateid operations 3176* Checks for stateid operations
3150*/ 3177*/
@@ -3243,6 +3270,17 @@ nfsd4_free_lock_stateid(struct nfs4_stateid *stp)
3243} 3270}
3244 3271
3245/* 3272/*
3273 * Test if the stateid is valid
3274 */
3275__be32
3276nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3277 struct nfsd4_test_stateid *test_stateid)
3278{
3279 test_stateid->ts_has_session = nfsd4_has_session(cstate);
3280 return nfs_ok;
3281}
3282
3283/*
3246 * Free a state id 3284 * Free a state id
3247 */ 3285 */
3248__be32 3286__be32
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ef9bd6f24fc0..a8d83bd5c1d5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -44,13 +44,14 @@
44#include <linux/namei.h> 44#include <linux/namei.h>
45#include <linux/statfs.h> 45#include <linux/statfs.h>
46#include <linux/utsname.h> 46#include <linux/utsname.h>
47#include <linux/pagemap.h>
47#include <linux/sunrpc/svcauth_gss.h> 48#include <linux/sunrpc/svcauth_gss.h>
48 49
49#include "idmap.h" 50#include "idmap.h"
50#include "acl.h" 51#include "acl.h"
51#include "xdr4.h" 52#include "xdr4.h"
52#include "vfs.h" 53#include "vfs.h"
53 54#include "state.h"
54 55
55#define NFSDDBG_FACILITY NFSDDBG_XDR 56#define NFSDDBG_FACILITY NFSDDBG_XDR
56 57
@@ -131,6 +132,22 @@ xdr_error: \
131 } \ 132 } \
132} while (0) 133} while (0)
133 134
135static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
136{
137 savep->p = argp->p;
138 savep->end = argp->end;
139 savep->pagelen = argp->pagelen;
140 savep->pagelist = argp->pagelist;
141}
142
143static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
144{
145 argp->p = savep->p;
146 argp->end = savep->end;
147 argp->pagelen = savep->pagelen;
148 argp->pagelist = savep->pagelist;
149}
150
134static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 151static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
135{ 152{
136 /* We want more bytes than seem to be available. 153 /* We want more bytes than seem to be available.
@@ -1274,6 +1291,40 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1274 DECODE_TAIL; 1291 DECODE_TAIL;
1275} 1292}
1276 1293
1294static __be32
1295nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1296{
1297 unsigned int nbytes;
1298 stateid_t si;
1299 int i;
1300 __be32 *p;
1301 __be32 status;
1302
1303 READ_BUF(4);
1304 test_stateid->ts_num_ids = ntohl(*p++);
1305
1306 nbytes = test_stateid->ts_num_ids * sizeof(stateid_t);
1307 if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
1308 goto xdr_error;
1309
1310 test_stateid->ts_saved_args = argp;
1311 save_buf(argp, &test_stateid->ts_savedp);
1312
1313 for (i = 0; i < test_stateid->ts_num_ids; i++) {
1314 status = nfsd4_decode_stateid(argp, &si);
1315 if (status)
1316 return status;
1317 }
1318
1319 status = 0;
1320out:
1321 return status;
1322xdr_error:
1323 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
1324 status = nfserr_bad_xdr;
1325 goto out;
1326}
1327
1277static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc) 1328static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1278{ 1329{
1279 DECODE_HEAD; 1330 DECODE_HEAD;
@@ -1393,7 +1444,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1393 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name, 1444 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
1394 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, 1445 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1395 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, 1446 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1396 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, 1447 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid,
1397 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp, 1448 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1398 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp, 1449 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
1399 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, 1450 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,
@@ -3166,6 +3217,36 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3166 return 0; 3217 return 0;
3167} 3218}
3168 3219
3220__be32
3221nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
3222 struct nfsd4_test_stateid *test_stateid)
3223{
3224 struct nfsd4_compoundargs *argp;
3225 stateid_t si;
3226 __be32 *p;
3227 int i;
3228 int valid;
3229
3230 restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
3231 argp = test_stateid->ts_saved_args;
3232
3233 RESERVE_SPACE(4);
3234 *p++ = htonl(test_stateid->ts_num_ids);
3235 resp->p = p;
3236
3237 nfs4_lock_state();
3238 for (i = 0; i < test_stateid->ts_num_ids; i++) {
3239 nfsd4_decode_stateid(argp, &si);
3240 valid = nfs4_validate_stateid(&si, test_stateid->ts_has_session);
3241 RESERVE_SPACE(4);
3242 *p++ = htonl(valid);
3243 resp->p = p;
3244 }
3245 nfs4_unlock_state();
3246
3247 return nfserr;
3248}
3249
3169static __be32 3250static __be32
3170nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) 3251nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
3171{ 3252{
@@ -3234,7 +3315,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3234 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name, 3315 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
3235 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, 3316 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
3236 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, 3317 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
3237 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, 3318 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid,
3238 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, 3319 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3239 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop, 3320 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
3240 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop, 3321 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 6bd2f3c21f2b..4eefaf1b42e8 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -482,6 +482,7 @@ extern void nfsd4_recdir_purge_old(void);
482extern int nfsd4_create_clid_dir(struct nfs4_client *clp); 482extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
483extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); 483extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
484extern void release_session_client(struct nfsd4_session *); 484extern void release_session_client(struct nfsd4_session *);
485extern __be32 nfs4_validate_stateid(stateid_t *, int);
485 486
486static inline void 487static inline void
487nfs4_put_stateowner(struct nfs4_stateowner *so) 488nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index ed1784d31a60..02fb0e09de7f 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -342,6 +342,20 @@ struct nfsd4_setclientid_confirm {
342 nfs4_verifier sc_confirm; 342 nfs4_verifier sc_confirm;
343}; 343};
344 344
345struct nfsd4_saved_compoundargs {
346 __be32 *p;
347 __be32 *end;
348 int pagelen;
349 struct page **pagelist;
350};
351
352struct nfsd4_test_stateid {
353 __be32 ts_num_ids;
354 __be32 ts_has_session;
355 struct nfsd4_compoundargs *ts_saved_args;
356 struct nfsd4_saved_compoundargs ts_savedp;
357};
358
345struct nfsd4_free_stateid { 359struct nfsd4_free_stateid {
346 stateid_t fr_stateid; /* request */ 360 stateid_t fr_stateid; /* request */
347 __be32 fr_status; /* response */ 361 __be32 fr_status; /* response */
@@ -437,6 +451,7 @@ struct nfsd4_op {
437 struct nfsd4_destroy_session destroy_session; 451 struct nfsd4_destroy_session destroy_session;
438 struct nfsd4_sequence sequence; 452 struct nfsd4_sequence sequence;
439 struct nfsd4_reclaim_complete reclaim_complete; 453 struct nfsd4_reclaim_complete reclaim_complete;
454 struct nfsd4_test_stateid test_stateid;
440 struct nfsd4_free_stateid free_stateid; 455 struct nfsd4_free_stateid free_stateid;
441 } u; 456 } u;
442 struct nfs4_replay * replay; 457 struct nfs4_replay * replay;
@@ -570,6 +585,8 @@ extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
570 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr); 585 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
571extern __be32 nfsd4_renew(struct svc_rqst *rqstp, 586extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
572 struct nfsd4_compound_state *, clientid_t *clid); 587 struct nfsd4_compound_state *, clientid_t *clid);
588extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
589 struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
573extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp, 590extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
574 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid); 591 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
575#endif 592#endif