/* Copyright (c) 2008-2012 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #ifndef _IOBUF_H_ #define _IOBUF_H_ #include // for size_t #include #include "glusterfs/atomic.h" // for gf_atomic_t #include // for struct iovec #include "glusterfs/locking.h" // for gf_lock_t #include "glusterfs/list.h" #define GF_VARIABLE_IOBUF_COUNT 32 #define GF_RDMA_DEVICE_COUNT 8 /* Lets try to define the new anonymous mapping * flag, in case the system is still using the * now deprecated MAP_ANON flag. * * Also, this should ideally be in a centralized/common * header which can be used by other source files also. */ #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif #define GF_ALIGN_BUF(ptr, bound) \ ((void *)((unsigned long)(ptr + bound - 1) & (unsigned long)(~(bound - 1)))) #define GF_IOBUF_ALIGN_SIZE 512 /* one allocatable unit for the consumers of the IOBUF API */ /* each unit hosts @page_size bytes of memory */ struct iobuf; /* one region of memory mapped from the operating system */ /* each region MMAPs @arena_size bytes of memory */ /* each arena hosts @arena_size / @page_size IOBUFs */ struct iobuf_arena; /* expandable and contractable pool of memory, internally broken into arenas */ struct iobuf_pool; struct iobuf_init_config { size_t pagesize; int32_t num_pages; }; struct iobuf { union { struct list_head list; struct { struct iobuf *next; struct iobuf *prev; }; }; struct iobuf_arena *iobuf_arena; gf_lock_t lock; /* for ->ptr and ->ref */ gf_atomic_t ref; /* 0 == passive, >0 == active */ void *ptr; /* usable memory region by the consumer */ void *free_ptr; /* in case of stdalloc, this is the one to be freed */ }; struct iobuf_arena { union { struct list_head list; struct { struct iobuf_arena *next; struct iobuf_arena *prev; }; }; struct list_head all_list; size_t page_size; /* size of all iobufs in this arena */ size_t arena_size; /* this is equal to rounded_size * num_iobufs. (rounded_size comes with gf_iobuf_get_pagesize().) */ size_t page_count; struct iobuf_pool *iobuf_pool; void *mem_base; struct iobuf *iobufs; /* allocated iobufs list */ struct iobuf active; /* head node iobuf (unused by itself) */ struct iobuf passive; /* head node iobuf (unused by itself) */ uint64_t alloc_cnt; /* total allocs in this pool */ int active_cnt; int passive_cnt; int max_active; /* max active buffers at a given time */ }; struct iobuf_pool { pthread_mutex_t mutex; size_t arena_size; /* size of memory region in arena */ size_t default_page_size; /* default size of iobuf */ struct list_head all_arenas; struct list_head arenas[GF_VARIABLE_IOBUF_COUNT]; /* array of arenas. Each element of the array is a list of arenas holding iobufs of particular page_size */ struct list_head filled[GF_VARIABLE_IOBUF_COUNT]; /* array of arenas without free iobufs */ struct list_head purge[GF_VARIABLE_IOBUF_COUNT]; /* array of of arenas which can be purged */ uint64_t request_misses; /* mostly the requests for higher value of iobufs */ int arena_cnt; int rdma_device_count; struct list_head *mr_list[GF_RDMA_DEVICE_COUNT]; void *device[GF_RDMA_DEVICE_COUNT]; int (*rdma_registration)(void **, void *); int (*rdma_deregistration)(struct list_head **, struct iobuf_arena *); }; struct iobuf_pool * iobuf_pool_new(void); void iobuf_pool_destroy(struct iobuf_pool *iobuf_pool); struct iobuf * iobuf_get(struct iobuf_pool *iobuf_pool); void iobuf_unref(struct iobuf *iobuf); struct iobuf * iobuf_ref(struct iobuf *iobuf); void iobuf_pool_destroy(struct iobuf_pool *iobuf_pool); void iobuf_to_iovec(struct iobuf *iob, struct iovec *iov); #define iobuf_ptr(iob) ((iob)->ptr) #define iobpool_default_pagesize(iobpool) ((iobpool)->default_page_size) #define iobuf_pagesize(iob) (iob->iobuf_arena->page_size) struct iobref { gf_lock_t lock; gf_atomic_t ref; struct iobuf **iobrefs; int allocated; int used; }; struct iobref * iobref_new(void); struct iobref * iobref_ref(struct iobref *iobref); void iobref_unref(struct iobref *iobref); int iobref_add(struct iobref *iobref, struct iobuf *iobuf); int iobref_merge(struct iobref *to, struct iobref *from); void iobref_clear(struct iobref *iobref); size_t iobuf_size(struct iobuf *iobuf); size_t iobref_size(struct iobref *iobref); void iobuf_stats_dump(struct iobuf_pool *iobuf_pool); struct iobuf * iobuf_get2(struct iobuf_pool *iobuf_pool, size_t page_size); struct iobuf * iobuf_get_page_aligned(struct iobuf_pool *iobuf_pool, size_t page_size, size_t align_size); int iobuf_copy(struct iobuf_pool *iobuf_pool, const struct iovec *iovec_src, int iovcnt, struct iobref **iobref, struct iobuf **iobuf, struct iovec *iov_dst); #endif /* !_IOBUF_H_ */