mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
writecache: move code into new file
put writecache specific code in writecache_manip.c should be no functional change
This commit is contained in:
parent
56aadd7fe2
commit
76dd9b2b51
@ -66,6 +66,7 @@ SOURCES =\
|
||||
locking/locking.c \
|
||||
log/log.c \
|
||||
metadata/cache_manip.c \
|
||||
metadata/writecache_manip.c \
|
||||
metadata/lv.c \
|
||||
metadata/lv_manip.c \
|
||||
metadata/merge.c \
|
||||
|
@ -1282,6 +1282,7 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
|
||||
int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean);
|
||||
int lv_cache_remove(struct logical_volume *cache_lv);
|
||||
int lv_detach_cache_vol(struct logical_volume *cache_lv, int noflush);
|
||||
int lv_detach_writecache_cachevol(struct logical_volume *cache_lv, int noflush);
|
||||
int wipe_cache_pool(struct logical_volume *cache_pool_lv);
|
||||
/* -- metadata/cache_manip.c */
|
||||
|
||||
|
@ -5166,30 +5166,3 @@ struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
int lv_is_writecache_origin(const struct logical_volume *lv)
|
||||
{
|
||||
struct seg_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
|
||||
if (!sl->seg || !sl->seg->lv || !sl->seg->origin)
|
||||
continue;
|
||||
if (lv_is_writecache(sl->seg->lv) && (sl->seg->origin == lv))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lv_is_writecache_cachevol(const struct logical_volume *lv)
|
||||
{
|
||||
struct seg_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
|
||||
if (!sl->seg || !sl->seg->lv || !sl->seg->writecache)
|
||||
continue;
|
||||
if (lv_is_writecache(sl->seg->lv) && (sl->seg->writecache == lv))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
201
lib/metadata/writecache_manip.c
Normal file
201
lib/metadata/writecache_manip.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/locking/locking.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "lib/metadata/segtype.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/config/defaults.h"
|
||||
#include "lib/metadata/lv_alloc.h"
|
||||
#include "lib/misc/lvm-signal.h"
|
||||
#include "lib/activate/dev_manager.h"
|
||||
|
||||
int lv_is_writecache_origin(const struct logical_volume *lv)
|
||||
{
|
||||
struct seg_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
|
||||
if (!sl->seg || !sl->seg->lv || !sl->seg->origin)
|
||||
continue;
|
||||
if (lv_is_writecache(sl->seg->lv) && (sl->seg->origin == lv))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lv_is_writecache_cachevol(const struct logical_volume *lv)
|
||||
{
|
||||
struct seg_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
|
||||
if (!sl->seg || !sl->seg->lv || !sl->seg->writecache)
|
||||
continue;
|
||||
if (lv_is_writecache(sl->seg->lv) && (sl->seg->writecache == lv))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lv_writecache_detach(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct logical_volume *lv_fast)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
struct logical_volume *origin;
|
||||
|
||||
if (!seg_is_writecache(seg)) {
|
||||
log_error("LV %s segment is not writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!seg->writecache) {
|
||||
log_error("LV %s writecache segment has no writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(origin = seg_lv(seg, 0))) {
|
||||
log_error("LV %s writecache segment has no origin", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!remove_seg_from_segs_using_this_lv(seg->writecache, seg))
|
||||
return_0;
|
||||
|
||||
lv_set_visible(seg->writecache);
|
||||
|
||||
lv->status &= ~WRITECACHE;
|
||||
seg->writecache = NULL;
|
||||
|
||||
lv_fast->status &= ~LV_CACHE_VOL;
|
||||
|
||||
if (!remove_layer_from_lv(lv, origin))
|
||||
return_0;
|
||||
|
||||
if (!lv_remove(origin))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_writecache_kernel_error(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
uint32_t *kernel_error)
|
||||
{
|
||||
struct lv_with_info_and_seg_status status;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.seg_status.type = SEG_STATUS_NONE;
|
||||
|
||||
status.seg_status.seg = first_seg(lv);
|
||||
|
||||
/* FIXME: why reporter_pool? */
|
||||
if (!(status.seg_status.mem = dm_pool_create("reporter_pool", 1024))) {
|
||||
log_error("Failed to get mem for LV status.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
|
||||
log_error("Failed to get device mapper status for %s", display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!status.info.exists) {
|
||||
log_error("No device mapper info exists for %s", display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (status.seg_status.type != SEG_STATUS_WRITECACHE) {
|
||||
log_error("Invalid device mapper status type (%d) for %s",
|
||||
(uint32_t)status.seg_status.type, display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*kernel_error = status.seg_status.writecache->error;
|
||||
|
||||
dm_pool_destroy(status.seg_status.mem);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
dm_pool_destroy(status.seg_status.mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lv_detach_writecache_cachevol(struct logical_volume *lv, int noflush)
|
||||
{
|
||||
struct cmd_context *cmd = lv->vg->cmd;
|
||||
struct logical_volume *lv_fast;
|
||||
uint32_t kernel_error = 0;
|
||||
|
||||
lv_fast = first_seg(lv)->writecache;
|
||||
|
||||
if (noflush)
|
||||
goto detach;
|
||||
|
||||
/*
|
||||
* Activate LV internally since the LV needs to be active to flush.
|
||||
* LV_TEMPORARY should keep the LV from being exposed to the user
|
||||
* and being accessed.
|
||||
*/
|
||||
|
||||
lv->status |= LV_TEMPORARY;
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate LV %s for flushing writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sync_local_dev_names(cmd)) {
|
||||
log_error("Failed to sync local devices before detaching writecache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_writecache_message(lv, "flush")) {
|
||||
log_error("Failed to flush writecache for %s.", display_lvname(lv));
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_get_writecache_kernel_error(cmd, lv, &kernel_error)) {
|
||||
log_error("Failed to get writecache error status for %s.", display_lvname(lv));
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kernel_error) {
|
||||
log_error("Failed to flush writecache (error %u) for %s.", kernel_error, display_lvname(lv));
|
||||
deactivate_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Failed to deactivate LV %s for detaching writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->status &= ~LV_TEMPORARY;
|
||||
|
||||
detach:
|
||||
if (!_lv_writecache_detach(cmd, lv, lv_fast)) {
|
||||
log_error("Failed to detach writecache from %s", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -5237,94 +5237,11 @@ int lvconvert_to_vdopool_param_cmd(struct cmd_context *cmd, int argc, char **arg
|
||||
NULL, NULL, &_lvconvert_to_vdopool_single);
|
||||
}
|
||||
|
||||
static int _lv_writecache_detach(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct logical_volume *lv_fast)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
struct logical_volume *origin;
|
||||
|
||||
if (!seg_is_writecache(seg)) {
|
||||
log_error("LV %s segment is not writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!seg->writecache) {
|
||||
log_error("LV %s writecache segment has no writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(origin = seg_lv(seg, 0))) {
|
||||
log_error("LV %s writecache segment has no origin", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!remove_seg_from_segs_using_this_lv(seg->writecache, seg))
|
||||
return_0;
|
||||
|
||||
lv_set_visible(seg->writecache);
|
||||
|
||||
lv->status &= ~WRITECACHE;
|
||||
seg->writecache = NULL;
|
||||
|
||||
lv_fast->status &= ~LV_CACHE_VOL;
|
||||
|
||||
if (!remove_layer_from_lv(lv, origin))
|
||||
return_0;
|
||||
|
||||
if (!lv_remove(origin))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_writecache_kernel_error(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
uint32_t *kernel_error)
|
||||
{
|
||||
struct lv_with_info_and_seg_status status;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.seg_status.type = SEG_STATUS_NONE;
|
||||
|
||||
status.seg_status.seg = first_seg(lv);
|
||||
|
||||
/* FIXME: why reporter_pool? */
|
||||
if (!(status.seg_status.mem = dm_pool_create("reporter_pool", 1024))) {
|
||||
log_error("Failed to get mem for LV status.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
|
||||
log_error("Failed to get device mapper status for %s", display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!status.info.exists) {
|
||||
log_error("No device mapper info exists for %s", display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (status.seg_status.type != SEG_STATUS_WRITECACHE) {
|
||||
log_error("Invalid device mapper status type (%d) for %s",
|
||||
(uint32_t)status.seg_status.type, display_lvname(lv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*kernel_error = status.seg_status.writecache->error;
|
||||
|
||||
dm_pool_destroy(status.seg_status.mem);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
dm_pool_destroy(status.seg_status.mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lvconvert_detach_writecache(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct logical_volume *lv_fast)
|
||||
{
|
||||
uint32_t kernel_error = 0;
|
||||
int noflush = 0;
|
||||
|
||||
/*
|
||||
* LV must be inactive externally before detaching cache.
|
||||
@ -5354,61 +5271,12 @@ static int _lvconvert_detach_writecache(struct cmd_context *cmd,
|
||||
log_error("Conversion aborted.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
goto detach;
|
||||
|
||||
noflush = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate LV internally since the LV needs to be active to flush.
|
||||
* LV_TEMPORARY should keep the LV from being exposed to the user
|
||||
* and being accessed.
|
||||
*/
|
||||
|
||||
lv->status |= LV_TEMPORARY;
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate LV %s for flushing.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sync_local_dev_names(cmd)) {
|
||||
log_error("Failed to sync local devices before detaching LV %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_writecache_message(lv, "flush")) {
|
||||
log_error("Failed to flush writecache for %s.", display_lvname(lv));
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_get_writecache_kernel_error(cmd, lv, &kernel_error)) {
|
||||
log_error("Failed to get writecache error status for %s.", display_lvname(lv));
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kernel_error) {
|
||||
log_error("Failed to flush writecache (error %u) for %s.", kernel_error, display_lvname(lv));
|
||||
deactivate_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Failed to deactivate LV %s for detaching writecache.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->status &= ~LV_TEMPORARY;
|
||||
|
||||
detach:
|
||||
if (!_lv_writecache_detach(cmd, lv, lv_fast)) {
|
||||
log_error("Failed to detach writecache from %s", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
if (!lv_detach_writecache_cachevol(lv, noflush))
|
||||
return_0;
|
||||
|
||||
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
|
||||
return_0;
|
||||
|
Loading…
Reference in New Issue
Block a user