1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*
Copyright (c) 2008-2015 Red Hat, Inc. <http://www.redhat.com>
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 "list.h"
#include "locking.h"
#include "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
|