SUNRPC: Fix pointer arithmetic bug recently introduced in rpc_malloc/free
authorChuck Lever <chuck.lever@oracle.com>
Tue, 8 May 2007 22:23:28 +0000 (18:23 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 9 May 2007 21:57:59 +0000 (17:57 -0400)
Use a cleaner method to find the size of an rpc_buffer.  This actually
works on x86-64!

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
net/sunrpc/sched.c

index 99014516b73c7855294df0788c88f3d954a7214f..b28a0b037f4f7d4daf4e01459bef1ff4e312c624 100644 (file)
@@ -736,6 +736,11 @@ static void rpc_async_schedule(struct work_struct *work)
        __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
 }
 
+struct rpc_buffer {
+       size_t  len;
+       char    data[];
+};
+
 /**
  * rpc_malloc - allocate an RPC buffer
  * @task: RPC task that will use this buffer
@@ -754,18 +759,18 @@ static void rpc_async_schedule(struct work_struct *work)
  */
 void *rpc_malloc(struct rpc_task *task, size_t size)
 {
-       size_t *buf;
+       struct rpc_buffer *buf;
        gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
 
-       size += sizeof(size_t);
+       size += sizeof(struct rpc_buffer);
        if (size <= RPC_BUFFER_MAXSIZE)
                buf = mempool_alloc(rpc_buffer_mempool, gfp);
        else
                buf = kmalloc(size, gfp);
-       *buf = size;
+       buf->len = size;
        dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
                        task->tk_pid, size, buf);
-       return ++buf;
+       return &buf->data;
 }
 
 /**
@@ -775,15 +780,18 @@ void *rpc_malloc(struct rpc_task *task, size_t size)
  */
 void rpc_free(void *buffer)
 {
-       size_t size, *buf = buffer;
+       size_t size;
+       struct rpc_buffer *buf;
 
        if (!buffer)
                return;
-       size = *buf;
-       buf--;
+
+       buf = container_of(buffer, struct rpc_buffer, data);
+       size = buf->len;
 
        dprintk("RPC:       freeing buffer of size %zu at %p\n",
                        size, buf);
+
        if (size <= RPC_BUFFER_MAXSIZE)
                mempool_free(buf, rpc_buffer_mempool);
        else