diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 171 |
1 files changed, 93 insertions, 78 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3b711f5147a7..980a216a48c8 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -182,7 +182,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
182 | { | 182 | { |
183 | struct nfs4_delegation *dp; | 183 | struct nfs4_delegation *dp; |
184 | struct nfs4_file *fp = stp->st_file; | 184 | struct nfs4_file *fp = stp->st_file; |
185 | struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; | 185 | struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn; |
186 | 186 | ||
187 | dprintk("NFSD alloc_init_deleg\n"); | 187 | dprintk("NFSD alloc_init_deleg\n"); |
188 | if (fp->fi_had_conflict) | 188 | if (fp->fi_had_conflict) |
@@ -203,10 +203,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
203 | get_file(stp->st_vfs_file); | 203 | get_file(stp->st_vfs_file); |
204 | dp->dl_vfs_file = stp->st_vfs_file; | 204 | dp->dl_vfs_file = stp->st_vfs_file; |
205 | dp->dl_type = type; | 205 | dp->dl_type = type; |
206 | dp->dl_recall.cbr_dp = NULL; | 206 | dp->dl_ident = cb->cb_ident; |
207 | dp->dl_recall.cbr_ident = cb->cb_ident; | 207 | dp->dl_stateid.si_boot = get_seconds(); |
208 | dp->dl_recall.cbr_trunc = 0; | ||
209 | dp->dl_stateid.si_boot = boot_time; | ||
210 | dp->dl_stateid.si_stateownerid = current_delegid++; | 208 | dp->dl_stateid.si_stateownerid = current_delegid++; |
211 | dp->dl_stateid.si_fileid = 0; | 209 | dp->dl_stateid.si_fileid = 0; |
212 | dp->dl_stateid.si_generation = 0; | 210 | dp->dl_stateid.si_generation = 0; |
@@ -427,6 +425,11 @@ static int set_forechannel_maxreqs(struct nfsd4_channel_attrs *fchan) | |||
427 | { | 425 | { |
428 | int status = 0, np = fchan->maxreqs * NFSD_PAGES_PER_SLOT; | 426 | int status = 0, np = fchan->maxreqs * NFSD_PAGES_PER_SLOT; |
429 | 427 | ||
428 | if (fchan->maxreqs < 1) | ||
429 | return nfserr_inval; | ||
430 | else if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION) | ||
431 | fchan->maxreqs = NFSD_MAX_SLOTS_PER_SESSION; | ||
432 | |||
430 | spin_lock(&nfsd_serv->sv_lock); | 433 | spin_lock(&nfsd_serv->sv_lock); |
431 | if (np + nfsd_serv->sv_drc_pages_used > nfsd_serv->sv_drc_max_pages) | 434 | if (np + nfsd_serv->sv_drc_pages_used > nfsd_serv->sv_drc_max_pages) |
432 | np = nfsd_serv->sv_drc_max_pages - nfsd_serv->sv_drc_pages_used; | 435 | np = nfsd_serv->sv_drc_max_pages - nfsd_serv->sv_drc_pages_used; |
@@ -446,8 +449,8 @@ static int set_forechannel_maxreqs(struct nfsd4_channel_attrs *fchan) | |||
446 | * fchan holds the client values on input, and the server values on output | 449 | * fchan holds the client values on input, and the server values on output |
447 | */ | 450 | */ |
448 | static int init_forechannel_attrs(struct svc_rqst *rqstp, | 451 | static int init_forechannel_attrs(struct svc_rqst *rqstp, |
449 | struct nfsd4_session *session, | 452 | struct nfsd4_channel_attrs *session_fchan, |
450 | struct nfsd4_channel_attrs *fchan) | 453 | struct nfsd4_channel_attrs *fchan) |
451 | { | 454 | { |
452 | int status = 0; | 455 | int status = 0; |
453 | __u32 maxcount = svc_max_payload(rqstp); | 456 | __u32 maxcount = svc_max_payload(rqstp); |
@@ -457,21 +460,21 @@ static int init_forechannel_attrs(struct svc_rqst *rqstp, | |||
457 | /* Use the client's max request and max response size if possible */ | 460 | /* Use the client's max request and max response size if possible */ |
458 | if (fchan->maxreq_sz > maxcount) | 461 | if (fchan->maxreq_sz > maxcount) |
459 | fchan->maxreq_sz = maxcount; | 462 | fchan->maxreq_sz = maxcount; |
460 | session->se_fmaxreq_sz = fchan->maxreq_sz; | 463 | session_fchan->maxreq_sz = fchan->maxreq_sz; |
461 | 464 | ||
462 | if (fchan->maxresp_sz > maxcount) | 465 | if (fchan->maxresp_sz > maxcount) |
463 | fchan->maxresp_sz = maxcount; | 466 | fchan->maxresp_sz = maxcount; |
464 | session->se_fmaxresp_sz = fchan->maxresp_sz; | 467 | session_fchan->maxresp_sz = fchan->maxresp_sz; |
465 | 468 | ||
466 | /* Set the max response cached size our default which is | 469 | /* Set the max response cached size our default which is |
467 | * a multiple of PAGE_SIZE and small */ | 470 | * a multiple of PAGE_SIZE and small */ |
468 | session->se_fmaxresp_cached = NFSD_PAGES_PER_SLOT * PAGE_SIZE; | 471 | session_fchan->maxresp_cached = NFSD_PAGES_PER_SLOT * PAGE_SIZE; |
469 | fchan->maxresp_cached = session->se_fmaxresp_cached; | 472 | fchan->maxresp_cached = session_fchan->maxresp_cached; |
470 | 473 | ||
471 | /* Use the client's maxops if possible */ | 474 | /* Use the client's maxops if possible */ |
472 | if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND) | 475 | if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND) |
473 | fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND; | 476 | fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND; |
474 | session->se_fmaxops = fchan->maxops; | 477 | session_fchan->maxops = fchan->maxops; |
475 | 478 | ||
476 | /* try to use the client requested number of slots */ | 479 | /* try to use the client requested number of slots */ |
477 | if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION) | 480 | if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION) |
@@ -483,7 +486,7 @@ static int init_forechannel_attrs(struct svc_rqst *rqstp, | |||
483 | */ | 486 | */ |
484 | status = set_forechannel_maxreqs(fchan); | 487 | status = set_forechannel_maxreqs(fchan); |
485 | 488 | ||
486 | session->se_fnumslots = fchan->maxreqs; | 489 | session_fchan->maxreqs = fchan->maxreqs; |
487 | return status; | 490 | return status; |
488 | } | 491 | } |
489 | 492 | ||
@@ -497,12 +500,14 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, | |||
497 | memset(&tmp, 0, sizeof(tmp)); | 500 | memset(&tmp, 0, sizeof(tmp)); |
498 | 501 | ||
499 | /* FIXME: For now, we just accept the client back channel attributes. */ | 502 | /* FIXME: For now, we just accept the client back channel attributes. */ |
500 | status = init_forechannel_attrs(rqstp, &tmp, &cses->fore_channel); | 503 | tmp.se_bchannel = cses->back_channel; |
504 | status = init_forechannel_attrs(rqstp, &tmp.se_fchannel, | ||
505 | &cses->fore_channel); | ||
501 | if (status) | 506 | if (status) |
502 | goto out; | 507 | goto out; |
503 | 508 | ||
504 | /* allocate struct nfsd4_session and slot table in one piece */ | 509 | /* allocate struct nfsd4_session and slot table in one piece */ |
505 | slotsize = tmp.se_fnumslots * sizeof(struct nfsd4_slot); | 510 | slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot); |
506 | new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL); | 511 | new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL); |
507 | if (!new) | 512 | if (!new) |
508 | goto out; | 513 | goto out; |
@@ -576,7 +581,7 @@ free_session(struct kref *kref) | |||
576 | int i; | 581 | int i; |
577 | 582 | ||
578 | ses = container_of(kref, struct nfsd4_session, se_ref); | 583 | ses = container_of(kref, struct nfsd4_session, se_ref); |
579 | for (i = 0; i < ses->se_fnumslots; i++) { | 584 | for (i = 0; i < ses->se_fchannel.maxreqs; i++) { |
580 | struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry; | 585 | struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry; |
581 | nfsd4_release_respages(e->ce_respages, e->ce_resused); | 586 | nfsd4_release_respages(e->ce_respages, e->ce_resused); |
582 | } | 587 | } |
@@ -632,16 +637,20 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) | |||
632 | static void | 637 | static void |
633 | shutdown_callback_client(struct nfs4_client *clp) | 638 | shutdown_callback_client(struct nfs4_client *clp) |
634 | { | 639 | { |
635 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | 640 | struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client; |
636 | 641 | ||
637 | if (clnt) { | 642 | if (clnt) { |
638 | /* | 643 | /* |
639 | * Callback threads take a reference on the client, so there | 644 | * Callback threads take a reference on the client, so there |
640 | * should be no outstanding callbacks at this point. | 645 | * should be no outstanding callbacks at this point. |
641 | */ | 646 | */ |
642 | clp->cl_callback.cb_client = NULL; | 647 | clp->cl_cb_conn.cb_client = NULL; |
643 | rpc_shutdown_client(clnt); | 648 | rpc_shutdown_client(clnt); |
644 | } | 649 | } |
650 | if (clp->cl_cb_conn.cb_cred) { | ||
651 | put_rpccred(clp->cl_cb_conn.cb_cred); | ||
652 | clp->cl_cb_conn.cb_cred = NULL; | ||
653 | } | ||
645 | } | 654 | } |
646 | 655 | ||
647 | static inline void | 656 | static inline void |
@@ -714,7 +723,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir) | |||
714 | return NULL; | 723 | return NULL; |
715 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | 724 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
716 | atomic_set(&clp->cl_count, 1); | 725 | atomic_set(&clp->cl_count, 1); |
717 | atomic_set(&clp->cl_callback.cb_set, 0); | 726 | atomic_set(&clp->cl_cb_conn.cb_set, 0); |
718 | INIT_LIST_HEAD(&clp->cl_idhash); | 727 | INIT_LIST_HEAD(&clp->cl_idhash); |
719 | INIT_LIST_HEAD(&clp->cl_strhash); | 728 | INIT_LIST_HEAD(&clp->cl_strhash); |
720 | INIT_LIST_HEAD(&clp->cl_openowners); | 729 | INIT_LIST_HEAD(&clp->cl_openowners); |
@@ -966,7 +975,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne | |||
966 | static void | 975 | static void |
967 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) | 976 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) |
968 | { | 977 | { |
969 | struct nfs4_callback *cb = &clp->cl_callback; | 978 | struct nfs4_cb_conn *cb = &clp->cl_cb_conn; |
970 | 979 | ||
971 | /* Currently, we only support tcp for the callback channel */ | 980 | /* Currently, we only support tcp for the callback channel */ |
972 | if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3)) | 981 | if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3)) |
@@ -975,6 +984,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) | |||
975 | if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val, | 984 | if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val, |
976 | &cb->cb_addr, &cb->cb_port))) | 985 | &cb->cb_addr, &cb->cb_port))) |
977 | goto out_err; | 986 | goto out_err; |
987 | cb->cb_minorversion = 0; | ||
978 | cb->cb_prog = se->se_callback_prog; | 988 | cb->cb_prog = se->se_callback_prog; |
979 | cb->cb_ident = se->se_callback_ident; | 989 | cb->cb_ident = se->se_callback_ident; |
980 | return; | 990 | return; |
@@ -1128,7 +1138,7 @@ nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | |||
1128 | * is sent (lease renewal). | 1138 | * is sent (lease renewal). |
1129 | */ | 1139 | */ |
1130 | if (seq && nfsd4_not_cached(resp)) { | 1140 | if (seq && nfsd4_not_cached(resp)) { |
1131 | seq->maxslots = resp->cstate.session->se_fnumslots; | 1141 | seq->maxslots = resp->cstate.session->se_fchannel.maxreqs; |
1132 | return nfs_ok; | 1142 | return nfs_ok; |
1133 | } | 1143 | } |
1134 | 1144 | ||
@@ -1238,12 +1248,6 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
1238 | expire_client(conf); | 1248 | expire_client(conf); |
1239 | goto out_new; | 1249 | goto out_new; |
1240 | } | 1250 | } |
1241 | if (ip_addr != conf->cl_addr && | ||
1242 | !(exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A)) { | ||
1243 | /* Client collision. 18.35.4 case 3 */ | ||
1244 | status = nfserr_clid_inuse; | ||
1245 | goto out; | ||
1246 | } | ||
1247 | /* | 1251 | /* |
1248 | * Set bit when the owner id and verifier map to an already | 1252 | * Set bit when the owner id and verifier map to an already |
1249 | * confirmed client id (18.35.3). | 1253 | * confirmed client id (18.35.3). |
@@ -1257,12 +1261,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
1257 | copy_verf(conf, &verf); | 1261 | copy_verf(conf, &verf); |
1258 | new = conf; | 1262 | new = conf; |
1259 | goto out_copy; | 1263 | goto out_copy; |
1260 | } else { | 1264 | } |
1261 | /* 18.35.4 case 7 */ | 1265 | |
1262 | if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { | 1266 | /* 18.35.4 case 7 */ |
1263 | status = nfserr_noent; | 1267 | if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { |
1264 | goto out; | 1268 | status = nfserr_noent; |
1265 | } | 1269 | goto out; |
1266 | } | 1270 | } |
1267 | 1271 | ||
1268 | unconf = find_unconfirmed_client_by_str(dname, strhashval, true); | 1272 | unconf = find_unconfirmed_client_by_str(dname, strhashval, true); |
@@ -1471,7 +1475,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
1471 | goto out; | 1475 | goto out; |
1472 | 1476 | ||
1473 | status = nfserr_badslot; | 1477 | status = nfserr_badslot; |
1474 | if (seq->slotid >= session->se_fnumslots) | 1478 | if (seq->slotid >= session->se_fchannel.maxreqs) |
1475 | goto out; | 1479 | goto out; |
1476 | 1480 | ||
1477 | slot = &session->se_slots[seq->slotid]; | 1481 | slot = &session->se_slots[seq->slotid]; |
@@ -1686,9 +1690,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
1686 | else { | 1690 | else { |
1687 | /* XXX: We just turn off callbacks until we can handle | 1691 | /* XXX: We just turn off callbacks until we can handle |
1688 | * change request correctly. */ | 1692 | * change request correctly. */ |
1689 | atomic_set(&conf->cl_callback.cb_set, 0); | 1693 | atomic_set(&conf->cl_cb_conn.cb_set, 0); |
1690 | gen_confirm(conf); | ||
1691 | nfsd4_remove_clid_dir(unconf); | ||
1692 | expire_client(unconf); | 1694 | expire_client(unconf); |
1693 | status = nfs_ok; | 1695 | status = nfs_ok; |
1694 | 1696 | ||
@@ -1882,7 +1884,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open * | |||
1882 | stp->st_stateowner = sop; | 1884 | stp->st_stateowner = sop; |
1883 | get_nfs4_file(fp); | 1885 | get_nfs4_file(fp); |
1884 | stp->st_file = fp; | 1886 | stp->st_file = fp; |
1885 | stp->st_stateid.si_boot = boot_time; | 1887 | stp->st_stateid.si_boot = get_seconds(); |
1886 | stp->st_stateid.si_stateownerid = sop->so_id; | 1888 | stp->st_stateid.si_stateownerid = sop->so_id; |
1887 | stp->st_stateid.si_fileid = fp->fi_id; | 1889 | stp->st_stateid.si_fileid = fp->fi_id; |
1888 | stp->st_stateid.si_generation = 0; | 1890 | stp->st_stateid.si_generation = 0; |
@@ -2059,19 +2061,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access) | |||
2059 | } | 2061 | } |
2060 | 2062 | ||
2061 | /* | 2063 | /* |
2062 | * Recall a delegation | ||
2063 | */ | ||
2064 | static int | ||
2065 | do_recall(void *__dp) | ||
2066 | { | ||
2067 | struct nfs4_delegation *dp = __dp; | ||
2068 | |||
2069 | dp->dl_file->fi_had_conflict = true; | ||
2070 | nfsd4_cb_recall(dp); | ||
2071 | return 0; | ||
2072 | } | ||
2073 | |||
2074 | /* | ||
2075 | * Spawn a thread to perform a recall on the delegation represented | 2064 | * Spawn a thread to perform a recall on the delegation represented |
2076 | * by the lease (file_lock) | 2065 | * by the lease (file_lock) |
2077 | * | 2066 | * |
@@ -2082,8 +2071,7 @@ do_recall(void *__dp) | |||
2082 | static | 2071 | static |
2083 | void nfsd_break_deleg_cb(struct file_lock *fl) | 2072 | void nfsd_break_deleg_cb(struct file_lock *fl) |
2084 | { | 2073 | { |
2085 | struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner; | 2074 | struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; |
2086 | struct task_struct *t; | ||
2087 | 2075 | ||
2088 | dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl); | 2076 | dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl); |
2089 | if (!dp) | 2077 | if (!dp) |
@@ -2111,16 +2099,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
2111 | */ | 2099 | */ |
2112 | fl->fl_break_time = 0; | 2100 | fl->fl_break_time = 0; |
2113 | 2101 | ||
2114 | t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); | 2102 | dp->dl_file->fi_had_conflict = true; |
2115 | if (IS_ERR(t)) { | 2103 | nfsd4_cb_recall(dp); |
2116 | struct nfs4_client *clp = dp->dl_client; | ||
2117 | |||
2118 | printk(KERN_INFO "NFSD: Callback thread failed for " | ||
2119 | "for client (clientid %08x/%08x)\n", | ||
2120 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); | ||
2121 | put_nfs4_client(dp->dl_client); | ||
2122 | nfs4_put_delegation(dp); | ||
2123 | } | ||
2124 | } | 2104 | } |
2125 | 2105 | ||
2126 | /* | 2106 | /* |
@@ -2422,7 +2402,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
2422 | { | 2402 | { |
2423 | struct nfs4_delegation *dp; | 2403 | struct nfs4_delegation *dp; |
2424 | struct nfs4_stateowner *sop = stp->st_stateowner; | 2404 | struct nfs4_stateowner *sop = stp->st_stateowner; |
2425 | struct nfs4_callback *cb = &sop->so_client->cl_callback; | 2405 | struct nfs4_cb_conn *cb = &sop->so_client->cl_cb_conn; |
2426 | struct file_lock fl, *flp = &fl; | 2406 | struct file_lock fl, *flp = &fl; |
2427 | int status, flag = 0; | 2407 | int status, flag = 0; |
2428 | 2408 | ||
@@ -2614,7 +2594,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
2614 | renew_client(clp); | 2594 | renew_client(clp); |
2615 | status = nfserr_cb_path_down; | 2595 | status = nfserr_cb_path_down; |
2616 | if (!list_empty(&clp->cl_delegations) | 2596 | if (!list_empty(&clp->cl_delegations) |
2617 | && !atomic_read(&clp->cl_callback.cb_set)) | 2597 | && !atomic_read(&clp->cl_cb_conn.cb_set)) |
2618 | goto out; | 2598 | goto out; |
2619 | status = nfs_ok; | 2599 | status = nfs_ok; |
2620 | out: | 2600 | out: |
@@ -2738,12 +2718,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) | |||
2738 | static int | 2718 | static int |
2739 | STALE_STATEID(stateid_t *stateid) | 2719 | STALE_STATEID(stateid_t *stateid) |
2740 | { | 2720 | { |
2741 | if (stateid->si_boot == boot_time) | 2721 | if (time_after((unsigned long)boot_time, |
2742 | return 0; | 2722 | (unsigned long)stateid->si_boot)) { |
2743 | dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", | 2723 | dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", |
2744 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, | 2724 | stateid->si_boot, stateid->si_stateownerid, |
2745 | stateid->si_generation); | 2725 | stateid->si_fileid, stateid->si_generation); |
2746 | return 1; | 2726 | return 1; |
2727 | } | ||
2728 | return 0; | ||
2729 | } | ||
2730 | |||
2731 | static int | ||
2732 | EXPIRED_STATEID(stateid_t *stateid) | ||
2733 | { | ||
2734 | if (time_before((unsigned long)boot_time, | ||
2735 | ((unsigned long)stateid->si_boot)) && | ||
2736 | time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) { | ||
2737 | dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n", | ||
2738 | stateid->si_boot, stateid->si_stateownerid, | ||
2739 | stateid->si_fileid, stateid->si_generation); | ||
2740 | return 1; | ||
2741 | } | ||
2742 | return 0; | ||
2743 | } | ||
2744 | |||
2745 | static __be32 | ||
2746 | stateid_error_map(stateid_t *stateid) | ||
2747 | { | ||
2748 | if (STALE_STATEID(stateid)) | ||
2749 | return nfserr_stale_stateid; | ||
2750 | if (EXPIRED_STATEID(stateid)) | ||
2751 | return nfserr_expired; | ||
2752 | |||
2753 | dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n", | ||
2754 | stateid->si_boot, stateid->si_stateownerid, | ||
2755 | stateid->si_fileid, stateid->si_generation); | ||
2756 | return nfserr_bad_stateid; | ||
2747 | } | 2757 | } |
2748 | 2758 | ||
2749 | static inline int | 2759 | static inline int |
@@ -2867,8 +2877,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
2867 | status = nfserr_bad_stateid; | 2877 | status = nfserr_bad_stateid; |
2868 | if (is_delegation_stateid(stateid)) { | 2878 | if (is_delegation_stateid(stateid)) { |
2869 | dp = find_delegation_stateid(ino, stateid); | 2879 | dp = find_delegation_stateid(ino, stateid); |
2870 | if (!dp) | 2880 | if (!dp) { |
2881 | status = stateid_error_map(stateid); | ||
2871 | goto out; | 2882 | goto out; |
2883 | } | ||
2872 | status = check_stateid_generation(stateid, &dp->dl_stateid, | 2884 | status = check_stateid_generation(stateid, &dp->dl_stateid, |
2873 | flags); | 2885 | flags); |
2874 | if (status) | 2886 | if (status) |
@@ -2881,8 +2893,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
2881 | *filpp = dp->dl_vfs_file; | 2893 | *filpp = dp->dl_vfs_file; |
2882 | } else { /* open or lock stateid */ | 2894 | } else { /* open or lock stateid */ |
2883 | stp = find_stateid(stateid, flags); | 2895 | stp = find_stateid(stateid, flags); |
2884 | if (!stp) | 2896 | if (!stp) { |
2897 | status = stateid_error_map(stateid); | ||
2885 | goto out; | 2898 | goto out; |
2899 | } | ||
2886 | if (nfs4_check_fh(current_fh, stp)) | 2900 | if (nfs4_check_fh(current_fh, stp)) |
2887 | goto out; | 2901 | goto out; |
2888 | if (!stp->st_stateowner->so_confirmed) | 2902 | if (!stp->st_stateowner->so_confirmed) |
@@ -2956,7 +2970,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, | |||
2956 | */ | 2970 | */ |
2957 | sop = search_close_lru(stateid->si_stateownerid, flags); | 2971 | sop = search_close_lru(stateid->si_stateownerid, flags); |
2958 | if (sop == NULL) | 2972 | if (sop == NULL) |
2959 | return nfserr_bad_stateid; | 2973 | return stateid_error_map(stateid); |
2960 | *sopp = sop; | 2974 | *sopp = sop; |
2961 | goto check_replay; | 2975 | goto check_replay; |
2962 | } | 2976 | } |
@@ -3227,8 +3241,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3227 | if (!is_delegation_stateid(stateid)) | 3241 | if (!is_delegation_stateid(stateid)) |
3228 | goto out; | 3242 | goto out; |
3229 | dp = find_delegation_stateid(inode, stateid); | 3243 | dp = find_delegation_stateid(inode, stateid); |
3230 | if (!dp) | 3244 | if (!dp) { |
3245 | status = stateid_error_map(stateid); | ||
3231 | goto out; | 3246 | goto out; |
3247 | } | ||
3232 | status = check_stateid_generation(stateid, &dp->dl_stateid, flags); | 3248 | status = check_stateid_generation(stateid, &dp->dl_stateid, flags); |
3233 | if (status) | 3249 | if (status) |
3234 | goto out; | 3250 | goto out; |
@@ -3455,7 +3471,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc | |||
3455 | stp->st_stateowner = sop; | 3471 | stp->st_stateowner = sop; |
3456 | get_nfs4_file(fp); | 3472 | get_nfs4_file(fp); |
3457 | stp->st_file = fp; | 3473 | stp->st_file = fp; |
3458 | stp->st_stateid.si_boot = boot_time; | 3474 | stp->st_stateid.si_boot = get_seconds(); |
3459 | stp->st_stateid.si_stateownerid = sop->so_id; | 3475 | stp->st_stateid.si_stateownerid = sop->so_id; |
3460 | stp->st_stateid.si_fileid = fp->fi_id; | 3476 | stp->st_stateid.si_fileid = fp->fi_id; |
3461 | stp->st_stateid.si_generation = 0; | 3477 | stp->st_stateid.si_generation = 0; |
@@ -3987,6 +4003,7 @@ nfs4_state_init(void) | |||
3987 | INIT_LIST_HEAD(&conf_str_hashtbl[i]); | 4003 | INIT_LIST_HEAD(&conf_str_hashtbl[i]); |
3988 | INIT_LIST_HEAD(&unconf_str_hashtbl[i]); | 4004 | INIT_LIST_HEAD(&unconf_str_hashtbl[i]); |
3989 | INIT_LIST_HEAD(&unconf_id_hashtbl[i]); | 4005 | INIT_LIST_HEAD(&unconf_id_hashtbl[i]); |
4006 | INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); | ||
3990 | } | 4007 | } |
3991 | for (i = 0; i < SESSION_HASH_SIZE; i++) | 4008 | for (i = 0; i < SESSION_HASH_SIZE; i++) |
3992 | INIT_LIST_HEAD(&sessionid_hashtbl[i]); | 4009 | INIT_LIST_HEAD(&sessionid_hashtbl[i]); |
@@ -4009,8 +4026,6 @@ nfs4_state_init(void) | |||
4009 | INIT_LIST_HEAD(&close_lru); | 4026 | INIT_LIST_HEAD(&close_lru); |
4010 | INIT_LIST_HEAD(&client_lru); | 4027 | INIT_LIST_HEAD(&client_lru); |
4011 | INIT_LIST_HEAD(&del_recall_lru); | 4028 | INIT_LIST_HEAD(&del_recall_lru); |
4012 | for (i = 0; i < CLIENT_HASH_SIZE; i++) | ||
4013 | INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); | ||
4014 | reclaim_str_hashtbl_size = 0; | 4029 | reclaim_str_hashtbl_size = 0; |
4015 | return 0; | 4030 | return 0; |
4016 | } | 4031 | } |