2009-10-06 11:31:07 -07:00
# include "ceph_debug.h"
# include "buffer.h"
2010-02-02 16:11:19 -08:00
# include "decode.h"
2009-10-06 11:31:07 -07:00
2009-12-07 12:17:17 -08:00
struct ceph_buffer * ceph_buffer_new ( size_t len , gfp_t gfp )
2009-10-06 11:31:07 -07:00
{
struct ceph_buffer * b ;
b = kmalloc ( sizeof ( * b ) , gfp ) ;
if ( ! b )
return NULL ;
2009-12-07 12:17:17 -08:00
b - > vec . iov_base = kmalloc ( len , gfp | __GFP_NOWARN ) ;
if ( b - > vec . iov_base ) {
b - > is_vmalloc = false ;
} else {
b - > vec . iov_base = __vmalloc ( len , gfp , PAGE_KERNEL ) ;
if ( ! b - > vec . iov_base ) {
kfree ( b ) ;
return NULL ;
}
b - > is_vmalloc = true ;
}
2009-12-05 10:13:33 -08:00
kref_init ( & b - > kref ) ;
2009-12-07 12:17:17 -08:00
b - > alloc_len = len ;
b - > vec . iov_len = len ;
dout ( " buffer_new %p \n " , b ) ;
2009-10-06 11:31:07 -07:00
return b ;
}
2009-12-05 10:13:33 -08:00
void ceph_buffer_release ( struct kref * kref )
{
struct ceph_buffer * b = container_of ( kref , struct ceph_buffer , kref ) ;
2009-12-07 12:17:17 -08:00
dout ( " buffer_release %p \n " , b ) ;
2009-12-05 10:13:33 -08:00
if ( b - > vec . iov_base ) {
if ( b - > is_vmalloc )
vfree ( b - > vec . iov_base ) ;
else
kfree ( b - > vec . iov_base ) ;
}
kfree ( b ) ;
}
2009-10-06 11:31:07 -07:00
int ceph_buffer_alloc ( struct ceph_buffer * b , int len , gfp_t gfp )
{
b - > vec . iov_base = kmalloc ( len , gfp | __GFP_NOWARN ) ;
if ( b - > vec . iov_base ) {
b - > is_vmalloc = false ;
} else {
b - > vec . iov_base = __vmalloc ( len , gfp , PAGE_KERNEL ) ;
b - > is_vmalloc = true ;
}
if ( ! b - > vec . iov_base )
return - ENOMEM ;
b - > alloc_len = len ;
b - > vec . iov_len = len ;
return 0 ;
}
2010-02-02 16:11:19 -08:00
int ceph_decode_buffer ( struct ceph_buffer * * b , void * * p , void * end )
{
size_t len ;
ceph_decode_need ( p , end , sizeof ( u32 ) , bad ) ;
len = ceph_decode_32 ( p ) ;
dout ( " decode_buffer len %d \n " , ( int ) len ) ;
ceph_decode_need ( p , end , len , bad ) ;
* b = ceph_buffer_new ( len , GFP_NOFS ) ;
if ( ! * b )
return - ENOMEM ;
ceph_decode_copy ( p , ( * b ) - > vec . iov_base , len ) ;
return 0 ;
bad :
return - EINVAL ;
}