1
0
mirror of https://github.com/schoebel/mars synced 2025-01-07 14:56:54 +00:00

light: implement resize operation during operation

This commit is contained in:
Thomas Schoebel-Theuer 2012-08-08 15:50:41 +02:00 committed by Thomas Schoebel-Theuer
parent 37e5645a8e
commit 8ad0d372aa
4 changed files with 107 additions and 56 deletions

View File

@ -439,8 +439,8 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
prefetch_len = total_len;
}
#endif
if (pos + prefetch_len > input->info.current_size) {
prefetch_len = input->info.current_size - pos;
if (pos + prefetch_len > brick->dev_size) {
prefetch_len = brick->dev_size - pos;
}
if (prefetch_len < bv_len) {
prefetch_len = bv_len;
@ -602,6 +602,23 @@ int mars_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
return 128;
}
static
unsigned long compute_capacity(struct if_brick *brick)
{
if (brick->dev_size <= 0) {
struct mars_info info = {};
struct if_input *input = brick->inputs[0];
int status;
status = GENERIC_INPUT_CALL(input, mars_get_info, &info);
if (status < 0) {
MARS_ERR("cannot get device info, status=%d\n", status);
return 0;
}
brick->dev_size = info.current_size;
}
return brick->dev_size >> 9; // TODO: make this dynamic
}
static const struct block_device_operations if_blkdev_ops;
static int if_switch(struct if_brick *brick)
@ -617,13 +634,7 @@ static int if_switch(struct if_brick *brick)
if (brick->power.button && brick->power.led_off) {
mars_power_led_off((void*)brick, false);
status = GENERIC_INPUT_CALL(input, mars_get_info, &input->info);
if (status < 0) {
MARS_ERR("cannot get device info, status=%d\n", status);
goto is_down;
}
capacity = input->info.current_size >> 9; // TODO: make this dynamic
capacity = compute_capacity(brick);
status = -ENOMEM;
q = blk_alloc_queue(GFP_MARS);
if (!q) {
@ -648,6 +659,7 @@ static int if_switch(struct if_brick *brick)
snprintf(disk->disk_name, sizeof(disk->disk_name), "mars/%s", brick->brick_name);
MARS_DBG("created device name %s\n", disk->disk_name);
disk->private_data = input;
input->capacity = capacity;
set_capacity(disk, capacity);
blk_queue_make_request(q, if_make_request);
@ -700,6 +712,12 @@ static int if_switch(struct if_brick *brick)
}
if (brick->power.button) {
mars_power_led_on((void*)brick, true);
capacity = compute_capacity(brick);
if (capacity > 0 && capacity != input->capacity) {
MARS_INF("changing capacity from %lld to %lld\n", (long long)input->capacity * 2, (long long)capacity * 2);
input->capacity = capacity;
set_capacity(input->disk, capacity);
}
status = 0;
} else if (!brick->power.led_off) {
mars_power_led_on((void*)brick, false);

View File

@ -47,6 +47,7 @@ struct if_input {
#ifdef USE_TIMER
struct timer_list timer;
#endif
unsigned long capacity;
atomic_t open_count;
atomic_t plugged_count;
atomic_t flying_count;
@ -61,7 +62,6 @@ struct if_input {
atomic_t total_mref_write_count;
spinlock_t req_lock;
struct semaphore kick_sem;
struct mars_info info;
spinlock_t hash_lock[IF_HASH_MAX];
struct list_head hash_table[IF_HASH_MAX];
};
@ -73,6 +73,7 @@ struct if_output {
struct if_brick {
MARS_BRICK(if);
// parameters
loff_t dev_size;
int max_plugged;
int readahead;
bool skip_sync;

View File

@ -69,6 +69,50 @@ struct light_class {
///////////////////////////////////////////////////////////////////////
// needed for logfile rotation
struct mars_rotate {
struct mars_global *global;
struct copy_brick *sync_brick;
struct mars_dent *replay_link;
struct mars_dent *aio_dent;
struct aio_brick *aio_brick;
struct mars_info aio_info;
struct trans_logger_brick *trans_brick;
struct mars_dent *first_log;
struct mars_dent *relevant_log;
struct mars_brick *relevant_brick;
struct mars_dent *next_relevant_log;
struct mars_brick *next_relevant_brick;
struct mars_dent *next_next_relevant_log;
struct mars_dent *prev_log;
struct mars_dent *next_log;
struct if_brick *if_brick;
const char *copy_path;
struct copy_brick *copy_brick;
long long switchover_timeout;
long long flip_start;
loff_t dev_size;
loff_t total_space;
loff_t remaining_space;
loff_t start_pos;
loff_t end_pos;
int max_sequence;
int copy_serial;
int relevant_serial;
bool has_error;
bool allow_update;
bool allow_sync;
bool allow_replay;
bool replay_mode;
bool todo_primary;
bool is_primary;
bool old_is_primary;
bool copy_is_done;
};
///////////////////////////////////////////////////////////////////////
// TUNING
int mars_mem_percent = 0;
@ -270,14 +314,17 @@ static
int _set_if_params(struct mars_brick *_brick, void *private)
{
struct if_brick *if_brick = (void*)_brick;
struct mars_rotate *rot = private;
if (_brick->type != (void*)&if_brick_type) {
MARS_ERR("bad brick type\n");
return -EINVAL;
}
if (rot)
if_brick->dev_size = rot->dev_size;
if_brick->max_plugged = IF_MAX_PLUGGED;
if_brick->readahead = IF_READAHEAD;
if_brick->skip_sync = IF_SKIP_SYNC;
MARS_INF("name = '%s' path = '%s'\n", _brick->brick_name, _brick->brick_path);
MARS_INF("name = '%s' path = '%s' size = %lld\n", _brick->brick_name, _brick->brick_path, if_brick->dev_size);
return 1;
}
@ -481,49 +528,6 @@ done:
///////////////////////////////////////////////////////////////////////
// needed for logfile rotation
struct mars_rotate {
struct mars_global *global;
struct copy_brick *sync_brick;
struct mars_dent *replay_link;
struct mars_dent *aio_dent;
struct aio_brick *aio_brick;
struct mars_info aio_info;
struct trans_logger_brick *trans_brick;
struct mars_dent *first_log;
struct mars_dent *relevant_log;
struct mars_brick *relevant_brick;
struct mars_dent *next_relevant_log;
struct mars_brick *next_relevant_brick;
struct mars_dent *next_next_relevant_log;
struct mars_dent *prev_log;
struct mars_dent *next_log;
struct if_brick *if_brick;
const char *copy_path;
struct copy_brick *copy_brick;
long long switchover_timeout;
long long flip_start;
loff_t total_space;
loff_t remaining_space;
loff_t start_pos;
loff_t end_pos;
int max_sequence;
int copy_serial;
int relevant_serial;
bool has_error;
bool allow_update;
bool allow_sync;
bool allow_replay;
bool replay_mode;
bool todo_primary;
bool is_primary;
bool old_is_primary;
bool copy_is_done;
};
///////////////////////////////////////////////////////////////////////
// status display
static
@ -1649,6 +1653,9 @@ int make_log_init(void *buf, struct mars_dent *dent)
rot->max_sequence = 0;
rot->has_error = false;
if (dent->new_link)
sscanf(dent->new_link, "%lld", &rot->dev_size);
mars_remaining_space(parent_path, &rot->total_space, &rot->remaining_space);
/* Fetch the replay status symlink.
@ -2597,6 +2604,10 @@ int make_dev(void *buf, struct mars_dent *dent)
MARS_DBG("nothing to do\n");
goto done;
}
if (rot->dev_size <= 0) {
MARS_WRN("trying to create device '%s' with zero size\n", dent->d_path);
goto done;
}
status = _parse_args(dent, dent->new_link, 1);
if (status < 0) {
@ -2618,7 +2629,7 @@ int make_dev(void *buf, struct mars_dent *dent)
dent,
false,
_set_if_params,
NULL,
rot,
10 * HZ,
dent->d_argv[0],
(const struct generic_brick_type*)&if_brick_type,

View File

@ -702,6 +702,27 @@ sub invalidate_res {
symlink("0", $dst) or die "cannot create invalidation symlink '$dst'\n";
}
sub resize_res {
my ($cmd, $res) = @_;
my @actsizes = glob("$mars/resource-$res/actsize-*");
die "resource $res has no actsize-* symlinks\n" unless @actsizes;
my $lnk = "$mars/resource-$res/size";
my $old_size = readlink($lnk) or die "cannot read symlink '$lnk'\n";
my $min_size = 0;
foreach my $actsize (@actsizes) {
my $this_size = readlink($actsize) or die "cannot read symlink '$actsize'\n";
if (!$min_size || $min_size < $this_size) {
$min_size = $this_size;
}
}
print "old_size=$old_size\n";
print "new_size=$min_size\n";
die "only increases of the size are possible\n" if $min_size <= $old_size && !$force;
unlink("$lnk.new");
symlink($min_size, "$lnk.new") or die "cannot create size symlink '$lnk.new'\n";
rename("$lnk.new", $lnk) or die "cannot create size symlink '$lnk'\n";;
}
sub role_cmd {
my ($cmd, $res) = @_;
my $pri = "$mars/resource-$res/primary";
@ -773,7 +794,7 @@ my %cmd_table =
"secondary" => \&primary_res,
"invalidate" => \&invalidate_res,
"invalidate-remote" => \&forbidden_cmd,
"resize" => \&nyi_cmd,
"resize" => \&resize_res,
"create-md" => \&senseless_cmd,
"get-gi" => \&ignore_cmd,
"show-gi" => \&ignore_cmd,