diff --git a/mars_if.c b/mars_if.c index c5b9a1b1..6a651da8 100644 --- a/mars_if.c +++ b/mars_if.c @@ -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); diff --git a/mars_if.h b/mars_if.h index 4da3af13..87b82f64 100644 --- a/mars_if.h +++ b/mars_if.h @@ -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; diff --git a/sy_old/mars_light.c b/sy_old/mars_light.c index cdd7e9f2..776914a9 100644 --- a/sy_old/mars_light.c +++ b/sy_old/mars_light.c @@ -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, diff --git a/userspace/marsadm b/userspace/marsadm index 6ff3f653..b70b7ec9 100644 --- a/userspace/marsadm +++ b/userspace/marsadm @@ -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,