diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-10-04 23:12:59 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-01-11 15:04:09 -0500 |
commit | 1d1bc8f2074f0b728dfca2a3c16f2f5a3f298ffc (patch) | |
tree | 314aae91a98ab5358886a1d8517151f40816ec4c /fs/nfsd/nfs4state.c | |
parent | 4c6493785a1ea9c3b3522f199760a90a30e1626c (diff) |
nfsd4: support BIND_CONN_TO_SESSION
Basic xdr and processing for BIND_CONN_TO_SESSION. This adds a
connection to the list of connections associated with a session.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3cf9900d5f32..956174f488a7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -679,15 +679,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn) | |||
679 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); | 679 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); |
680 | } | 680 | } |
681 | 681 | ||
682 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 682 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) |
683 | { | 683 | { |
684 | struct nfsd4_conn *conn; | 684 | struct nfsd4_conn *conn; |
685 | u32 flags = NFS4_CDFC4_FORE; | ||
686 | int ret; | 685 | int ret; |
687 | 686 | ||
688 | if (ses->se_flags & SESSION4_BACK_CHAN) | 687 | conn = alloc_conn(rqstp, dir); |
689 | flags |= NFS4_CDFC4_BACK; | ||
690 | conn = alloc_conn(rqstp, flags); | ||
691 | if (!conn) | 688 | if (!conn) |
692 | return nfserr_jukebox; | 689 | return nfserr_jukebox; |
693 | nfsd4_hash_conn(conn, ses); | 690 | nfsd4_hash_conn(conn, ses); |
@@ -698,6 +695,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | |||
698 | return nfs_ok; | 695 | return nfs_ok; |
699 | } | 696 | } |
700 | 697 | ||
698 | static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) | ||
699 | { | ||
700 | u32 dir = NFS4_CDFC4_FORE; | ||
701 | |||
702 | if (ses->se_flags & SESSION4_BACK_CHAN) | ||
703 | dir |= NFS4_CDFC4_BACK; | ||
704 | |||
705 | return nfsd4_new_conn(rqstp, ses, dir); | ||
706 | } | ||
707 | |||
708 | /* must be called under client_lock */ | ||
701 | static void nfsd4_del_conns(struct nfsd4_session *s) | 709 | static void nfsd4_del_conns(struct nfsd4_session *s) |
702 | { | 710 | { |
703 | struct nfs4_client *clp = s->se_client; | 711 | struct nfs4_client *clp = s->se_client; |
@@ -776,7 +784,7 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
776 | spin_unlock(&clp->cl_lock); | 784 | spin_unlock(&clp->cl_lock); |
777 | spin_unlock(&client_lock); | 785 | spin_unlock(&client_lock); |
778 | 786 | ||
779 | status = nfsd4_new_conn(rqstp, new); | 787 | status = nfsd4_new_conn_from_crses(rqstp, new); |
780 | /* whoops: benny points out, status is ignored! (err, or bogus) */ | 788 | /* whoops: benny points out, status is ignored! (err, or bogus) */ |
781 | if (status) { | 789 | if (status) { |
782 | free_session(&new->se_ref); | 790 | free_session(&new->se_ref); |
@@ -1597,6 +1605,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | |||
1597 | return argp->opcnt == resp->opcnt; | 1605 | return argp->opcnt == resp->opcnt; |
1598 | } | 1606 | } |
1599 | 1607 | ||
1608 | static __be32 nfsd4_map_bcts_dir(u32 *dir) | ||
1609 | { | ||
1610 | switch (*dir) { | ||
1611 | case NFS4_CDFC4_FORE: | ||
1612 | case NFS4_CDFC4_BACK: | ||
1613 | return nfs_ok; | ||
1614 | case NFS4_CDFC4_FORE_OR_BOTH: | ||
1615 | case NFS4_CDFC4_BACK_OR_BOTH: | ||
1616 | *dir = NFS4_CDFC4_BOTH; | ||
1617 | return nfs_ok; | ||
1618 | }; | ||
1619 | return nfserr_inval; | ||
1620 | } | ||
1621 | |||
1622 | __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | ||
1623 | struct nfsd4_compound_state *cstate, | ||
1624 | struct nfsd4_bind_conn_to_session *bcts) | ||
1625 | { | ||
1626 | __be32 status; | ||
1627 | |||
1628 | if (!nfsd4_last_compound_op(rqstp)) | ||
1629 | return nfserr_not_only_op; | ||
1630 | spin_lock(&client_lock); | ||
1631 | cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid); | ||
1632 | /* Sorta weird: we only need the refcnt'ing because new_conn acquires | ||
1633 | * client_lock iself: */ | ||
1634 | if (cstate->session) { | ||
1635 | nfsd4_get_session(cstate->session); | ||
1636 | atomic_inc(&cstate->session->se_client->cl_refcount); | ||
1637 | } | ||
1638 | spin_unlock(&client_lock); | ||
1639 | if (!cstate->session) | ||
1640 | return nfserr_badsession; | ||
1641 | |||
1642 | status = nfsd4_map_bcts_dir(&bcts->dir); | ||
1643 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); | ||
1644 | return nfs_ok; | ||
1645 | } | ||
1646 | |||
1600 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1647 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) |
1601 | { | 1648 | { |
1602 | if (!session) | 1649 | if (!session) |