⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rait-device.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 4 页
字号:
    chunk_size = size / (chunks - 1);    rval = malloc(chunk_size);    if (chunks != chunk) {        /* data block. */        memcpy(rval, data + chunk_size * (chunk - 1), chunk_size);    } else {        make_parity_block(data, rval, chunk_size, chunks);    }        return rval;}static gboolean rait_device_write_block (Device * dself, guint size, gpointer data,                         gboolean last_block) {    GPtrArray * ops;    guint i;    gboolean success;    guint data_children, num_children;    int blocksize;    RaitDevice * self;    self = RAIT_DEVICE(dself);    g_return_val_if_fail(self != NULL, FALSE);    find_simple_params(RAIT_DEVICE(self), &num_children, &data_children,                       &blocksize);    num_children = self->private->children->len;    if (num_children != 1)        data_children = num_children - 1;    else        data_children = num_children;        g_return_val_if_fail(size % data_children == 0 || last_block, FALSE);    if (last_block) {        char *new_data;        new_data = malloc(blocksize);        memcpy(new_data, data, size);        bzero(new_data + size, blocksize - size);        data = new_data;        size = blocksize;    }    ops = g_ptr_array_sized_new(num_children);    for (i = 0; i < self->private->children->len; i ++) {        WriteBlockOp * op;        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->short_block = last_block;        op->size = size / data_children;        if (num_children <= 2) {            op->data = data;            op->data_needs_free = FALSE;        } else {            op->data_needs_free = TRUE;            op->data = extract_data_block(data, size, num_children, i + 1);        }        g_ptr_array_add(ops, op);    }    if (last_block) {        amfree(data);    }        do_rait_child_ops(write_block_do_op, ops, NULL);    success = g_ptr_array_and(ops, extract_boolean_generic_op);    for (i = 0; i < self->private->children->len; i ++) {        WriteBlockOp * op = g_ptr_array_index(ops, i);        if (op->data_needs_free)            free(op->data);    }    g_ptr_array_free_full(ops);    if (!success) {        return FALSE;    } else {        /* We don't chain up here because we must handle finish_file           differently. If we were called with last_block, then the           children have already called finish_file themselves. So we           update the device block numbers manually. */        dself->block ++;        if (last_block)            dself->in_file = FALSE;        return TRUE;    }}/* A GFunc */static void finish_file_do_op(gpointer data,                              gpointer user_data G_GNUC_UNUSED) {    GenericOp * op = data;    op->result = GINT_TO_POINTER(device_finish_file(op->child));}static gboolean rait_device_finish_file (Device * self) {    GPtrArray * ops;    gboolean success;    ops = make_generic_boolean_op_array(RAIT_DEVICE(self));        do_rait_child_ops(finish_file_do_op, ops, NULL);    success = g_ptr_array_and(ops, extract_boolean_generic_op);    g_ptr_array_free_full(ops);    if (!success) {        return FALSE;    } else if (parent_class->finish_file) {        return parent_class->finish_file(self);    } else {        return TRUE;    }}typedef struct {    GenericOp base;    guint requested_file;                /* IN */    guint actual_file;                   /* OUT */} SeekFileOp;/* a GFunc. */static void seek_file_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) {    SeekFileOp * op = data;    op->base.result = device_seek_file(op->base.child, op->requested_file);    op->actual_file = op->base.child->file;}static dumpfile_t * rait_device_seek_file (Device * dself, guint file) {    GPtrArray * ops;    guint i;    gboolean success;    dumpfile_t * rval;    RaitDevice * self = RAIT_DEVICE(dself);    guint actual_file = 0;    g_return_val_if_fail(self != NULL, FALSE);    ops = g_ptr_array_sized_new(self->private->children->len);    for (i = 0; i < self->private->children->len; i ++) {        SeekFileOp * op;        if ((int)i == self->private->failed)            continue; /* This device is broken. */        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->base.child_index = i;        op->requested_file = file;        g_ptr_array_add(ops, op);    }        do_rait_child_ops(seek_file_do_op, ops, NULL);    /* This checks for NULL values, but we still have to check for       consistant headers. */    success = g_ptr_array_union_robust(RAIT_DEVICE(self),                                       ops, extract_boolean_pointer_op);    rval = NULL;    for (i = 0; i < self->private->children->len; i ++) {        SeekFileOp * this_op;        dumpfile_t * this_result;        guint this_actual_file;        if ((int)i == self->private->failed)            continue;                this_op = (SeekFileOp*)g_ptr_array_index(ops, i);        this_result = this_op->base.result;        this_actual_file = this_op->actual_file;        if (rval == NULL) {            rval = this_result;            actual_file = this_actual_file;        } else {            if (headers_are_equal(rval, this_result) &&                actual_file == this_actual_file) {                /* Do nothing. */            } else {                success = FALSE;            }            free(this_result);        }    }    g_ptr_array_free_full(ops);    if (!success) {        amfree(rval);        return NULL;    } else if (parent_class->seek_file) {        parent_class->seek_file(dself, file);    }    return rval;}typedef struct {    GenericOp base;    guint64 block; /* IN */} SeekBlockOp;/* a GFunc. */static void seek_block_do_op(gpointer data, gpointer user_data G_GNUC_UNUSED) {    SeekBlockOp * op = data;    op->base.result =        GINT_TO_POINTER(device_seek_block(op->base.child, op->block));}static gboolean rait_device_seek_block (Device * dself, guint64 block) {    GPtrArray * ops;    guint i;    gboolean success;    RaitDevice * self = RAIT_DEVICE(dself);    g_return_val_if_fail(self != NULL, FALSE);    ops = g_ptr_array_sized_new(self->private->children->len);    for (i = 0; i < self->private->children->len; i ++) {        SeekBlockOp * op;        if ((int)i == self->private->failed)            continue; /* This device is broken. */        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->base.child_index = i;        op->block = block;        g_ptr_array_add(ops, op);    }        do_rait_child_ops(seek_block_do_op, ops, NULL);    success = g_ptr_array_union_robust(RAIT_DEVICE(self),                                       ops, extract_boolean_generic_op);    g_ptr_array_free_full(ops);    if (!success) {        return FALSE;    } else if (parent_class->seek_block) {        return parent_class->seek_block(dself, block);    } else {        return success;    }}typedef struct {    GenericOp base;    gpointer buffer; /* IN */    int read_size;      /* IN/OUT -- note not a pointer */    int desired_read_size; /* bookkeeping */} ReadBlockOp;/* a GFunc. */static void read_block_do_op(gpointer data,                             gpointer user_data G_GNUC_UNUSED) {    ReadBlockOp * op = data;    op->base.result =        GINT_TO_POINTER(device_read_block(op->base.child, op->buffer,                                          &(op->read_size)));}/* A BooleanExtractor. This one checks for a successful read. */static gboolean extract_boolean_read_block_op_data(gpointer data) {    ReadBlockOp * op = data;    return GPOINTER_TO_INT(op->base.result) == op->desired_read_size;}/* A BooleanExtractor. This one checks for EOF. */static gboolean extract_boolean_read_block_op_eof(gpointer data) {    ReadBlockOp * op = data;    return op->base.child->is_eof;}static int g_ptr_array_count(GPtrArray * array, BooleanExtractor filter) {    int rval;    unsigned int i;    rval = 0;    for (i = 0; i < array->len ; i++) {        if (filter(g_ptr_array_index(array, i)))            rval ++;    }    return rval;}static gboolean raid_block_reconstruction(RaitDevice * self, GPtrArray * ops,                                      gpointer buf) {    guint num_children, data_children;    int blocksize, child_blocksize;    guint i;    int parity_child;    gpointer parity_block = NULL;    gboolean success;    success = TRUE;    find_simple_params(self, &num_children, &data_children, &blocksize);    if (num_children > 1)        parity_child = num_children - 1;    else        parity_child = -1;    child_blocksize = blocksize / data_children;    for (i = 0; i < ops->len; i ++) {        ReadBlockOp * op = g_ptr_array_index(ops, i);        if (!extract_boolean_read_block_op_data(op))            continue;        if ((int)(op->base.child_index) == parity_child) {            parity_block = op->buffer;        } else {            memcpy((char *)buf + child_blocksize * op->base.child_index, op->buffer,                   child_blocksize);        }    }    if (self->private->status == RAIT_STATUS_COMPLETE) {        if (num_children >= 2) {            /* Verify the parity block. This code is inefficient but               does the job for the 2-device case, too. */            gpointer constructed_parity;            GPtrArray * data_extents;                        constructed_parity = malloc(child_blocksize);            data_extents = g_ptr_array_sized_new(data_children);            for (i = 0; i < data_children; i ++) {                ReadBlockOp * op = g_ptr_array_index(ops, i);                g_assert(extract_boolean_read_block_op_data(op));                if ((int)op->base.child_index == parity_child)                    continue;                g_ptr_array_add(data_extents, op->buffer);            }            make_parity_block_extents(data_extents, constructed_parity,                                      child_blocksize);                        if (0 != memcmp(parity_block, constructed_parity,                            child_blocksize)) {                g_fprintf(stderr, "RAIT is inconsistant: "                        "Parity block did not match data blocks.\n");                success = FALSE;            }            g_ptr_array_free(data_extents, TRUE);            amfree(constructed_parity);        } else { /* do nothing. */ }    } else if (self->private->status == RAIT_STATUS_DEGRADED) {        /* We are in degraded mode. What's missing? */        if (self->private->failed == parity_child) {            /* do nothing. */        } else if (num_children >= 2) {            /* Reconstruct failed block from parity block. */            GPtrArray * data_extents = g_ptr_array_new();                        for (i = 0; i < data_children; i ++) {                ReadBlockOp * op = g_ptr_array_index(ops, i);                if (!extract_boolean_read_block_op_data(op))                    continue;                g_ptr_array_add(data_extents, op->buffer);            }            /* Conveniently, the reconstruction is the same procedure               as the parity generation. This even works if there is               only one remaining device! */            make_parity_block_extents(data_extents,                                      (char *)buf + (child_blocksize *                                             self->private->failed),                                      child_blocksize);            /* The array members belong to our ops argument. */            g_ptr_array_free(data_extents, TRUE);        } else {            g_assert_not_reached();        }    } else {        success = FALSE;    }    return success;}static intrait_device_read_block (Device * dself, gpointer buf, int * size) {    GPtrArray * ops;    guint i;    gboolean success;    guint num_children, data_children;    int blocksize;    RaitDevice * self = RAIT_DEVICE(dself);    g_return_val_if_fail(self != NULL, -1);    find_simple_params(self, &num_children, &data_children,                       &blocksize);    g_return_val_if_fail(*size >= (int)device_write_min_size(dself), -1);    g_assert(blocksize % data_children == 0); /* If not we are screwed */    ops = g_ptr_array_sized_new(num_children);    for (i = 0; i < num_children; i ++) {        ReadBlockOp * op;        if ((int)i == self->private->failed)            continue; /* This device is broken. */        op = malloc(sizeof(*op));        op->base.child = g_ptr_array_index(self->private->children, i);        op->base.child_index = i;        op->buffer = malloc(blocksize / data_children);        op->desired_read_size = op->read_size = blocksize / data_children;        g_ptr_array_add(ops, op);    }        do_rait_child_ops(read_block_do_op, ops, NULL);    if (g_ptr_array_count(ops, extract_boolean_read_block_op_data)) {        success =            g_ptr_array_union_robust(RAIT_DEVICE(self),                                     ops,                                     extract_boolean_read_block_op_data) &&            raid_block_reconstruction(RAIT_DEVICE(self),                                      ops, buf);    } else {        success = FALSE;        if (g_ptr_array_union_robust(RAIT_DEVICE(self),                                     ops,                                     extract_boolean_read_block_op_eof)) {            /* We hit EOF. */            dself->is_eof = TRUE;        }    }    for (i = 0; i < ops->len; i ++) {        ReadBlockOp * op = g_ptr_array_index(ops, i);        amfree(op->buffer);    }    g_ptr_array_free_full(ops);    if (success) {        if (parent_class->read_block)            parent_class->read_block(dself, buf, size);        return blocksize;    } else {        return -1;    }}typedef struct {    GenericOp base;    DevicePropertyId id;   /* IN */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -