@@ -17,9 +17,7 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/sunrpc/svcauth_gss.h>
-#if defined(CONFIG_NFS_V4_1)
#include <linux/sunrpc/bc_xprt.h>
-#endif
#include <net/inet_sock.h>
@@ -346,19 +344,28 @@ static int check_gss_callback_principal(struct nfs_client *clp,
return SVC_OK;
}
+/*
+ * Lookup the nfs_client that corresponds to this backchannel request.
+ *
+ * We only support NFSv4.1 callbacks on the fore channel connection, so
+ * the svc_is_backchannel test indicates which minorversion nfs_client we are
+ * searching for.
+ */
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
struct nfs_client *clp;
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+ u32 minorversion = svc_is_backchannel(rqstp) ? 1 : 0;
int ret = SVC_OK;
/* Don't talk to strangers */
- clp = nfs_find_client(svc_addr(rqstp), 4);
+ clp = nfs_find_client(svc_addr(rqstp), 4, minorversion);
if (clp == NULL)
- return SVC_DROP;
+ return SVC_DENIED;
- dprintk("%s: %s NFSv4 callback!\n", __func__,
- svc_print_addr(rqstp, buf, sizeof(buf)));
+ dprintk("%s: %s NFSv4 callback! minorversion %d\n", __func__,
+ svc_print_addr(rqstp, buf, sizeof(buf)),
+ clp->cl_minorversion);
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
@@ -177,7 +177,7 @@ static inline void put_session_client(struct nfs4_session *session)
static inline struct nfs_client *
find_client_from_cps(struct cb_process_state *cps, struct sockaddr *addr)
{
- return cps->session ? cps->session->clp : nfs_find_client(addr, 4);
+ return cps->session ? cps->session->clp : nfs_find_client(addr, 4, 0);
}
#else /* CONFIG_NFS_V4_1 */
@@ -189,7 +189,7 @@ static inline void nfs_client_return_layouts(struct nfs_client *clp)
static inline struct nfs_client *
find_client_from_cps(struct cb_process_state *cps, struct sockaddr *addr)
{
- return nfs_find_client(addr, 4);
+ return nfs_find_client(addr, 4, 0);
}
static inline void put_session_client(struct nfs4_session *session)
@@ -505,13 +505,13 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
* Returns NULL if there are no connections with sessions, or if no session
* matches the one of interest.
*/
- static struct nfs_client *find_client_with_session(
- const struct sockaddr *addr, u32 nfsversion,
- struct nfs4_sessionid *sessionid)
+static struct nfs_client *
+find_client_with_session(const struct sockaddr *addr, u32 nfsversion,
+ struct nfs4_sessionid *sessionid)
{
struct nfs_client *clp;
- clp = nfs_find_client(addr, 4);
+ clp = nfs_find_client(addr, 4, 1);
if (clp == NULL)
return NULL;
@@ -371,7 +371,8 @@ EXPORT_SYMBOL(nfs_sockaddr_cmp);
* Find a client by IP address and protocol version
* - returns NULL if no such client
*/
-struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
+struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion,
+ u32 minorversion)
{
struct nfs_client *clp;
@@ -385,7 +386,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
continue;
/* Different NFS versions cannot share the same nfs_client */
- if (clp->rpc_ops->version != nfsversion)
+ if (clp->rpc_ops->version != nfsversion ||
+ clp->cl_minorversion != minorversion)
continue;
/* Match only the IP address, not the port number */
@@ -401,13 +403,16 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
}
/*
- * Find a client by IP address and protocol version
- * - returns NULL if no such client
+ * Callback service RPC layer pg_authenticate method.
+ *
+ * Find a client by IP address, protocol version, and minorversion.
+ * Returns NULL if no such client
*/
struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
{
struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
u32 nfsvers = clp->rpc_ops->version;
+ u32 minorversion = clp->cl_minorversion;
spin_lock(&nfs_client_lock);
list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) {
@@ -418,7 +423,8 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
continue;
/* Different NFS versions cannot share the same nfs_client */
- if (clp->rpc_ops->version != nfsvers)
+ if (clp->rpc_ops->version != nfsvers ||
+ clp->cl_minorversion != minorversion)
continue;
/* Match only the IP address, not the port number */
@@ -131,7 +131,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
extern struct rpc_program nfs_program;
extern void nfs_put_client(struct nfs_client *);
-extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32);
+extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32, u32);
extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *,