/* Copyright (c) 2008-2015 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 __ROT_BUFFS_H #define __ROT_BUFFS_H #include "glusterfs/list.h" #include "glusterfs/locking.h" #include "glusterfs/common-utils.h" typedef struct rbuf_iovec { struct iovec iov; struct list_head list; } rbuf_iovec_t; #define RBUF_IOVEC_SIZE (sizeof(rbuf_iovec_t)) typedef struct rbuf_list { gf_lock_t c_lock; pthread_mutex_t b_lock; /* protects this structure */ pthread_cond_t b_cond; /* signal for writer completion */ gf_boolean_t awaiting; unsigned long long pending; /* pending writers */ unsigned long long completed; /* completed writers */ rbuf_iovec_t *rvec; /* currently used IO vector */ struct list_head veclist; /* list of attached rbuf_iov */ unsigned long long used; /* consumable entries attached in ->veclist */ unsigned long long total; /* total entries in ->veclist (used during deallocation) */ unsigned long seq[2]; /* if interested, this whould store the start sequence number and the range */ struct list_head list; /* attachment to rbuf_t */ } rbuf_list_t; struct rlist_iter { struct list_head veclist; unsigned long long iter; }; #define RLIST_ENTRY_COUNT(rlist) rlist->used #define rlist_iter_init(riter, rlist) \ do { \ (riter)->iter = rlist->used; \ (riter)->veclist = rlist->veclist; \ } while (0) #define rvec_for_each_entry(pos, riter) \ for (pos = list_entry((riter)->veclist.next, typeof(*pos), list); \ (riter)->iter > 0; \ pos = list_entry(pos->list.next, typeof(*pos), list), \ --((riter)->iter)) /** * Sequence number assignment routine is called during buffer * switch under rbuff ->lock. */ typedef void(sequence_fn)(rbuf_list_t *, void *); #define RLIST_STORE_SEQ(rlist, start, range) \ do { \ rlist->seq[0] = start; \ rlist->seq[1] = range; \ } while (0) #define RLIST_GET_SEQ(rlist, start, range) \ do { \ start = rlist->seq[0]; \ range = rlist->seq[1]; \ } while (0) typedef struct rbuf { gf_lock_t lock; /* protects "current" rlist */ rbuf_list_t *current; /* cached pointer to first free rlist */ struct list_head freelist; } rbuf_t; typedef enum { RBUF_CONSUMABLE = 1, RBUF_BUSY, RBUF_EMPTY, RBUF_WOULD_STARVE, } rlist_retval_t; /* Initialization/Destruction */ rbuf_t * rbuf_init(int); void rbuf_dtor(rbuf_t *); /* Producer API */ char * rbuf_reserve_write_area(rbuf_t *, size_t, void **); int rbuf_write_complete(void *); /* Consumer API */ int rbuf_get_buffer(rbuf_t *, void **, sequence_fn *, void *); int rbuf_wait_for_completion(rbuf_t *, void *, void (*)(rbuf_list_t *, void *), void *); #endif