📄 rrc_common.h
字号:
/* * Common interface for the level drivers * * (C) 2000 by Jakob Oestergaard * * This source is covered by the GNU GPL, the same as all Linux kernel * sources. */#ifndef __RRC_COMMON_H#define __RRC_COMMON_H#include "raidreconf.h"#include <limits.h>typedef struct wish_t { int source_disk_id; unsigned long source_rblock; int sink_disk_id; unsigned long sink_rblock; struct wish_t *next;} wish_t;typedef struct fulfilled_t { int sink_disk_id; unsigned long sink_rblock; char *data; struct fulfilled_t *next;} fulfilled_t;/* * About free blocks: A block is considered free, if it has been * read from the source disk. Free means ``sink is free to write stuff * here''. * Thus, we only account free blocks on the source disks, sink-only disks * are per definition always entirely free. nr_free_blocks() return only * number of free blocks on source disks. * * When the sink wishes for a block, this means it wants the data in * that global block read from somewhere on the old array. It also * means, that it wants the sink-disk,sink-disk-block freed so that it * can safely write to it. Freeing the block will mean reading it to * memory. So in real-life (TM), wishing for one block can often mean * freeing two blocks, where only one can actually be written to * somewhere. The freed blocks will end up in the list of fulfilled * requests, so the list of fulfilled requests _will_ actually hold * (lots of) blocks that hasn't directly been asked for by the sink * driver. * If the sink-disk,sink-disk-block locations of the un-wished-for * blocks are free themselves, we can easily flush these blocks. If * they are not, we should probably look for a way to free them. * This, in turn, may leed to freeing even more un-wished-for blocks. * The sink will never get more than two blocks from each wish it * files, but this is still bad if we recurse for long (quadratic * memory requirements). * There is no simple way (that I thought of at least) to ensure that * we follow a request/read/write pattern so that this program can work * correctly at all times within some limited memory space (memory much * less than size of array). Therefore we always run an algorithm check * before we actually perform the reconfiguration. The algorithm check * is a full run of the reconfiguration, only with physical disk access * turned off. If such a run can succeed, so can one with physical disk * access. * * If algorithm check fails, we probably could try a multiple-pass * strategy. For example, converting chunk sizes first, then levels, * or going thru intermediate levels... Eventually we could use a * scratch disk, or use the parity blocks on raid-[145] as temporary * buffers. * * Driver vs. common-layer operation: * * request: * The sink driver will request that a number of blocks are read from * the old array, so that it can write them to their proper location * on the new array. Wishes are inserted with global block * addresses. Global block N on the sink drive is usually not the * same as global block N on the source drive, so before the wish is * hooked into the wish-list, the common layer will have the source * driver map the global block number into a * source-disk,source-disk-block address. * * read: * The source driver will use the common layer to fulfill requests * that look good, that is, request sequences that are large and * sequential. As blocks are read, the common layer will mark them * as free. * * write: * The common layer will flush the fulfilled requests to the sink * disks. As the source driver will usually ask for sink-disk * sequential regions, the writer can assume that just flushing the * sorted sequences of fulfilled requests will perform reasonably * well. * */const char *setup_free_blocks (unsigned ndisks, rrc_disk_t * diskcfg);const char *initialize_unique_disks (void);/* * Drivers should not touch these directly */extern unsigned max_wishes;extern unsigned long reconf_block_size;extern char **source_disk_free_map;extern unsigned long *source_disk_free_size;extern unsigned long source_blocks, sink_blocks;/* * Drivers should use these routines instead... *//* * These are for the sink requester */int can_wish_again (void);int is_gblock_in_source (unsigned long gblock);void insert_wish (unsigned long gblock);/* * These are generic */unsigned long nr_free_blocks (void);int is_diskid_in_source (int diskid);int is_disk_block_free (int diskid, unsigned long block);wish_t *wish_list_source_diskid (int source_disk_id);fulfilled_t *gift_list_diskid (int disk_id);const char *generic_write_blocks (int partial);void debug_print_nonfree_blocks (void);void debug_print_wish_list (void);void print_common_stats (void);/* * These are for the common reader stuff */void fulfill_wishes (int partial);int must_fulfill_more (int partial);unsigned nr_wishes_left (void);unsigned nr_gifts_left (void);void fulfill_wish (int diskid, unsigned long begin, unsigned long end); /* do the reading *//* * This one's for the initial block freeing when we shrink arrays */void mark_disk_block_free (int diskid, unsigned long block);/* to be used in free_block_above_gblock() only! */void unchecked_mark_disk_block_free (int diskid, unsigned long block);void mark_disk_block_unfree (int diskid, unsigned long block);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -