fed up with those stupid warnings
[mmotm.git] / fs / reiser4 / flush.h
blobced87aa9e3bbace2f1931070f2caafd89e2e9356
1 /* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* DECLARATIONS: */
5 #if !defined(__REISER4_FLUSH_H__)
6 #define __REISER4_FLUSH_H__
8 #include "plugin/cluster.h"
10 /* The flush_scan data structure maintains the state of an in-progress
11 flush-scan on a single level of the tree. A flush-scan is used for counting
12 the number of adjacent nodes to flush, which is used to determine whether we
13 should relocate, and it is also used to find a starting point for flush. A
14 flush-scan object can scan in both right and left directions via the
15 scan_left() and scan_right() interfaces. The right- and left-variations are
16 similar but perform different functions. When scanning left we (optionally
17 perform rapid scanning and then) longterm-lock the endpoint node. When
18 scanning right we are simply counting the number of adjacent, dirty nodes. */
19 struct flush_scan {
21 /* The current number of nodes scanned on this level. */
22 unsigned count;
24 /* There may be a maximum number of nodes for a scan on any single
25 level. When going leftward, max_count is determined by
26 FLUSH_SCAN_MAXNODES (see reiser4.h) */
27 unsigned max_count;
29 /* Direction: Set to one of the sideof enumeration:
30 { LEFT_SIDE, RIGHT_SIDE }. */
31 sideof direction;
33 /* Initially @stop is set to false then set true once some condition
34 stops the search (e.g., we found a clean node before reaching
35 max_count or we found a node belonging to another atom). */
36 int stop;
38 /* The current scan position. If @node is non-NULL then its reference
39 count has been incremented to reflect this reference. */
40 jnode *node;
42 /* A handle for zload/zrelse of current scan position node. */
43 load_count node_load;
45 /* During left-scan, if the final position (a.k.a. endpoint node) is
46 formatted the node is locked using this lock handle. The endpoint
47 needs to be locked for transfer to the flush_position object after
48 scanning finishes. */
49 lock_handle node_lock;
51 /* When the position is unformatted, its parent, coordinate, and parent
52 zload/zrelse handle. */
53 lock_handle parent_lock;
54 coord_t parent_coord;
55 load_count parent_load;
57 /* The block allocator preceder hint. Sometimes flush_scan determines
58 what the preceder is and if so it sets it here, after which it is
59 copied into the flush_position. Otherwise, the preceder is computed
60 later. */
61 reiser4_block_nr preceder_blk;
64 struct convert_item_info {
65 dc_item_stat d_cur; /* disk cluster state of the current item */
66 dc_item_stat d_next; /* disk cluster state of the next slum item */
67 int cluster_shift; /* disk cluster shift */
68 flow_t flow; /* disk cluster data */
71 struct convert_info {
72 int count; /* for squalloc terminating */
73 item_plugin *iplug; /* current item plugin */
74 struct convert_item_info *itm; /* current item info */
75 struct cluster_handle clust; /* transform cluster */
78 typedef enum flush_position_state {
79 POS_INVALID, /* Invalid or stopped pos, do not continue slum
80 * processing */
81 POS_ON_LEAF, /* pos points to already prepped, locked
82 * formatted node at leaf level */
83 POS_ON_EPOINT, /* pos keeps a lock on twig level, "coord" field
84 * is used to traverse unformatted nodes */
85 POS_TO_LEAF, /* pos is being moved to leaf level */
86 POS_TO_TWIG, /* pos is being moved to twig level */
87 POS_END_OF_TWIG, /* special case of POS_ON_TWIG, when coord is
88 * after rightmost unit of the current twig */
89 POS_ON_INTERNAL /* same as POS_ON_LEAF, but points to internal
90 * node */
91 } flushpos_state_t;
93 /* An encapsulation of the current flush point and all the parameters that are
94 passed through the entire squeeze-and-allocate stage of the flush routine.
95 A single flush_position object is constructed after left- and right-scanning
96 finishes. */
97 struct flush_position {
98 flushpos_state_t state;
100 coord_t coord; /* coord to traverse unformatted nodes */
101 lock_handle lock; /* current lock we hold */
102 load_count load; /* load status for current locked formatted node
104 jnode *child; /* for passing a reference to unformatted child
105 * across pos state changes */
107 reiser4_blocknr_hint preceder; /* The flush 'hint' state. */
108 int leaf_relocate; /* True if enough leaf-level nodes were
109 * found to suggest a relocate policy. */
110 int alloc_cnt; /* The number of nodes allocated during squeeze
111 and allococate. */
112 int prep_or_free_cnt; /* The number of nodes prepared for write
113 (allocate) or squeezed and freed. */
114 flush_queue_t *fq;
115 long *nr_written; /* number of nodes submitted to disk */
116 int flags; /* a copy of jnode_flush flags argument */
118 znode *prev_twig; /* previous parent pointer value, used to catch
119 * processing of new twig node */
120 struct convert_info *sq; /* convert info */
122 unsigned long pos_in_unit; /* for extents only. Position
123 within an extent unit of first
124 jnode of slum */
125 long nr_to_write; /* number of unformatted nodes to handle on
126 flush */
129 static inline int item_convert_count(flush_pos_t *pos)
131 return pos->sq->count;
133 static inline void inc_item_convert_count(flush_pos_t *pos)
135 pos->sq->count++;
137 static inline void set_item_convert_count(flush_pos_t *pos, int count)
139 pos->sq->count = count;
141 static inline item_plugin *item_convert_plug(flush_pos_t *pos)
143 return pos->sq->iplug;
146 static inline struct convert_info *convert_data(flush_pos_t *pos)
148 return pos->sq;
151 static inline struct convert_item_info *item_convert_data(flush_pos_t *pos)
153 assert("edward-955", convert_data(pos));
154 return pos->sq->itm;
157 static inline struct tfm_cluster *tfm_cluster_sq(flush_pos_t *pos)
159 return &pos->sq->clust.tc;
162 static inline struct tfm_stream *tfm_stream_sq(flush_pos_t *pos,
163 tfm_stream_id id)
165 assert("edward-854", pos->sq != NULL);
166 return get_tfm_stream(tfm_cluster_sq(pos), id);
169 static inline int chaining_data_present(flush_pos_t *pos)
171 return convert_data(pos) && item_convert_data(pos);
174 /* Returns true if next node contains next item of the disk cluster
175 so item convert data should be moved to the right slum neighbor.
177 static inline int should_chain_next_node(flush_pos_t *pos)
179 int result = 0;
181 assert("edward-1007", chaining_data_present(pos));
183 switch (item_convert_data(pos)->d_next) {
184 case DC_CHAINED_ITEM:
185 result = 1;
186 break;
187 case DC_AFTER_CLUSTER:
188 break;
189 default:
190 impossible("edward-1009", "bad state of next slum item");
192 return result;
195 /* update item state in a disk cluster to assign conversion mode */
196 static inline void
197 move_chaining_data(flush_pos_t *pos, int this_node/* where is next item */)
200 assert("edward-1010", chaining_data_present(pos));
202 if (this_node == 0) {
203 /* next item is on the right neighbor */
204 assert("edward-1011",
205 item_convert_data(pos)->d_cur == DC_FIRST_ITEM ||
206 item_convert_data(pos)->d_cur == DC_CHAINED_ITEM);
207 assert("edward-1012",
208 item_convert_data(pos)->d_next == DC_CHAINED_ITEM);
210 item_convert_data(pos)->d_cur = DC_CHAINED_ITEM;
211 item_convert_data(pos)->d_next = DC_INVALID_STATE;
212 } else {
213 /* next item is on the same node */
214 assert("edward-1013",
215 item_convert_data(pos)->d_cur == DC_FIRST_ITEM ||
216 item_convert_data(pos)->d_cur == DC_CHAINED_ITEM);
217 assert("edward-1227",
218 item_convert_data(pos)->d_next == DC_AFTER_CLUSTER ||
219 item_convert_data(pos)->d_next == DC_INVALID_STATE);
221 item_convert_data(pos)->d_cur = DC_AFTER_CLUSTER;
222 item_convert_data(pos)->d_next = DC_INVALID_STATE;
226 static inline int should_convert_node(flush_pos_t *pos, znode * node)
228 return znode_convertible(node);
231 /* true if there is attached convert item info */
232 static inline int should_convert_next_node(flush_pos_t *pos)
234 return convert_data(pos) && item_convert_data(pos);
237 #define SQUALLOC_THRESHOLD 256
239 static inline int should_terminate_squalloc(flush_pos_t *pos)
241 return convert_data(pos) &&
242 !item_convert_data(pos) &&
243 item_convert_count(pos) >= SQUALLOC_THRESHOLD;
246 #if 1
247 #define check_convert_info(pos) \
248 do { \
249 if (unlikely(should_convert_next_node(pos))) { \
250 warning("edward-1006", "unprocessed chained data"); \
251 printk("d_cur = %d, d_next = %d, flow.len = %llu\n", \
252 item_convert_data(pos)->d_cur, \
253 item_convert_data(pos)->d_next, \
254 item_convert_data(pos)->flow.length); \
256 } while (0)
257 #else
258 #define check_convert_info(pos)
259 #endif /* REISER4_DEBUG */
261 void free_convert_data(flush_pos_t *pos);
262 /* used in extent.c */
263 int scan_set_current(flush_scan * scan, jnode * node, unsigned add_size,
264 const coord_t *parent);
265 int reiser4_scan_finished(flush_scan * scan);
266 int reiser4_scanning_left(flush_scan * scan);
267 int reiser4_scan_goto(flush_scan * scan, jnode * tonode);
268 txn_atom *atom_locked_by_fq(flush_queue_t *fq);
269 int reiser4_alloc_extent(flush_pos_t *flush_pos);
270 squeeze_result squalloc_extent(znode *left, const coord_t *, flush_pos_t *,
271 reiser4_key *stop_key);
272 extern int reiser4_init_fqs(void);
273 extern void reiser4_done_fqs(void);
275 #if REISER4_DEBUG
277 extern void reiser4_check_fq(const txn_atom *atom);
278 extern atomic_t flush_cnt;
280 #define check_preceder(blk) \
281 assert("nikita-2588", blk < reiser4_block_count(reiser4_get_current_sb()));
282 extern void check_pos(flush_pos_t *pos);
283 #else
284 #define check_preceder(b) noop
285 #define check_pos(pos) noop
286 #endif
288 /* __REISER4_FLUSH_H__ */
289 #endif
291 /* Make Linus happy.
292 Local variables:
293 c-indentation-style: "K&R"
294 mode-name: "LC"
295 c-basic-offset: 8
296 tab-width: 8
297 fill-column: 90
298 LocalWords: preceder
299 End: