]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/nfsd/nfs4callback.c
Merge branch 'parisc-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[karo-tx-linux.git] / fs / nfsd / nfs4callback.c
index bdf29c96e4cdbed8eff6d25bb28022ead1e0122e..99bc85ff02179f3e28ed36f56872e1e48d190e21 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include "nfsd.h"
 #include "state.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -625,20 +626,46 @@ static const struct rpc_program cb_program = {
        .pipe_dir_name          = "nfsd4_cb",
 };
 
-static int max_cb_time(void)
+static int max_cb_time(struct net *net)
 {
-       return max(nfsd4_lease/10, (time_t)1) * HZ;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
 }
 
+static struct rpc_cred *callback_cred;
+
+int set_callback_cred(void)
+{
+       if (callback_cred)
+               return 0;
+       callback_cred = rpc_lookup_machine_cred("nfs");
+       if (!callback_cred)
+               return -ENOMEM;
+       return 0;
+}
+
+static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
+{
+       if (clp->cl_minorversion == 0) {
+               return get_rpccred(callback_cred);
+       } else {
+               struct rpc_auth *auth = client->cl_auth;
+               struct auth_cred acred = {};
+
+               acred.uid = ses->se_cb_sec.uid;
+               acred.gid = ses->se_cb_sec.gid;
+               return auth->au_ops->lookup_cred(client->cl_auth, &acred, 0);
+       }
+}
 
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
        struct rpc_timeout      timeparms = {
-               .to_initval     = max_cb_time(),
+               .to_initval     = max_cb_time(clp->net),
                .to_retries     = 0,
        };
        struct rpc_create_args args = {
-               .net            = &init_net,
+               .net            = clp->net,
                .address        = (struct sockaddr *) &conn->cb_addr,
                .addrsize       = conn->cb_addrlen,
                .saddress       = (struct sockaddr *) &conn->cb_saddr,
@@ -648,6 +675,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
        };
        struct rpc_clnt *client;
+       struct rpc_cred *cred;
 
        if (clp->cl_minorversion == 0) {
                if (!clp->cl_cred.cr_principal &&
@@ -666,7 +694,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                args.bc_xprt = conn->cb_xprt;
                args.prognumber = clp->cl_cb_session->se_cb_prog;
                args.protocol = XPRT_TRANSPORT_BC_TCP;
-               args.authflavor = RPC_AUTH_UNIX;
+               args.authflavor = ses->se_cb_sec.flavor;
        }
        /* Create RPC client */
        client = rpc_create(&args);
@@ -675,9 +703,14 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                        PTR_ERR(client));
                return PTR_ERR(client);
        }
+       cred = get_backchannel_cred(clp, client, ses);
+       if (IS_ERR(cred)) {
+               rpc_shutdown_client(client);
+               return PTR_ERR(cred);
+       }
        clp->cl_cb_client = client;
+       clp->cl_cb_cred = cred;
        return 0;
-
 }
 
 static void warn_no_callback_path(struct nfs4_client *clp, int reason)
@@ -714,18 +747,6 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
        .rpc_call_done = nfsd4_cb_probe_done,
 };
 
-static struct rpc_cred *callback_cred;
-
-int set_callback_cred(void)
-{
-       if (callback_cred)
-               return 0;
-       callback_cred = rpc_lookup_machine_cred("nfs");
-       if (!callback_cred)
-               return -ENOMEM;
-       return 0;
-}
-
 static struct workqueue_struct *callback_wq;
 
 static void run_nfsd4_cb(struct nfsd4_callback *cb)
@@ -743,7 +764,6 @@ static void do_probe_callback(struct nfs4_client *clp)
        cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
        cb->cb_msg.rpc_argp = NULL;
        cb->cb_msg.rpc_resp = NULL;
-       cb->cb_msg.rpc_cred = callback_cred;
 
        cb->cb_ops = &nfsd4_cb_probe_ops;
 
@@ -962,6 +982,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
        if (clp->cl_cb_client) {
                rpc_shutdown_client(clp->cl_cb_client);
                clp->cl_cb_client = NULL;
+               put_rpccred(clp->cl_cb_cred);
+               clp->cl_cb_cred = NULL;
        }
        if (clp->cl_cb_conn.cb_xprt) {
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
@@ -995,7 +1017,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
                run_nfsd4_cb(cb);
 }
 
-void nfsd4_do_callback_rpc(struct work_struct *w)
+static void nfsd4_do_callback_rpc(struct work_struct *w)
 {
        struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
        struct nfs4_client *clp = cb->cb_clp;
@@ -1010,10 +1032,16 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
                nfsd4_release_cb(cb);
                return;
        }
+       cb->cb_msg.rpc_cred = clp->cl_cb_cred;
        rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
                        cb->cb_ops, cb);
 }
 
+void nfsd4_init_callback(struct nfsd4_callback *cb)
+{
+       INIT_WORK(&cb->cb_work, nfsd4_do_callback_rpc);
+}
+
 void nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
        struct nfsd4_callback *cb = &dp->dl_recall;
@@ -1025,7 +1053,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
        cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
        cb->cb_msg.rpc_argp = cb;
        cb->cb_msg.rpc_resp = cb;
-       cb->cb_msg.rpc_cred = callback_cred;
 
        cb->cb_ops = &nfsd4_cb_recall_ops;