/****************************************************************************** * * Create a DAG to do a read or write operation. * * create a list of dagLists, one list per parity stripe. * return the lists in the desc->dagList (which is a list of lists). * * Normally, each list contains one dag for the entire stripe. In some * tricky cases, we break this into multiple dags, either one per stripe * unit or one per block (sector). When this occurs, these dags are returned * as a linked list (dagList) which is executed sequentially (to preserve * atomic parity updates in the stripe). * * dags which operate on independent parity goups (stripes) are returned in * independent dagLists (distinct elements in desc->dagArray) and may be * executed concurrently. * * Finally, if the SelectionFunc fails to create a dag for a block, we punt * and return 1. * * The above process is performed in two phases: * 1) create an array(s) of creation functions (eg stripeFuncs) * 2) create dags and concatenate/merge to form the final dag. * * Because dag's are basic blocks (single entry, single exit, unconditional * control flow, we can add the following optimizations (future work): * first-pass optimizer to allow max concurrency (need all data dependencies) * second-pass optimizer to eliminate common subexpressions (need true * data dependencies) * third-pass optimizer to eliminate dead code (need true data dependencies) *****************************************************************************/