Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142198
b: refs/heads/master
c: ec6b5d7
h: refs/heads/master
v: v3
  • Loading branch information
Andy Adamson authored and J. Bruce Fields committed Apr 4, 2009
1 parent bf47e39 commit 714b22f
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 14778a133e3be332be77d981552a79260a61ee17
refs/heads/master: ec6b5d7b5064fde27aee798b81107ea3a830de85
188 changes: 187 additions & 1 deletion trunk/fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static u32 current_delegid = 1;
static u32 nfs4_init;
static stateid_t zerostateid; /* bits all 0 */
static stateid_t onestateid; /* bits all 1 */
static u64 current_sessionid = 1;

#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
Expand Down Expand Up @@ -401,6 +402,131 @@ dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
}

static void
gen_sessionid(struct nfsd4_session *ses)
{
struct nfs4_client *clp = ses->se_client;
struct nfsd4_sessionid *sid;

sid = (struct nfsd4_sessionid *)ses->se_sessionid.data;
sid->clientid = clp->cl_clientid;
sid->sequence = current_sessionid++;
sid->reserved = 0;
}

/*
* Give the client the number of slots it requests bound by
* NFSD_MAX_SLOTS_PER_SESSION and by sv_drc_max_pages.
*
* If we run out of pages (sv_drc_pages_used == sv_drc_max_pages) we
* should (up to a point) re-negotiate active sessions and reduce their
* slot usage to make rooom for new connections. For now we just fail the
* create session.
*/
static int set_forechannel_maxreqs(struct nfsd4_channel_attrs *fchan)
{
int status = 0, np = fchan->maxreqs * NFSD_PAGES_PER_SLOT;

spin_lock(&nfsd_serv->sv_lock);
if (np + nfsd_serv->sv_drc_pages_used > nfsd_serv->sv_drc_max_pages)
np = nfsd_serv->sv_drc_max_pages - nfsd_serv->sv_drc_pages_used;
nfsd_serv->sv_drc_pages_used += np;
spin_unlock(&nfsd_serv->sv_lock);

if (np <= 0) {
status = nfserr_resource;
fchan->maxreqs = 0;
} else
fchan->maxreqs = np / NFSD_PAGES_PER_SLOT;

return status;
}

/*
* fchan holds the client values on input, and the server values on output
*/
static int init_forechannel_attrs(struct svc_rqst *rqstp,
struct nfsd4_session *session,
struct nfsd4_channel_attrs *fchan)
{
int status = 0;
__u32 maxcount = svc_max_payload(rqstp);

/* headerpadsz set to zero in encode routine */

/* Use the client's max request and max response size if possible */
if (fchan->maxreq_sz > maxcount)
fchan->maxreq_sz = maxcount;
session->se_fmaxreq_sz = fchan->maxreq_sz;

if (fchan->maxresp_sz > maxcount)
fchan->maxresp_sz = maxcount;
session->se_fmaxresp_sz = fchan->maxresp_sz;

/* Set the max response cached size our default which is
* a multiple of PAGE_SIZE and small */
session->se_fmaxresp_cached = NFSD_PAGES_PER_SLOT * PAGE_SIZE;
fchan->maxresp_cached = session->se_fmaxresp_cached;

/* Use the client's maxops if possible */
if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND)
fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND;
session->se_fmaxops = fchan->maxops;

/* try to use the client requested number of slots */
if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION)
fchan->maxreqs = NFSD_MAX_SLOTS_PER_SESSION;

/* FIXME: Error means no more DRC pages so the server should
* recover pages from existing sessions. For now fail session
* creation.
*/
status = set_forechannel_maxreqs(fchan);

session->se_fnumslots = fchan->maxreqs;
return status;
}

static int
alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
struct nfsd4_create_session *cses)
{
struct nfsd4_session *new, tmp;
int idx, status = nfserr_resource, slotsize;

memset(&tmp, 0, sizeof(tmp));

/* FIXME: For now, we just accept the client back channel attributes. */
status = init_forechannel_attrs(rqstp, &tmp, &cses->fore_channel);
if (status)
goto out;

/* allocate struct nfsd4_session and slot table in one piece */
slotsize = tmp.se_fnumslots * sizeof(struct nfsd4_slot);
new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
if (!new)
goto out;

memcpy(new, &tmp, sizeof(*new));

new->se_client = clp;
gen_sessionid(new);
idx = hash_sessionid(&new->se_sessionid);
memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
NFS4_MAX_SESSIONID_LEN);

new->se_flags = cses->flags;
kref_init(&new->se_ref);
spin_lock(&sessionid_lock);
list_add(&new->se_hash, &sessionid_hashtbl[idx]);
list_add(&new->se_perclnt, &clp->cl_sessions);
spin_unlock(&sessionid_lock);

status = nfs_ok;
out:
return status;
}

/* caller must hold sessionid_lock */
static struct nfsd4_session *
find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
Expand Down Expand Up @@ -1182,7 +1308,67 @@ nfsd4_create_session(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate,
struct nfsd4_create_session *cr_ses)
{
return -1; /* stub */
u32 ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
struct nfs4_client *conf, *unconf;
int status = 0;

nfs4_lock_state();
unconf = find_unconfirmed_client(&cr_ses->clientid);
conf = find_confirmed_client(&cr_ses->clientid);

if (conf) {
status = nfs_ok;
if (conf->cl_seqid == cr_ses->seqid) {
dprintk("Got a create_session replay! seqid= %d\n",
conf->cl_seqid);
goto out_replay;
} else if (cr_ses->seqid != conf->cl_seqid + 1) {
status = nfserr_seq_misordered;
dprintk("Sequence misordered!\n");
dprintk("Expected seqid= %d but got seqid= %d\n",
conf->cl_seqid, cr_ses->seqid);
goto out;
}
conf->cl_seqid++;
} else if (unconf) {
if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
(ip_addr != unconf->cl_addr)) {
status = nfserr_clid_inuse;
goto out;
}

if (unconf->cl_seqid != cr_ses->seqid) {
status = nfserr_seq_misordered;
goto out;
}

move_to_confirmed(unconf);

/*
* We do not support RDMA or persistent sessions
*/
cr_ses->flags &= ~SESSION4_PERSIST;
cr_ses->flags &= ~SESSION4_RDMA;

conf = unconf;
} else {
status = nfserr_stale_clientid;
goto out;
}

status = alloc_init_session(rqstp, conf, cr_ses);
if (status)
goto out;

out_replay:
memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data,
NFS4_MAX_SESSIONID_LEN);
cr_ses->seqid = conf->cl_seqid;

out:
nfs4_unlock_state();
dprintk("%s returns %d\n", __func__, ntohl(status));
return status;
}

__be32
Expand Down
148 changes: 145 additions & 3 deletions trunk/fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,108 @@ static __be32
nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
struct nfsd4_create_session *sess)
{
return nfserr_opnotsupp; /* stub */
DECODE_HEAD;

u32 dummy;
char *machine_name;
int i;
int nr_secflavs;

READ_BUF(16);
COPYMEM(&sess->clientid, 8);
READ32(sess->seqid);
READ32(sess->flags);

/* Fore channel attrs */
READ_BUF(28);
READ32(dummy); /* headerpadsz is always 0 */
READ32(sess->fore_channel.maxreq_sz);
READ32(sess->fore_channel.maxresp_sz);
READ32(sess->fore_channel.maxresp_cached);
READ32(sess->fore_channel.maxops);
READ32(sess->fore_channel.maxreqs);
READ32(sess->fore_channel.nr_rdma_attrs);
if (sess->fore_channel.nr_rdma_attrs == 1) {
READ_BUF(4);
READ32(sess->fore_channel.rdma_attrs);
} else if (sess->fore_channel.nr_rdma_attrs > 1) {
dprintk("Too many fore channel attr bitmaps!\n");
goto xdr_error;
}

/* Back channel attrs */
READ_BUF(28);
READ32(dummy); /* headerpadsz is always 0 */
READ32(sess->back_channel.maxreq_sz);
READ32(sess->back_channel.maxresp_sz);
READ32(sess->back_channel.maxresp_cached);
READ32(sess->back_channel.maxops);
READ32(sess->back_channel.maxreqs);
READ32(sess->back_channel.nr_rdma_attrs);
if (sess->back_channel.nr_rdma_attrs == 1) {
READ_BUF(4);
READ32(sess->back_channel.rdma_attrs);
} else if (sess->back_channel.nr_rdma_attrs > 1) {
dprintk("Too many back channel attr bitmaps!\n");
goto xdr_error;
}

READ_BUF(8);
READ32(sess->callback_prog);

/* callback_sec_params4 */
READ32(nr_secflavs);
for (i = 0; i < nr_secflavs; ++i) {
READ_BUF(4);
READ32(dummy);
switch (dummy) {
case RPC_AUTH_NULL:
/* Nothing to read */
break;
case RPC_AUTH_UNIX:
READ_BUF(8);
/* stamp */
READ32(dummy);

/* machine name */
READ32(dummy);
READ_BUF(dummy);
SAVEMEM(machine_name, dummy);

/* uid, gid */
READ_BUF(8);
READ32(sess->uid);
READ32(sess->gid);

/* more gids */
READ_BUF(4);
READ32(dummy);
READ_BUF(dummy * 4);
for (i = 0; i < dummy; ++i)
READ32(dummy);
break;
case RPC_AUTH_GSS:
dprintk("RPC_AUTH_GSS callback secflavor "
"not supported!\n");
READ_BUF(8);
/* gcbp_service */
READ32(dummy);
/* gcbp_handle_from_server */
READ32(dummy);
READ_BUF(dummy);
p += XDR_QUADLEN(dummy);
/* gcbp_handle_from_client */
READ_BUF(4);
READ32(dummy);
READ_BUF(dummy);
p += XDR_QUADLEN(dummy);
break;
default:
dprintk("Illegal callback secflavor\n");
return nfserr_inval;
}
}
DECODE_TAIL;
}

static __be32
Expand Down Expand Up @@ -2821,8 +2922,49 @@ static __be32
nfsd4_encode_create_session(struct nfsd4_compoundres *resp, int nfserr,
struct nfsd4_create_session *sess)
{
/* stub */
return nfserr;
ENCODE_HEAD;

if (nfserr)
return nfserr;

RESERVE_SPACE(24);
WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN);
WRITE32(sess->seqid);
WRITE32(sess->flags);
ADJUST_ARGS();

RESERVE_SPACE(28);
WRITE32(0); /* headerpadsz */
WRITE32(sess->fore_channel.maxreq_sz);
WRITE32(sess->fore_channel.maxresp_sz);
WRITE32(sess->fore_channel.maxresp_cached);
WRITE32(sess->fore_channel.maxops);
WRITE32(sess->fore_channel.maxreqs);
WRITE32(sess->fore_channel.nr_rdma_attrs);
ADJUST_ARGS();

if (sess->fore_channel.nr_rdma_attrs) {
RESERVE_SPACE(4);
WRITE32(sess->fore_channel.rdma_attrs);
ADJUST_ARGS();
}

RESERVE_SPACE(28);
WRITE32(0); /* headerpadsz */
WRITE32(sess->back_channel.maxreq_sz);
WRITE32(sess->back_channel.maxresp_sz);
WRITE32(sess->back_channel.maxresp_cached);
WRITE32(sess->back_channel.maxops);
WRITE32(sess->back_channel.maxreqs);
WRITE32(sess->back_channel.nr_rdma_attrs);
ADJUST_ARGS();

if (sess->back_channel.nr_rdma_attrs) {
RESERVE_SPACE(4);
WRITE32(sess->back_channel.rdma_attrs);
ADJUST_ARGS();
}
return 0;
}

static __be32
Expand Down
Loading

0 comments on commit 714b22f

Please sign in to comment.