1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Fix possible overflow of size if %FREE or %VG is used.

https://bugzilla.redhat.com/show_bug.cgi?id=737087
This commit is contained in:
Milan Broz 2011-09-15 15:26:40 +00:00
parent 89880365fc
commit b18e1fd50e
6 changed files with 59 additions and 11 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.89 -
==================================
Fix possible overflow of size if %FREE or %VG is used.
Fix vgchange activation of snapshot with virtual origin.
Activate virtual snapshot origin exclusively (only on local node in cluster).
Fix lv_mirror_count to handle mirrored stripes properly.

40
test/t-lvcreate-large.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
#
# 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 General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# 'Exercise some lvcreate diagnostics'
. lib/test
aux prepare_vg 4
lvcreate -s -l 100%FREE -n $lv $vg --virtualsize 1024T
#FIXME this should be 1024T
#check lv_field $vg/$lv size "128.00m"
aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]'
pvcreate $DM_DEV_DIR/$vg/$lv
vgcreate $vg1 $DM_DEV_DIR/$vg/$lv
lvcreate -l 100%FREE -n $lv1 $vg1
check lv_field $vg1/$lv1 size "1024.00t"
lvresize -f -l 72%VG $vg1/$lv1
check lv_field $vg1/$lv1 size "737.28t"
lvremove -ff $vg1/$lv1
lvcreate -l 100%VG -n $lv1 $vg1
check lv_field $vg1/$lv1 size "1024.00t"
lvresize -f -l 72%VG $vg1/$lv1
check lv_field $vg1/$lv1 size "737.28t"
lvremove -ff $vg1/$lv1
lvremove -ff $vg/$lv

View File

@ -250,17 +250,17 @@ static int _update_extents_params(struct volume_group *vg,
switch(lcp->percent) {
case PERCENT_VG:
lp->extents = lp->extents * vg->extent_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->extent_count);
break;
case PERCENT_FREE:
lp->extents = lp->extents * vg->free_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->free_count);
break;
case PERCENT_PVS:
if (!lcp->pv_count)
lp->extents = lp->extents * vg->extent_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->extent_count);
else {
pv_extent_count = pv_list_extents_free(lp->pvh);
lp->extents = lp->extents * pv_extent_count / 100;
lp->extents = percent_of_extents(lp->extents, pv_extent_count);
}
break;
case PERCENT_LV:
@ -278,7 +278,7 @@ static int _update_extents_params(struct volume_group *vg,
log_error(INTERNAL_ERROR "Couldn't find origin volume.");
return 0;
}
lp->extents = lp->extents * origin->le_count / 100;
lp->extents = percent_of_extents(lp->extents, origin->le_count);
break;
case PERCENT_NONE:
break;

View File

@ -433,27 +433,27 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
switch(lp->percent) {
case PERCENT_VG:
lp->extents = lp->extents * vg->extent_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->extent_count);
break;
case PERCENT_FREE:
lp->extents = lp->extents * vg->free_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->free_count);
break;
case PERCENT_LV:
lp->extents = lp->extents * lv->le_count / 100;
lp->extents = percent_of_extents(lp->extents, lv->le_count);
break;
case PERCENT_PVS:
if (lp->argc) {
pv_extent_count = pv_list_extents_free(pvh);
lp->extents = lp->extents * pv_extent_count / 100;
lp->extents = percent_of_extents(lp->extents, pv_extent_count);
} else
lp->extents = lp->extents * vg->extent_count / 100;
lp->extents = percent_of_extents(lp->extents, vg->extent_count);
break;
case PERCENT_ORIGIN:
if (!lv_is_cow(lv)) {
log_error("Specified LV does not have an origin LV.");
return EINVALID_CMD_LINE;
}
lp->extents = lp->extents * origin_from_cow(lv)->le_count / 100;
lp->extents = percent_of_extents(lp->extents, origin_from_cow(lv)->le_count);
break;
case PERCENT_NONE:
break;

View File

@ -1623,3 +1623,9 @@ int change_tag(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
/* Return percents of extents and avoid overflow */
uint32_t percent_of_extents(uint32_t percents, uint32_t count)
{
return (uint32_t)((uint64_t)percents * (uint64_t)count / 100);
}

View File

@ -181,4 +181,5 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv, unsigned
int mirror_remove_missing(struct cmd_context *cmd,
struct logical_volume *lv, int force);
uint32_t percent_of_extents(uint32_t percents, uint32_t count);
#endif