Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / sunrpc / svc.c
index bb2d99f..b08419e 100644 (file)
@@ -32,23 +32,27 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
        int vers;
        unsigned int xdrsize;
 
-       if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL)))
+       if (!(serv = kmalloc(sizeof(*serv), GFP_KERNEL)))
                return NULL;
        memset(serv, 0, sizeof(*serv));
+       serv->sv_name      = prog->pg_name;
        serv->sv_program   = prog;
        serv->sv_nrthreads = 1;
        serv->sv_stats     = prog->pg_stats;
        serv->sv_bufsz     = bufsize? bufsize : 4096;
-       prog->pg_lovers = prog->pg_nvers-1;
        xdrsize = 0;
-       for (vers=0; vers<prog->pg_nvers ; vers++)
-               if (prog->pg_vers[vers]) {
-                       prog->pg_hivers = vers;
-                       if (prog->pg_lovers > vers)
-                               prog->pg_lovers = vers;
-                       if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
-                               xdrsize = prog->pg_vers[vers]->vs_xdrsize;
-               }
+       while (prog) {
+               prog->pg_lovers = prog->pg_nvers-1;
+               for (vers=0; vers<prog->pg_nvers ; vers++)
+                       if (prog->pg_vers[vers]) {
+                               prog->pg_hivers = vers;
+                               if (prog->pg_lovers > vers)
+                                       prog->pg_lovers = vers;
+                               if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
+                                       xdrsize = prog->pg_vers[vers]->vs_xdrsize;
+                       }
+               prog = prog->pg_next;
+       }
        serv->sv_xdrsize   = xdrsize;
        INIT_LIST_HEAD(&serv->sv_threads);
        INIT_LIST_HEAD(&serv->sv_sockets);
@@ -56,8 +60,6 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
        INIT_LIST_HEAD(&serv->sv_permsocks);
        spin_lock_init(&serv->sv_lock);
 
-       serv->sv_name      = prog->pg_name;
-
        /* Remove any stale portmap registrations */
        svc_register(serv, 0, 0);
 
@@ -120,8 +122,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
        rqstp->rq_argused = 0;
        rqstp->rq_resused = 0;
        arghi = 0;
-       if (pages > RPCSVC_MAXPAGES)
-               BUG();
+       BUG_ON(pages > RPCSVC_MAXPAGES);
        while (pages) {
                struct page *p = alloc_page(GFP_KERNEL);
                if (!p)
@@ -165,8 +166,8 @@ svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
        memset(rqstp, 0, sizeof(*rqstp));
        init_waitqueue_head(&rqstp->rq_wait);
 
-       if (!(rqstp->rq_argp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
-        || !(rqstp->rq_resp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
+       if (!(rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
+        || !(rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
         || !svc_init_buffer(rqstp, serv->sv_bufsz))
                goto out_thread;
 
@@ -194,12 +195,9 @@ svc_exit_thread(struct svc_rqst *rqstp)
        struct svc_serv *serv = rqstp->rq_server;
 
        svc_release_buffer(rqstp);
-       if (rqstp->rq_resp)
-               kfree(rqstp->rq_resp);
-       if (rqstp->rq_argp)
-               kfree(rqstp->rq_argp);
-       if (rqstp->rq_auth_data)
-               kfree(rqstp->rq_auth_data);
+       kfree(rqstp->rq_resp);
+       kfree(rqstp->rq_argp);
+       kfree(rqstp->rq_auth_data);
        kfree(rqstp);
 
        /* Release the server */
@@ -281,6 +279,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        rqstp->rq_res.len = 0;
        rqstp->rq_res.page_base = 0;
        rqstp->rq_res.page_len = 0;
+       rqstp->rq_res.buflen = PAGE_SIZE;
        rqstp->rq_res.tail[0].iov_len = 0;
        /* tcp needs a space for the record length... */
        if (rqstp->rq_prot == IPPROTO_TCP)
@@ -310,6 +309,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        rqstp->rq_proc = proc = ntohl(svc_getu32(argv));        /* procedure number */
 
        progp = serv->sv_program;
+
+       for (progp = serv->sv_program; progp; progp = progp->pg_next)
+               if (prog == progp->pg_prog)
+                       break;
+
        /*
         * Decode auth data, and add verifier to reply buffer.
         * We do this before anything else in order to get a decent
@@ -317,7 +321,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
         */
        auth_res = svc_authenticate(rqstp, &auth_stat);
        /* Also give the program a chance to reject this call: */
-       if (auth_res == SVC_OK) {
+       if (auth_res == SVC_OK && progp) {
                auth_stat = rpc_autherr_badcred;
                auth_res = progp->pg_authenticate(rqstp);
        }
@@ -337,8 +341,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        case SVC_COMPLETE:
                goto sendit;
        }
-               
-       if (prog != progp->pg_prog)
+
+       if (progp == NULL)
                goto err_bad_prog;
 
        if (vers >= progp->pg_nvers ||
@@ -451,11 +455,7 @@ err_bad_auth:
        goto sendit;
 
 err_bad_prog:
-#ifdef RPC_PARANOIA
-       if (prog != 100227 || progp->pg_prog != 100003)
-               printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
-       /* else it is just a Solaris client seeing if ACLs are supported */
-#endif
+       dprintk("svc: unknown program %d\n", prog);
        serv->sv_stats->rpcbadfmt++;
        svc_putu32(resv, rpc_prog_unavail);
        goto sendit;