diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-05-08 18:23:28 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-05-09 17:57:59 -0400 |
commit | aa3d1faebe6e214cd96be0e587571477ff6fd9fc (patch) | |
tree | d2295c15e30437a2bc693bd71b79a42c742ffc8b /net/sunrpc/sched.c | |
parent | e70c490810dc683fad39e57cf00e69d5f120c542 (diff) | |
download | linux-aa3d1faebe6e214cd96be0e587571477ff6fd9fc.tar.gz linux-aa3d1faebe6e214cd96be0e587571477ff6fd9fc.tar.bz2 linux-aa3d1faebe6e214cd96be0e587571477ff6fd9fc.zip |
SUNRPC: Fix pointer arithmetic bug recently introduced in rpc_malloc/free
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>
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r-- | net/sunrpc/sched.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 99014516b73c..b28a0b037f4f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -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 |