diff --git a/[refs] b/[refs] index 18d53a039d80..8e2995c43d00 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8546ee518c6662ddb3075249fb31d89e5dbfb7d5 +refs/heads/master: 6a8a13e03861c0ab83ab07d573ca793cff0e5d00 diff --git a/trunk/fs/lockd/svc.c b/trunk/fs/lockd/svc.c index 2444780f5cfa..c061b9aa7ddb 100644 --- a/trunk/fs/lockd/svc.c +++ b/trunk/fs/lockd/svc.c @@ -440,7 +440,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \ __typeof__(type) num = which_strtol(val, &endp, 0); \ if (endp == val || *endp || num < (min) || num > (max)) \ return -EINVAL; \ - *((type *) kp->arg) = num; \ + *((int *) kp->arg) = num; \ return 0; \ } diff --git a/trunk/fs/nfsd/current_stateid.h b/trunk/fs/nfsd/current_stateid.h deleted file mode 100644 index 4123551208d8..000000000000 --- a/trunk/fs/nfsd/current_stateid.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _NFSD4_CURRENT_STATE_H -#define _NFSD4_CURRENT_STATE_H - -#include "state.h" -#include "xdr4.h" - -extern void clear_current_stateid(struct nfsd4_compound_state *cstate); -/* - * functions to set current state id - */ -extern void nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *); -extern void nfsd4_set_openstateid(struct nfsd4_compound_state *, struct nfsd4_open *); -extern void nfsd4_set_lockstateid(struct nfsd4_compound_state *, struct nfsd4_lock *); -extern void nfsd4_set_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *); - -/* - * functions to consume current state id - */ -extern void nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *); -extern void nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *, struct nfsd4_delegreturn *); -extern void nfsd4_get_freestateid(struct nfsd4_compound_state *, struct nfsd4_free_stateid *); -extern void nfsd4_get_setattrstateid(struct nfsd4_compound_state *, struct nfsd4_setattr *); -extern void nfsd4_get_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *); -extern void nfsd4_get_lockustateid(struct nfsd4_compound_state *, struct nfsd4_locku *); -extern void nfsd4_get_readstateid(struct nfsd4_compound_state *, struct nfsd4_read *); -extern void nfsd4_get_writestateid(struct nfsd4_compound_state *, struct nfsd4_write *); - -#endif /* _NFSD4_CURRENT_STATE_H */ diff --git a/trunk/fs/nfsd/export.c b/trunk/fs/nfsd/export.c index 8e9689abbc0c..cf8a6bd062fa 100644 --- a/trunk/fs/nfsd/export.c +++ b/trunk/fs/nfsd/export.c @@ -87,7 +87,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) struct svc_expkey key; struct svc_expkey *ek = NULL; - if (mesg[mlen - 1] != '\n') + if (mlen < 1 || mesg[mlen-1] != '\n') return -EINVAL; mesg[mlen-1] = 0; diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 24b6bcf1e945..6f3ebb48b12f 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -986,7 +986,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) err = setup_callback_client(clp, &conn, ses); if (err) { - nfsd4_mark_cb_down(clp, err); + warn_no_callback_path(clp, err); return; } /* Yay, the callback channel's back! Restart any callbacks: */ diff --git a/trunk/fs/nfsd/nfs4proc.c b/trunk/fs/nfsd/nfs4proc.c index abe808a52d97..896da74ec563 100644 --- a/trunk/fs/nfsd/nfs4proc.c +++ b/trunk/fs/nfsd/nfs4proc.c @@ -39,7 +39,6 @@ #include "cache.h" #include "xdr4.h" #include "vfs.h" -#include "current_stateid.h" #define NFSDDBG_FACILITY NFSDDBG_PROC @@ -193,13 +192,10 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh) static __be32 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { - struct svc_fh *resfh; + struct svc_fh resfh; __be32 status; - resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); - if (!resfh) - return nfserr_jukebox; - fh_init(resfh, NFS4_FHSIZE); + fh_init(&resfh, NFS4_FHSIZE); open->op_truncate = 0; if (open->op_create) { @@ -224,7 +220,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o */ status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, open->op_fname.len, &open->op_iattr, - resfh, open->op_createmode, + &resfh, open->op_createmode, (u32 *)open->op_verf.data, &open->op_truncate, &open->op_created); @@ -238,29 +234,30 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o FATTR4_WORD1_TIME_MODIFY); } else { status = nfsd_lookup(rqstp, current_fh, - open->op_fname.data, open->op_fname.len, resfh); + open->op_fname.data, open->op_fname.len, &resfh); fh_unlock(current_fh); if (status) goto out; - status = nfsd_check_obj_isreg(resfh); + status = nfsd_check_obj_isreg(&resfh); } if (status) goto out; if (is_create_with_attrs(open) && open->op_acl != NULL) - do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); + do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval); + + set_change_info(&open->op_cinfo, current_fh); + fh_dup2(current_fh, &resfh); /* set reply cache */ fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, - &resfh->fh_handle); + &resfh.fh_handle); if (!open->op_created) - status = do_open_permission(rqstp, resfh, open, + status = do_open_permission(rqstp, current_fh, open, NFSD_MAY_NOP); - set_change_info(&open->op_cinfo, current_fh); - fh_dup2(current_fh, resfh); + out: - fh_put(resfh); - kfree(resfh); + fh_put(&resfh); return status; } @@ -313,6 +310,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) return nfserr_inval; + /* We don't yet support WANT bits: */ + open->op_share_access &= NFS4_SHARE_ACCESS_MASK; + open->op_created = 0; /* * RFC5661 18.51.3 @@ -452,10 +452,6 @@ nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, return nfserr_restorefh; fh_dup2(&cstate->current_fh, &cstate->save_fh); - if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) { - memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t)); - SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); - } return nfs_ok; } @@ -467,10 +463,6 @@ nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, return nfserr_nofilehandle; fh_dup2(&cstate->save_fh, &cstate->current_fh); - if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) { - memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t)); - SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG); - } return nfs_ok; } @@ -1008,8 +1000,6 @@ static inline void nfsd4_increment_op_stats(u32 opnum) typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, void *); typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); -typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *); -typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *); enum nfsd4_op_flags { ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ @@ -1035,10 +1025,6 @@ enum nfsd4_op_flags { * the v4.0 case). */ OP_CACHEME = 1 << 6, - /* - * These are ops which clear current state id. - */ - OP_CLEAR_STATEID = 1 << 7, }; struct nfsd4_operation { @@ -1047,8 +1033,6 @@ struct nfsd4_operation { char *op_name; /* Try to get response size before operation */ nfsd4op_rsize op_rsize_bop; - stateid_setter op_get_currentstateid; - stateid_getter op_set_currentstateid; }; static struct nfsd4_operation nfsd4_ops[]; @@ -1231,23 +1215,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, if (op->status) goto encode_op; - if (opdesc->op_func) { - if (opdesc->op_get_currentstateid) - opdesc->op_get_currentstateid(cstate, &op->u); + if (opdesc->op_func) op->status = opdesc->op_func(rqstp, cstate, &op->u); - } else + else BUG_ON(op->status == nfs_ok); - if (!op->status) { - if (opdesc->op_set_currentstateid) - opdesc->op_set_currentstateid(cstate, &op->u); - - if (opdesc->op_flags & OP_CLEAR_STATEID) - clear_current_stateid(cstate); - - if (need_wrongsec_check(rqstp)) - op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); - } + if (!op->status && need_wrongsec_check(rqstp)) + op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); encode_op: /* Only from SEQUENCE */ @@ -1439,8 +1413,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_CLOSE", .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid, - .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid, }, [OP_COMMIT] = { .op_func = (nfsd4op_func)nfsd4_commit, @@ -1450,7 +1422,7 @@ static struct nfsd4_operation nfsd4_ops[] = { }, [OP_CREATE] = { .op_func = (nfsd4op_func)nfsd4_create, - .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID, + .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_CREATE", .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize, }, @@ -1459,7 +1431,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_DELEGRETURN", .op_rsize_bop = nfsd4_only_status_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid, }, [OP_GETATTR] = { .op_func = (nfsd4op_func)nfsd4_getattr, @@ -1482,7 +1453,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LOCK", .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize, - .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid, }, [OP_LOCKT] = { .op_func = (nfsd4op_func)nfsd4_lockt, @@ -1493,16 +1463,15 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_LOCKU", .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid, }, [OP_LOOKUP] = { .op_func = (nfsd4op_func)nfsd4_lookup, - .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, + .op_flags = OP_HANDLES_WRONGSEC, .op_name = "OP_LOOKUP", }, [OP_LOOKUPP] = { .op_func = (nfsd4op_func)nfsd4_lookupp, - .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, + .op_flags = OP_HANDLES_WRONGSEC, .op_name = "OP_LOOKUPP", }, [OP_NVERIFY] = { @@ -1514,7 +1483,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, .op_name = "OP_OPEN", .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize, - .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid, }, [OP_OPEN_CONFIRM] = { .op_func = (nfsd4op_func)nfsd4_open_confirm, @@ -1527,30 +1495,25 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_OPEN_DOWNGRADE", .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid, - .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid, }, [OP_PUTFH] = { .op_func = (nfsd4op_func)nfsd4_putfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING - | OP_CLEAR_STATEID, + | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, .op_name = "OP_PUTFH", .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, }, [OP_PUTPUBFH] = { .op_func = (nfsd4op_func)nfsd4_putrootfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING - | OP_CLEAR_STATEID, + | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, .op_name = "OP_PUTPUBFH", .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, }, [OP_PUTROOTFH] = { .op_func = (nfsd4op_func)nfsd4_putrootfh, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS - | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING - | OP_CLEAR_STATEID, + | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, .op_name = "OP_PUTROOTFH", .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, }, @@ -1559,7 +1522,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING, .op_name = "OP_READ", .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid, }, [OP_READDIR] = { .op_func = (nfsd4op_func)nfsd4_readdir, @@ -1614,7 +1576,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_name = "OP_SETATTR", .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid, }, [OP_SETCLIENTID] = { .op_func = (nfsd4op_func)nfsd4_setclientid, @@ -1639,7 +1600,6 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_WRITE", .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, - .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid, }, [OP_RELEASE_LOCKOWNER] = { .op_func = (nfsd4op_func)nfsd4_release_lockowner, diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index 867086357f6c..e8c98f009670 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -58,15 +58,11 @@ static const stateid_t one_stateid = { static const stateid_t zero_stateid = { /* all fields zero */ }; -static const stateid_t currentstateid = { - .si_generation = 1, -}; static u64 current_sessionid = 1; #define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t))) #define ONE_STATEID(stateid) (!memcmp((stateid), &one_stateid, sizeof(stateid_t))) -#define CURRENT_STATEID(stateid) (!memcmp((stateid), ¤tstateid, sizeof(stateid_t))) /* forward declarations */ static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); @@ -95,19 +91,6 @@ nfs4_lock_state(void) mutex_lock(&client_mutex); } -static void free_session(struct kref *); - -/* Must be called under the client_lock */ -static void nfsd4_put_session_locked(struct nfsd4_session *ses) -{ - kref_put(&ses->se_ref, free_session); -} - -static void nfsd4_get_session(struct nfsd4_session *ses) -{ - kref_get(&ses->se_ref); -} - void nfs4_unlock_state(void) { @@ -849,12 +832,11 @@ static void nfsd4_del_conns(struct nfsd4_session *s) spin_unlock(&clp->cl_lock); } -static void free_session(struct kref *kref) +void free_session(struct kref *kref) { struct nfsd4_session *ses; int mem; - BUG_ON(!spin_is_locked(&client_lock)); ses = container_of(kref, struct nfsd4_session, se_ref); nfsd4_del_conns(ses); spin_lock(&nfsd_drc_lock); @@ -865,13 +847,6 @@ static void free_session(struct kref *kref) kfree(ses); } -void nfsd4_put_session(struct nfsd4_session *ses) -{ - spin_lock(&client_lock); - nfsd4_put_session_locked(ses); - spin_unlock(&client_lock); -} - static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) { struct nfsd4_session *new; @@ -919,9 +894,7 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n status = nfsd4_new_conn_from_crses(rqstp, new); /* whoops: benny points out, status is ignored! (err, or bogus) */ if (status) { - spin_lock(&client_lock); free_session(&new->se_ref); - spin_unlock(&client_lock); return NULL; } if (cses->flags & SESSION4_BACK_CHAN) { @@ -1033,13 +1006,12 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) static inline void free_client(struct nfs4_client *clp) { - BUG_ON(!spin_is_locked(&client_lock)); while (!list_empty(&clp->cl_sessions)) { struct nfsd4_session *ses; ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, se_perclnt); list_del(&ses->se_perclnt); - nfsd4_put_session_locked(ses); + nfsd4_put_session(ses); } if (clp->cl_cred.cr_group_info) put_group_info(clp->cl_cred.cr_group_info); @@ -1208,9 +1180,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, if (princ) { clp->cl_principal = kstrdup(princ, GFP_KERNEL); if (clp->cl_principal == NULL) { - spin_lock(&client_lock); free_client(clp); - spin_unlock(&client_lock); return NULL; } } @@ -1377,7 +1347,6 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; - slot->sl_flags |= NFSD4_SLOT_INITIALIZED; if (nfsd4_not_cached(resp)) { slot->sl_datalen = 0; return; @@ -1405,12 +1374,15 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args, struct nfsd4_op *op; struct nfsd4_slot *slot = resp->cstate.slot; + dprintk("--> %s resp->opcnt %d cachethis %u \n", __func__, + resp->opcnt, resp->cstate.slot->sl_cachethis); + /* Encode the replayed sequence operation */ op = &args->ops[resp->opcnt - 1]; nfsd4_encode_operation(resp, op); /* Return nfserr_retry_uncached_rep in next operation. */ - if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) { + if (args->opcnt > 1 && slot->sl_cachethis == 0) { op = &args->ops[resp->opcnt++]; op->status = nfserr_retry_uncached_rep; nfsd4_encode_operation(resp, op); @@ -1603,11 +1575,16 @@ check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse) else return nfserr_seq_misordered; } - /* Note unsigned 32-bit arithmetic handles wraparound: */ + /* Normal */ if (likely(seqid == slot_seqid + 1)) return nfs_ok; + /* Replay */ if (seqid == slot_seqid) return nfserr_replay_cache; + /* Wraparound */ + if (seqid == 1 && (slot_seqid + 1) == 0) + return nfs_ok; + /* Misordered replay or misordered new request */ return nfserr_seq_misordered; } @@ -1838,10 +1815,9 @@ nfsd4_destroy_session(struct svc_rqst *r, nfsd4_probe_callback_sync(ses->se_client); nfs4_unlock_state(); - spin_lock(&client_lock); nfsd4_del_conns(ses); - nfsd4_put_session_locked(ses); - spin_unlock(&client_lock); + + nfsd4_put_session(ses); status = nfs_ok; out: dprintk("%s returns %d\n", __func__, ntohl(status)); @@ -1945,12 +1921,8 @@ nfsd4_sequence(struct svc_rqst *rqstp, * sr_highest_slotid and the sr_target_slot id to maxslots */ seq->maxslots = session->se_fchannel.maxreqs; - status = check_slot_seqid(seq->seqid, slot->sl_seqid, - slot->sl_flags & NFSD4_SLOT_INUSE); + status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_inuse); if (status == nfserr_replay_cache) { - status = nfserr_seq_misordered; - if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED)) - goto out; cstate->slot = slot; cstate->session = session; /* Return the cached reply status and set cstate->status @@ -1966,12 +1938,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, conn = NULL; /* Success! bump slot seqid */ + slot->sl_inuse = true; slot->sl_seqid = seq->seqid; - slot->sl_flags |= NFSD4_SLOT_INUSE; - if (seq->cachethis) - slot->sl_flags |= NFSD4_SLOT_CACHETHIS; - else - slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS; + slot->sl_cachethis = seq->cachethis; cstate->slot = slot; cstate->session = session; @@ -2664,6 +2633,8 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) static int share_access_to_flags(u32 share_access) { + share_access &= ~NFS4_SHARE_WANT_MASK; + return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; } @@ -2805,15 +2776,10 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c static void -nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) +nfs4_set_claim_prev(struct nfsd4_open *open) { open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; - /* - * On a 4.1+ client, we don't create a state record for a client - * until it performs RECLAIM_COMPLETE: - */ - if (!has_session) - open->op_openowner->oo_owner.so_client->cl_firststate = 1; + open->op_openowner->oo_owner.so_client->cl_firststate = 1; } /* Should we give out recallable state?: */ @@ -2889,27 +2855,6 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) return 0; } -static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) -{ - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; - if (status == -EAGAIN) - open->op_why_no_deleg = WND4_CONTENTION; - else { - open->op_why_no_deleg = WND4_RESOURCE; - switch (open->op_deleg_want) { - case NFS4_SHARE_WANT_READ_DELEG: - case NFS4_SHARE_WANT_WRITE_DELEG: - case NFS4_SHARE_WANT_ANY_DELEG: - break; - case NFS4_SHARE_WANT_CANCEL: - open->op_why_no_deleg = WND4_CANCELLED; - break; - case NFS4_SHARE_WANT_NO_DELEG: - BUG(); /* not supposed to get here */ - } - } -} - /* * Attempt to hand out a delegation. */ @@ -2919,7 +2864,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_ struct nfs4_delegation *dp; struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); int cb_up; - int status = 0, flag = 0; + int status, flag = 0; cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); flag = NFS4_OPEN_DELEGATE_NONE; @@ -2960,16 +2905,11 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_ dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", STATEID_VAL(&dp->dl_stid.sc_stateid)); out: + if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS + && flag == NFS4_OPEN_DELEGATE_NONE + && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) + dprintk("NFSD: WARNING: refusing delegation reclaim\n"); open->op_delegate_type = flag; - if (flag == NFS4_OPEN_DELEGATE_NONE) { - if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && - open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) - dprintk("NFSD: WARNING: refusing delegation reclaim\n"); - - /* 4.1 client asking for a delegation? */ - if (open->op_deleg_want) - nfsd4_open_deleg_none_ext(open, status); - } return; out_free: nfs4_put_delegation(dp); @@ -2978,24 +2918,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_ goto out; } -static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, - struct nfs4_delegation *dp) -{ - if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG && - dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; - open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE; - } else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG && - dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; - open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE; - } - /* Otherwise the client must be confused wanting a delegation - * it already has, therefore we don't return - * NFS4_OPEN_DELEGATE_NONE_EXT and reason. - */ -} - /* * called with nfs4_lock_state() held. */ @@ -3057,36 +2979,24 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf update_stateid(&stp->st_stid.sc_stateid); memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); - if (nfsd4_has_session(&resp->cstate)) { + if (nfsd4_has_session(&resp->cstate)) open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; - if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; - open->op_why_no_deleg = WND4_NOT_WANTED; - goto nodeleg; - } - } - /* * Attempt to hand out a delegation. No error return, because the * OPEN succeeds even if we fail. */ nfs4_open_delegation(current_fh, open, stp); -nodeleg: + status = nfs_ok; dprintk("%s: stateid=" STATEID_FMT "\n", __func__, STATEID_VAL(&stp->st_stid.sc_stateid)); out: - /* 4.1 client trying to upgrade/downgrade delegation? */ - if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp && - open->op_deleg_want) - nfsd4_deleg_xgrade_none_ext(open, dp); - if (fp) put_nfs4_file(fp); if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) - nfs4_set_claim_prev(open, nfsd4_has_session(&resp->cstate)); + nfs4_set_claim_prev(open); /* * To finish the open response, we just need to set the rflags. */ @@ -3490,14 +3400,7 @@ __be32 nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_test_stateid *test_stateid) { - struct nfsd4_test_stateid_id *stateid; - struct nfs4_client *cl = cstate->session->se_client; - - nfs4_lock_state(); - list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list) - stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid); - nfs4_unlock_state(); - + /* real work is done during encoding */ return nfs_ok; } @@ -3693,9 +3596,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, cstate->current_fh.fh_dentry->d_name.name); /* We don't yet support WANT bits: */ - if (od->od_deleg_want) - dprintk("NFSD: %s: od_deleg_want=0x%x ignored\n", __func__, - od->od_deleg_want); + od->od_share_access &= NFS4_SHARE_ACCESS_MASK; nfs4_lock_state(); status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid, @@ -4452,9 +4353,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) struct nfs4_client *clp; clp = find_confirmed_client_by_str(name, strhashval); - if (!clp) - return 0; - return clp->cl_firststate; + return clp ? 1 : 0; } /* @@ -4714,26 +4613,21 @@ set_max_delegations(void) /* initialization to perform when the nfsd service is started: */ -int -nfs4_state_start(void) +static int +__nfs4_state_start(void) { int ret; - nfsd4_load_reboot_recovery_data(); boot_time = get_seconds(); locks_start_grace(&nfsd4_manager); printk(KERN_INFO "NFSD: starting %ld-second grace period\n", nfsd4_grace); ret = set_callback_cred(); - if (ret) { - ret = -ENOMEM; - goto out_recovery; - } + if (ret) + return -ENOMEM; laundry_wq = create_singlethread_workqueue("nfsd4"); - if (laundry_wq == NULL) { - ret = -ENOMEM; - goto out_recovery; - } + if (laundry_wq == NULL) + return -ENOMEM; ret = nfsd4_create_callback_queue(); if (ret) goto out_free_laundry; @@ -4742,12 +4636,16 @@ nfs4_state_start(void) return 0; out_free_laundry: destroy_workqueue(laundry_wq); -out_recovery: - nfs4_release_reclaim(); - nfsd4_shutdown_recdir(); return ret; } +int +nfs4_state_start(void) +{ + nfsd4_load_reboot_recovery_data(); + return __nfs4_state_start(); +} + static void __nfs4_state_shutdown(void) { @@ -4793,104 +4691,3 @@ nfs4_state_shutdown(void) nfs4_unlock_state(); nfsd4_destroy_callback_queue(); } - -static void -get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid) -{ - if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid)) - memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t)); -} - -static void -put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid) -{ - if (cstate->minorversion) { - memcpy(&cstate->current_stateid, stateid, sizeof(stateid_t)); - SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); - } -} - -void -clear_current_stateid(struct nfsd4_compound_state *cstate) -{ - CLEAR_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); -} - -/* - * functions to set current state id - */ -void -nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp) -{ - put_stateid(cstate, &odp->od_stateid); -} - -void -nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open) -{ - put_stateid(cstate, &open->op_stateid); -} - -void -nfsd4_set_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close) -{ - put_stateid(cstate, &close->cl_stateid); -} - -void -nfsd4_set_lockstateid(struct nfsd4_compound_state *cstate, struct nfsd4_lock *lock) -{ - put_stateid(cstate, &lock->lk_resp_stateid); -} - -/* - * functions to consume current state id - */ - -void -nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp) -{ - get_stateid(cstate, &odp->od_stateid); -} - -void -nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *cstate, struct nfsd4_delegreturn *drp) -{ - get_stateid(cstate, &drp->dr_stateid); -} - -void -nfsd4_get_freestateid(struct nfsd4_compound_state *cstate, struct nfsd4_free_stateid *fsp) -{ - get_stateid(cstate, &fsp->fr_stateid); -} - -void -nfsd4_get_setattrstateid(struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr) -{ - get_stateid(cstate, &setattr->sa_stateid); -} - -void -nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close) -{ - get_stateid(cstate, &close->cl_stateid); -} - -void -nfsd4_get_lockustateid(struct nfsd4_compound_state *cstate, struct nfsd4_locku *locku) -{ - get_stateid(cstate, &locku->lu_stateid); -} - -void -nfsd4_get_readstateid(struct nfsd4_compound_state *cstate, struct nfsd4_read *read) -{ - get_stateid(cstate, &read->rd_stateid); -} - -void -nfsd4_get_writestateid(struct nfsd4_compound_state *cstate, struct nfsd4_write *write) -{ - get_stateid(cstate, &write->wr_stateid); -} diff --git a/trunk/fs/nfsd/nfs4xdr.c b/trunk/fs/nfsd/nfs4xdr.c index f8fcddca0414..0ec5a1b9700e 100644 --- a/trunk/fs/nfsd/nfs4xdr.c +++ b/trunk/fs/nfsd/nfs4xdr.c @@ -133,6 +133,22 @@ xdr_error: \ } \ } while (0) +static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep) +{ + savep->p = argp->p; + savep->end = argp->end; + savep->pagelen = argp->pagelen; + savep->pagelist = argp->pagelist; +} + +static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep) +{ + argp->p = savep->p; + argp->end = savep->end; + argp->pagelen = savep->pagelen; + argp->pagelist = savep->pagelist; +} + static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) { /* We want more bytes than seem to be available. @@ -622,18 +638,14 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup DECODE_TAIL; } -static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when) +static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x) { __be32 *p; u32 w; READ_BUF(4); READ32(w); - *share_access = w & NFS4_SHARE_ACCESS_MASK; - *deleg_want = w & NFS4_SHARE_WANT_MASK; - if (deleg_when) - *deleg_when = w & NFS4_SHARE_WHEN_MASK; - + *x = w; switch (w & NFS4_SHARE_ACCESS_MASK) { case NFS4_SHARE_ACCESS_READ: case NFS4_SHARE_ACCESS_WRITE: @@ -661,9 +673,6 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *sh w &= ~NFS4_SHARE_WANT_MASK; if (!w) return nfs_ok; - - if (!deleg_when) /* open_downgrade */ - return nfserr_inval; switch (w) { case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL: case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED: @@ -710,7 +719,6 @@ static __be32 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) { DECODE_HEAD; - u32 dummy; memset(open->op_bmval, 0, sizeof(open->op_bmval)); open->op_iattr.ia_valid = 0; @@ -719,9 +727,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) /* seqid, share_access, share_deny, clientid, ownerlen */ READ_BUF(4); READ32(open->op_seqid); - /* decode, yet ignore deleg_when until supported */ - status = nfsd4_decode_share_access(argp, &open->op_share_access, - &open->op_deleg_want, &dummy); + status = nfsd4_decode_share_access(argp, &open->op_share_access); if (status) goto xdr_error; status = nfsd4_decode_share_deny(argp, &open->op_share_deny); @@ -842,8 +848,7 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d return status; READ_BUF(4); READ32(open_down->od_seqid); - status = nfsd4_decode_share_access(argp, &open_down->od_share_access, - &open_down->od_deleg_want, NULL); + status = nfsd4_decode_share_access(argp, &open_down->od_share_access); if (status) return status; status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny); @@ -1380,29 +1385,26 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, static __be32 nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid) { + unsigned int nbytes; + stateid_t si; int i; - __be32 *p, status; - struct nfsd4_test_stateid_id *stateid; + __be32 *p; + __be32 status; READ_BUF(4); test_stateid->ts_num_ids = ntohl(*p++); - INIT_LIST_HEAD(&test_stateid->ts_stateid_list); - - for (i = 0; i < test_stateid->ts_num_ids; i++) { - stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL); - if (!stateid) { - status = PTR_ERR(stateid); - goto out; - } + nbytes = test_stateid->ts_num_ids * sizeof(stateid_t); + if (nbytes > (u32)((char *)argp->end - (char *)argp->p)) + goto xdr_error; - defer_free(argp, kfree, stateid); - INIT_LIST_HEAD(&stateid->ts_id_list); - list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list); + test_stateid->ts_saved_args = argp; + save_buf(argp, &test_stateid->ts_savedp); - status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid); + for (i = 0; i < test_stateid->ts_num_ids; i++) { + status = nfsd4_decode_stateid(argp, &si); if (status) - goto out; + return status; } status = 0; @@ -2849,20 +2851,6 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op WRITE32(0); /* XXX: is NULL principal ok? */ ADJUST_ARGS(); break; - case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */ - switch (open->op_why_no_deleg) { - case WND4_CONTENTION: - case WND4_RESOURCE: - RESERVE_SPACE(8); - WRITE32(open->op_why_no_deleg); - WRITE32(0); /* deleg signaling not supported yet */ - break; - default: - RESERVE_SPACE(4); - WRITE32(open->op_why_no_deleg); - } - ADJUST_ARGS(); - break; default: BUG(); } @@ -3403,17 +3391,30 @@ __be32 nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_test_stateid *test_stateid) { - struct nfsd4_test_stateid_id *stateid, *next; + struct nfsd4_compoundargs *argp; + struct nfs4_client *cl = resp->cstate.session->se_client; + stateid_t si; __be32 *p; + int i; + int valid; + + restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp); + argp = test_stateid->ts_saved_args; - RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); + RESERVE_SPACE(4); *p++ = htonl(test_stateid->ts_num_ids); + resp->p = p; - list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { - *p++ = htonl(stateid->ts_id_status); + nfs4_lock_state(); + for (i = 0; i < test_stateid->ts_num_ids; i++) { + nfsd4_decode_stateid(argp, &si); + valid = nfs4_validate_stateid(cl, &si); + RESERVE_SPACE(4); + *p++ = htonl(valid); + resp->p = p; } + nfs4_unlock_state(); - ADJUST_ARGS(); return nfserr; } @@ -3531,7 +3532,7 @@ int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) if (length > session->se_fchannel.maxresp_sz) return nfserr_rep_too_big; - if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) && + if (slot->sl_cachethis == 1 && length > session->se_fchannel.maxresp_cached) return nfserr_rep_too_big_to_cache; @@ -3655,7 +3656,8 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo if (nfsd4_has_session(cs)) { if (cs->status != nfserr_replay_cache) { nfsd4_store_cache_entry(resp); - cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; + dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__); + cs->slot->sl_inuse = false; } /* Renew the clientid on success and on replay */ release_session_client(cs->session); diff --git a/trunk/fs/nfsd/nfssvc.c b/trunk/fs/nfsd/nfssvc.c index aacf1f4b9fb5..eda7d7e55e05 100644 --- a/trunk/fs/nfsd/nfssvc.c +++ b/trunk/fs/nfsd/nfssvc.c @@ -307,37 +307,33 @@ static void set_max_drc(void) dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem); } -static int nfsd_get_default_max_blksize(void) -{ - struct sysinfo i; - unsigned long long target; - unsigned long ret; - - si_meminfo(&i); - target = (i.totalram - i.totalhigh) << PAGE_SHIFT; - /* - * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig - * machines, but only uses 32K on 128M machines. Bottom out at - * 8K on 32M and smaller. Of course, this is only a default. - */ - target >>= 12; - - ret = NFSSVC_MAXBLKSIZE; - while (ret > target && ret >= 8*1024*2) - ret /= 2; - return ret; -} - int nfsd_create_serv(void) { + int err = 0; + WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { svc_get(nfsd_serv); return 0; } - if (nfsd_max_blksize == 0) - nfsd_max_blksize = nfsd_get_default_max_blksize(); + if (nfsd_max_blksize == 0) { + /* choose a suitable default */ + struct sysinfo i; + si_meminfo(&i); + /* Aim for 1/4096 of memory per thread + * This gives 1MB on 4Gig machines + * But only uses 32K on 128M machines. + * Bottom out at 8K on 32M and smaller. + * Of course, this is only a default. + */ + nfsd_max_blksize = NFSSVC_MAXBLKSIZE; + i.totalram <<= PAGE_SHIFT - 12; + while (nfsd_max_blksize > i.totalram && + nfsd_max_blksize >= 8*1024*2) + nfsd_max_blksize /= 2; + } nfsd_reset_versions(); + nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, nfsd_last_thread, nfsd, THIS_MODULE); if (nfsd_serv == NULL) @@ -345,7 +341,7 @@ int nfsd_create_serv(void) set_max_drc(); do_gettimeofday(&nfssvc_boot); /* record boot time */ - return 0; + return err; } int nfsd_nrpools(void) diff --git a/trunk/fs/nfsd/state.h b/trunk/fs/nfsd/state.h index 1e2b582bc9dc..ffb5df1db94f 100644 --- a/trunk/fs/nfsd/state.h +++ b/trunk/fs/nfsd/state.h @@ -128,14 +128,12 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) (NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE) struct nfsd4_slot { + bool sl_inuse; + bool sl_cachethis; + u16 sl_opcnt; u32 sl_seqid; __be32 sl_status; u32 sl_datalen; - u16 sl_opcnt; -#define NFSD4_SLOT_INUSE (1 << 0) -#define NFSD4_SLOT_CACHETHIS (1 << 1) -#define NFSD4_SLOT_INITIALIZED (1 << 2) - u8 sl_flags; char sl_data[]; }; @@ -198,7 +196,18 @@ struct nfsd4_session { struct nfsd4_slot *se_slots[]; /* forward channel slots */ }; -extern void nfsd4_put_session(struct nfsd4_session *ses); +static inline void +nfsd4_put_session(struct nfsd4_session *ses) +{ + extern void free_session(struct kref *kref); + kref_put(&ses->se_ref, free_session); +} + +static inline void +nfsd4_get_session(struct nfsd4_session *ses) +{ + kref_get(&ses->se_ref); +} /* formatted contents of nfs4_sessionid */ struct nfsd4_sessionid { diff --git a/trunk/fs/nfsd/xdr4.h b/trunk/fs/nfsd/xdr4.h index b89781f1477a..2364747ee97d 100644 --- a/trunk/fs/nfsd/xdr4.h +++ b/trunk/fs/nfsd/xdr4.h @@ -43,13 +43,6 @@ #define NFSD4_MAX_TAGLEN 128 #define XDR_LEN(n) (((n) + 3) & ~3) -#define CURRENT_STATE_ID_FLAG (1<<0) -#define SAVED_STATE_ID_FLAG (1<<1) - -#define SET_STATE_ID(c, f) ((c)->sid_flags |= (f)) -#define HAS_STATE_ID(c, f) ((c)->sid_flags & (f)) -#define CLEAR_STATE_ID(c, f) ((c)->sid_flags &= ~(f)) - struct nfsd4_compound_state { struct svc_fh current_fh; struct svc_fh save_fh; @@ -61,10 +54,6 @@ struct nfsd4_compound_state { size_t iovlen; u32 minorversion; u32 status; - stateid_t current_stateid; - stateid_t save_stateid; - /* to indicate current and saved state id presents */ - u32 sid_flags; }; static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) @@ -223,7 +212,6 @@ struct nfsd4_open { struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ u32 op_delegate_type; /* request - CLAIM_PREV only */ stateid_t op_delegate_stateid; /* request - response */ - u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */ u32 op_create; /* request */ u32 op_createmode; /* request */ u32 op_bmval[3]; /* request */ @@ -234,7 +222,6 @@ struct nfsd4_open { u32 op_seqid; /* request */ u32 op_share_access; /* request */ u32 op_share_deny; /* request */ - u32 op_deleg_want; /* request */ stateid_t op_stateid; /* response */ u32 op_recall; /* recall */ struct nfsd4_change_info op_cinfo; /* response */ @@ -258,9 +245,8 @@ struct nfsd4_open_confirm { struct nfsd4_open_downgrade { stateid_t od_stateid; u32 od_seqid; - u32 od_share_access; /* request */ - u32 od_deleg_want; /* request */ - u32 od_share_deny; /* request */ + u32 od_share_access; + u32 od_share_deny; }; @@ -357,15 +343,10 @@ struct nfsd4_saved_compoundargs { struct page **pagelist; }; -struct nfsd4_test_stateid_id { - __be32 ts_id_status; - stateid_t ts_id_stateid; - struct list_head ts_id_list; -}; - struct nfsd4_test_stateid { __be32 ts_num_ids; - struct list_head ts_stateid_list; + struct nfsd4_compoundargs *ts_saved_args; + struct nfsd4_saved_compoundargs ts_savedp; }; struct nfsd4_free_stateid { @@ -522,8 +503,7 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp) static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) { - return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) - || nfsd4_is_solo_sequence(resp); + return !resp->cstate.slot->sl_cachethis || nfsd4_is_solo_sequence(resp); } #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 386da09f229d..8975a5602931 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -92,6 +92,10 @@ struct inodes_stat_t { /* File is opened using open(.., 3, ..) and is writeable only for ioctls (specialy hack for floppy.c) */ #define FMODE_WRITE_IOCTL ((__force fmode_t)0x100) +/* 32bit hashes as llseek() offset (for directories) */ +#define FMODE_32BITHASH ((__force fmode_t)0x200) +/* 64bit hashes as llseek() offset (for directories) */ +#define FMODE_64BITHASH ((__force fmode_t)0x400) /* * Don't update ctime and mtime. diff --git a/trunk/include/linux/nfs4.h b/trunk/include/linux/nfs4.h index 8cdde4d1fad8..32345c2805c0 100644 --- a/trunk/include/linux/nfs4.h +++ b/trunk/include/linux/nfs4.h @@ -441,20 +441,7 @@ enum limit_by4 { enum open_delegation_type4 { NFS4_OPEN_DELEGATE_NONE = 0, NFS4_OPEN_DELEGATE_READ = 1, - NFS4_OPEN_DELEGATE_WRITE = 2, - NFS4_OPEN_DELEGATE_NONE_EXT = 3, /* 4.1 */ -}; - -enum why_no_delegation4 { /* new to v4.1 */ - WND4_NOT_WANTED = 0, - WND4_CONTENTION = 1, - WND4_RESOURCE = 2, - WND4_NOT_SUPP_FTYPE = 3, - WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4, - WND4_NOT_SUPP_UPGRADE = 5, - WND4_NOT_SUPP_DOWNGRADE = 6, - WND4_CANCELLED = 7, - WND4_IS_DIR = 8, + NFS4_OPEN_DELEGATE_WRITE = 2 }; enum lock_type4 { diff --git a/trunk/include/linux/sunrpc/svc_rdma.h b/trunk/include/linux/sunrpc/svc_rdma.h index 0b8e3e6bdacf..c14fe86dac59 100644 --- a/trunk/include/linux/sunrpc/svc_rdma.h +++ b/trunk/include/linux/sunrpc/svc_rdma.h @@ -190,7 +190,7 @@ extern int svc_rdma_xdr_encode_error(struct svcxprt_rdma *, extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int); extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int); extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int, - __be32, __be64, u32); + u32, u64, u32); extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *, struct rpcrdma_msg *, struct rpcrdma_msg *, @@ -292,7 +292,7 @@ svc_rdma_get_reply_array(struct rpcrdma_msg *rmsgp) if (wr_ary) { rp_ary = (struct rpcrdma_write_array *) &wr_ary-> - wc_array[ntohl(wr_ary->wc_nchunks)].wc_target.rs_length; + wc_array[wr_ary->wc_nchunks].wc_target.rs_length; goto found_it; } diff --git a/trunk/net/sunrpc/cache.c b/trunk/net/sunrpc/cache.c index 8c6598e0334a..465df9ae1046 100644 --- a/trunk/net/sunrpc/cache.c +++ b/trunk/net/sunrpc/cache.c @@ -828,8 +828,6 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, { ssize_t ret; - if (count == 0) - return -EINVAL; if (copy_from_user(kaddr, buf, count)) return -EFAULT; kaddr[count] = '\0'; diff --git a/trunk/net/sunrpc/svcauth_unix.c b/trunk/net/sunrpc/svcauth_unix.c index 6ab35736d88f..01153ead1dba 100644 --- a/trunk/net/sunrpc/svcauth_unix.c +++ b/trunk/net/sunrpc/svcauth_unix.c @@ -509,7 +509,7 @@ static int unix_gid_parse(struct cache_detail *cd, time_t expiry; struct unix_gid ug, *ugp; - if (mesg[mlen - 1] != '\n') + if (mlen <= 0 || mesg[mlen-1] != '\n') return -EINVAL; mesg[mlen-1] = 0; diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index b3bb18ba350a..464570906f80 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -1381,6 +1381,8 @@ void svc_sock_update_bufs(struct svc_serv *serv) spin_lock_bh(&serv->sv_lock); list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); + list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list) + set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); spin_unlock_bh(&serv->sv_lock); } EXPORT_SYMBOL_GPL(svc_sock_update_bufs); diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma.c b/trunk/net/sunrpc/xprtrdma/svc_rdma.c index 8343737e85f4..09af4fab1a45 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma.c @@ -47,7 +47,6 @@ #include #include #include -#include "xprt_rdma.h" #define RPCDBG_FACILITY RPCDBG_SVCXPRT diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_marshal.c index 8d2edddf48cf..9530ef2d40dc 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_marshal.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_marshal.c @@ -60,11 +60,21 @@ static u32 *decode_read_list(u32 *va, u32 *vaend) struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; while (ch->rc_discrim != xdr_zero) { + u64 ch_offset; + if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > (unsigned long)vaend) { dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); return NULL; } + + ch->rc_discrim = ntohl(ch->rc_discrim); + ch->rc_position = ntohl(ch->rc_position); + ch->rc_target.rs_handle = ntohl(ch->rc_target.rs_handle); + ch->rc_target.rs_length = ntohl(ch->rc_target.rs_length); + va = (u32 *)&ch->rc_target.rs_offset; + xdr_decode_hyper(va, &ch_offset); + put_unaligned(ch_offset, (u64 *)va); ch++; } return (u32 *)&ch->rc_position; @@ -81,7 +91,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, *byte_count = 0; *ch_count = 0; for (; ch->rc_discrim != 0; ch++) { - *byte_count = *byte_count + ntohl(ch->rc_target.rs_length); + *byte_count = *byte_count + ch->rc_target.rs_length; *ch_count = *ch_count + 1; } } @@ -98,8 +108,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, */ static u32 *decode_write_list(u32 *va, u32 *vaend) { - int nchunks; - + int ch_no; struct rpcrdma_write_array *ary = (struct rpcrdma_write_array *)va; @@ -112,24 +121,37 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); return NULL; } - nchunks = ntohl(ary->wc_nchunks); + ary->wc_discrim = ntohl(ary->wc_discrim); + ary->wc_nchunks = ntohl(ary->wc_nchunks); if (((unsigned long)&ary->wc_array[0] + - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > + (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > (unsigned long)vaend) { dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", - ary, nchunks, vaend); + ary, ary->wc_nchunks, vaend); return NULL; } + for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { + u64 ch_offset; + + ary->wc_array[ch_no].wc_target.rs_handle = + ntohl(ary->wc_array[ch_no].wc_target.rs_handle); + ary->wc_array[ch_no].wc_target.rs_length = + ntohl(ary->wc_array[ch_no].wc_target.rs_length); + va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; + xdr_decode_hyper(va, &ch_offset); + put_unaligned(ch_offset, (u64 *)va); + } + /* * rs_length is the 2nd 4B field in wc_target and taking its * address skips the list terminator */ - return (u32 *)&ary->wc_array[nchunks].wc_target.rs_length; + return (u32 *)&ary->wc_array[ch_no].wc_target.rs_length; } static u32 *decode_reply_array(u32 *va, u32 *vaend) { - int nchunks; + int ch_no; struct rpcrdma_write_array *ary = (struct rpcrdma_write_array *)va; @@ -142,15 +164,28 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); return NULL; } - nchunks = ntohl(ary->wc_nchunks); + ary->wc_discrim = ntohl(ary->wc_discrim); + ary->wc_nchunks = ntohl(ary->wc_nchunks); if (((unsigned long)&ary->wc_array[0] + - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > + (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > (unsigned long)vaend) { dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", - ary, nchunks, vaend); + ary, ary->wc_nchunks, vaend); return NULL; } - return (u32 *)&ary->wc_array[nchunks]; + for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { + u64 ch_offset; + + ary->wc_array[ch_no].wc_target.rs_handle = + ntohl(ary->wc_array[ch_no].wc_target.rs_handle); + ary->wc_array[ch_no].wc_target.rs_length = + ntohl(ary->wc_array[ch_no].wc_target.rs_length); + va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; + xdr_decode_hyper(va, &ch_offset); + put_unaligned(ch_offset, (u64 *)va); + } + + return (u32 *)&ary->wc_array[ch_no]; } int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, @@ -351,14 +386,13 @@ void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary, void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, int chunk_no, - __be32 rs_handle, - __be64 rs_offset, + u32 rs_handle, u64 rs_offset, u32 write_len) { struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; - seg->rs_handle = rs_handle; - seg->rs_offset = rs_offset; + seg->rs_handle = htonl(rs_handle); seg->rs_length = htonl(write_len); + xdr_encode_hyper((u32 *) &seg->rs_offset, rs_offset); } void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 41cb63b623df..df67211c4baf 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -147,7 +147,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, page_off = 0; ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; ch_no = 0; - ch_bytes = ntohl(ch->rc_target.rs_length); + ch_bytes = ch->rc_target.rs_length; head->arg.head[0] = rqstp->rq_arg.head[0]; head->arg.tail[0] = rqstp->rq_arg.tail[0]; head->arg.pages = &head->pages[head->count]; @@ -183,7 +183,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, ch_no++; ch++; chl_map->ch[ch_no].start = sge_no; - ch_bytes = ntohl(ch->rc_target.rs_length); + ch_bytes = ch->rc_target.rs_length; /* If bytes remaining account for next chunk */ if (byte_count) { head->arg.page_len += ch_bytes; @@ -281,12 +281,11 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, offset = 0; ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; for (ch_no = 0; ch_no < ch_count; ch_no++) { - int len = ntohl(ch->rc_target.rs_length); rpl_map->sge[ch_no].iov_base = frmr->kva + offset; - rpl_map->sge[ch_no].iov_len = len; + rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length; chl_map->ch[ch_no].count = 1; chl_map->ch[ch_no].start = ch_no; - offset += len; + offset += ch->rc_target.rs_length; ch++; } @@ -317,7 +316,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt, for (i = 0; i < count; i++) { ctxt->sge[i].length = 0; /* in case map fails */ if (!frmr) { - BUG_ON(!virt_to_page(vec[i].iov_base)); + BUG_ON(0 == virt_to_page(vec[i].iov_base)); off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; ctxt->sge[i].addr = ib_dma_map_page(xprt->sc_cm_id->device, @@ -427,7 +426,6 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; ch->rc_discrim != 0; ch++, ch_no++) { - u64 rs_offset; next_sge: ctxt = svc_rdma_get_context(xprt); ctxt->direction = DMA_FROM_DEVICE; @@ -442,10 +440,10 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, read_wr.opcode = IB_WR_RDMA_READ; ctxt->wr_op = read_wr.opcode; read_wr.send_flags = IB_SEND_SIGNALED; - read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle); - xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset, - &rs_offset); - read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset; + read_wr.wr.rdma.rkey = ch->rc_target.rs_handle; + read_wr.wr.rdma.remote_addr = + get_unaligned(&(ch->rc_target.rs_offset)) + + sgl_offset; read_wr.sg_list = ctxt->sge; read_wr.num_sge = rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 42eb7ba0b903..249a835b703f 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -409,21 +409,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, u64 rs_offset; arg_ch = &arg_ary->wc_array[chunk_no].wc_target; - write_len = min(xfer_len, ntohl(arg_ch->rs_length)); + write_len = min(xfer_len, arg_ch->rs_length); /* Prepare the response chunk given the length actually * written */ - xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset); + rs_offset = get_unaligned(&(arg_ch->rs_offset)); svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, - arg_ch->rs_handle, - arg_ch->rs_offset, - write_len); + arg_ch->rs_handle, + rs_offset, + write_len); chunk_off = 0; while (write_len) { int this_write; this_write = min(write_len, max_write); ret = send_write(xprt, rqstp, - ntohl(arg_ch->rs_handle), + arg_ch->rs_handle, rs_offset + chunk_off, xdr_off, this_write, @@ -457,7 +457,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, u32 xdr_off; int chunk_no; int chunk_off; - int nchunks; struct rpcrdma_segment *ch; struct rpcrdma_write_array *arg_ary; struct rpcrdma_write_array *res_ary; @@ -477,27 +476,26 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, max_write = xprt->sc_max_sge * PAGE_SIZE; /* xdr offset starts at RPC message */ - nchunks = ntohl(arg_ary->wc_nchunks); for (xdr_off = 0, chunk_no = 0; - xfer_len && chunk_no < nchunks; + xfer_len && chunk_no < arg_ary->wc_nchunks; chunk_no++) { u64 rs_offset; ch = &arg_ary->wc_array[chunk_no].wc_target; - write_len = min(xfer_len, htonl(ch->rs_length)); + write_len = min(xfer_len, ch->rs_length); /* Prepare the reply chunk given the length actually * written */ - xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset); + rs_offset = get_unaligned(&(ch->rs_offset)); svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, - ch->rs_handle, ch->rs_offset, - write_len); + ch->rs_handle, rs_offset, + write_len); chunk_off = 0; while (write_len) { int this_write; this_write = min(write_len, max_write); ret = send_write(xprt, rqstp, - ntohl(ch->rs_handle), + ch->rs_handle, rs_offset + chunk_off, xdr_off, this_write, diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c index 73b428bef598..894cb42db91d 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -51,7 +51,6 @@ #include #include #include -#include "xprt_rdma.h" #define RPCDBG_FACILITY RPCDBG_SVCXPRT @@ -91,6 +90,12 @@ struct svc_xprt_class svc_rdma_class = { .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, }; +/* WR context cache. Created in svc_rdma.c */ +extern struct kmem_cache *svc_rdma_ctxt_cachep; + +/* Workqueue created in svc_rdma.c */ +extern struct workqueue_struct *svc_rdma_wq; + struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) { struct svc_rdma_op_ctxt *ctxt; @@ -145,6 +150,9 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) atomic_dec(&xprt->sc_ctxt_used); } +/* Temporary NFS request map cache. Created in svc_rdma.c */ +extern struct kmem_cache *svc_rdma_map_cachep; + /* * Temporary NFS req mappings are shared across all transport * instances. These are short lived and should be bounded by the number diff --git a/trunk/net/sunrpc/xprtrdma/xprt_rdma.h b/trunk/net/sunrpc/xprtrdma/xprt_rdma.h index 9a66c95b5837..08c5d5a128fc 100644 --- a/trunk/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/trunk/net/sunrpc/xprtrdma/xprt_rdma.h @@ -343,11 +343,4 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *); */ int rpcrdma_marshal_req(struct rpc_rqst *); -/* Temporary NFS request map cache. Created in svc_rdma.c */ -extern struct kmem_cache *svc_rdma_map_cachep; -/* WR context cache. Created in svc_rdma.c */ -extern struct kmem_cache *svc_rdma_ctxt_cachep; -/* Workqueue created in svc_rdma.c */ -extern struct workqueue_struct *svc_rdma_wq; - #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */