Federico Simoncelli has uploaded a new change for review.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
block: simplify zeroImgVolumes using threads
Change-Id: I665d863085842de8ff93c9aacf7c26277dfb031d Signed-off-by: Federico Simoncelli fsimonce@redhat.com --- M vdsm/storage/blockSD.py 1 file changed, 26 insertions(+), 72 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/30/35630/1
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py index 36078d0..daaa94f 100644 --- a/vdsm/storage/blockSD.py +++ b/vdsm/storage/blockSD.py @@ -22,7 +22,6 @@ import threading import logging import signal -import select import errno import re from StringIO import StringIO @@ -50,6 +49,7 @@ import resourceManager as rm import mount import supervdsm as svdsm +from threadLocal import vars import volume
STORAGE_DOMAIN_TAG = "RHAT_storage_domain" @@ -200,80 +200,34 @@ lvm.removeLVs(sdUUID, vols)
-def _zeroVolume(sdUUID, volUUID): - """Fill a block volume. - - This function requires an active LV. - """ - dm = lvm.lvDmDev(sdUUID, volUUID) - size = multipath.getDeviceSize(dm) # Bytes - # TODO: Change for zero 128 M chuncks and log. - # 128 M is the vdsm extent size default - BS = constants.MEGAB # 1024 ** 2 = 1 MiB - count = size / BS - cmd = [constants.EXT_DD, "oflag=%s" % misc.DIRECTFLAG, "if=/dev/zero", - "of=%s" % lvm.lvPath(sdUUID, volUUID), "bs=%s" % BS, - "count=%s" % count] - p = misc.execCmd(cmd, sync=False, nice=utils.NICENESS.HIGH, - ioclass=utils.IOCLASS.IDLE, deathSignal=signal.SIGKILL) - return p - - def zeroImgVolumes(sdUUID, imgUUID, volUUIDs): - ProcVol = namedtuple("ProcVol", "proc, vol") - # Put a sensible value for dd zeroing a 128 M or 1 G chunk and lvremove - # spent time. - ZEROING_TIMEOUT = 60000 # [miliseconds] - log.debug("sd: %s, LVs: %s, img: %s", sdUUID, volUUIDs, imgUUID) - # Following call to changelv is separate since setting rw permission on an - # LV fails if the LV is already set to the same value, hence we would not - # be able to differentiate between a real failure of deltag/addtag and one - # we would like to ignore (permission is the same) - try: - lvm.changelv(sdUUID, volUUIDs, ("--permission", "rw")) - except se.StorageException as e: - # Hope this only means that some volumes were already writable. - log.debug("Ignoring failed permission change: %s", e) - # blank the volumes. - zerofds = {} - poller = select.poll() - for volUUID in volUUIDs: - proc = _zeroVolume(sdUUID, volUUID) - fd = proc.stdout.fileno() - zerofds[fd] = ProcVol(proc, volUUID) - poller.register(fd, select.EPOLLHUP) + taskid = vars.task.id + aborting = vars.task.aborting
- # Wait until all the asyncs procs return - # Yes, this is a potentially infinite loop. Kill the vdsm task. - while zerofds: - fdevents = poller.poll(ZEROING_TIMEOUT) # [(fd, event)] - toDelete = [] - for fd, event in fdevents: - proc, vol = zerofds[fd] - if not proc.wait(0): - continue - else: - poller.unregister(fd) - zerofds.pop(fd) - if proc.returncode != 0: - log.error("zeroing %s/%s failed. Zero and remove this " - "volume manually. rc=%s %s", sdUUID, vol, - proc.returncode, proc.stderr.read(1000)) - else: - log.debug("%s/%s was zeroed and will be deleted", - sdUUID, volUUID) - toDelete.append(vol) - if toDelete: - try: - deleteVolumes(sdUUID, toDelete) - except se.CannotRemoveLogicalVolume: - # TODO: Add the list of removed fail volumes to the exception. - log.error("Remove failed for some of VG: %s zeroed volumes: " - "%s", sdUUID, toDelete, exc_info=True) + def zeroVolume(volUUID): + log.debug('starting to zero volume %s on domain %s for ' + 'task %s', volUUID, sdUUID, taskid) + try: + lvm.changelv(sdUUID, volUUIDs, ("--permission", "rw")) + except se.StorageException as e: + # We ignore the failure hoping that the volumes were + # already writable. + log.debug("Ignoring failed permission change: %s", e)
- log.debug("finished with VG:%s LVs: %s, img: %s", sdUUID, volUUIDs, - imgUUID) - return + path = lvm.lvPath(sdUUID, volUUID) + size = multipath.getDeviceSize(lvm.lvDmDev(sdUUID, volUUID)) + + try: + misc.ddWatchCopy("/dev/zero", path, aborting, size) + except Exception as e: + log.exception('zeroing operation failed') + raise se.VolumesZeroingError(path) + + deleteVolumes(sdUUID, volUUID) + log.debug('zeroing of volume %s on domain %s for task %s ' + 'completed successfully', volUUID, sdUUID, taskid) + + misc.tmap(zeroVolume, volUUIDs)
class VGTagMetadataRW(object):
oVirt Jenkins CI Server has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 1:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/12926/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/13878/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/13715/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 2:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/13748/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/12959/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/13911/ : FAILURE
oVirt Jenkins CI Server has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/13755/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/12966/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/13918/ : FAILURE
Dan Kenigsberg has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3: Code-Review-1
(1 comment)
http://gerrit.ovirt.org/#/c/35630/3/vdsm/storage/blockSD.py File vdsm/storage/blockSD.py:
Line 48: from storage_mailbox import MAILBOX_SIZE Line 49: import resourceManager as rm Line 50: import mount Line 51: import supervdsm as svdsm Line 52: from threadLocal import vars The unloved threadLocal module is important to make zeroImgVolumes abortable; it should not appear in this patch, that aims only to simplify the code by using threads. Line 53: import volume Line 54: Line 55: STORAGE_DOMAIN_TAG = "RHAT_storage_domain" Line 56: STORAGE_UNREADY_DOMAIN_TAG = STORAGE_DOMAIN_TAG + "_UNREADY"
Federico Simoncelli has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3:
(1 comment)
http://gerrit.ovirt.org/#/c/35630/3/vdsm/storage/blockSD.py File vdsm/storage/blockSD.py:
Line 48: from storage_mailbox import MAILBOX_SIZE Line 49: import resourceManager as rm Line 50: import mount Line 51: import supervdsm as svdsm Line 52: from threadLocal import vars
The unloved threadLocal module is important to make zeroImgVolumes abortabl
Yeah... actually I use it for logging purposes... to tie the thread to the task uuid.
If I take out the "abortability" the threadLocal import remains anyway. Do you still want to split it? Line 53: import volume Line 54: Line 55: STORAGE_DOMAIN_TAG = "RHAT_storage_domain" Line 56: STORAGE_UNREADY_DOMAIN_TAG = STORAGE_DOMAIN_TAG + "_UNREADY"
Dan Kenigsberg has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3:
(1 comment)
http://gerrit.ovirt.org/#/c/35630/3/vdsm/storage/blockSD.py File vdsm/storage/blockSD.py:
Line 48: from storage_mailbox import MAILBOX_SIZE Line 49: import resourceManager as rm Line 50: import mount Line 51: import supervdsm as svdsm Line 52: from threadLocal import vars
Yeah... actually I use it for logging purposes... to tie the thread to the
I'm pretty sure that we agreed to split this patch. One patch should simplify the current code (as the commit message says), and a followup would make at fully-fledged task out of it. didn't we? Line 53: import volume Line 54: Line 55: STORAGE_DOMAIN_TAG = "RHAT_storage_domain" Line 56: STORAGE_UNREADY_DOMAIN_TAG = STORAGE_DOMAIN_TAG + "_UNREADY"
Dan Kenigsberg has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3: Code-Review+2
Nir Soffer has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3: Code-Review-1
Don't we have enough threads?!
What is wrong with the current code? This code is exactly what we should be using everywhere in vdsm instead of starting zillions of threads.
For example, we could monitor all storage domains using *one* threads, waiting on multiple dd processes.
Nir Soffer has posted comments on this change.
Change subject: block: simplify zeroImgVolumes using threads ......................................................................
Patch Set 3:
(4 comments)
https://gerrit.ovirt.org/#/c/35630/3/vdsm/storage/blockSD.py File vdsm/storage/blockSD.py:
Line 207: try: Line 208: lvm.changelv(sdUUID, volUUIDs, ("--permission", "rw")) Line 209: except se.StorageException as e: Line 210: # We ignore the failure hoping that the volumes were Line 211: # already writable. The original comment was better. Line 212: log.debug('ignoring failed permission change: %s', e) Line 213: Line 214: def zeroVolume(volUUID): Line 215: log.debug('starting to zero volume %s on domain %s for '
Line 218: path = lvm.lvPath(sdUUID, volUUID) Line 219: size = multipath.getDeviceSize(lvm.lvDmDev(sdUUID, volUUID)) Line 220: Line 221: try: Line 222: misc.ddWatchCopy("/dev/zero", path, aborting, size) Previously we use specific dd command for this operation, that seems to do the write thing. Now you call ddWatchCopy, which is 10 times more complex, running dd twice and trying to support any odd image size, while our images are always in 128MB chunks.
I don't feel confident with using ddWatchCopy, and prefer the current direct and simple code. Line 223: except Exception: Line 224: log.exception('zeroing operation failed') Line 225: raise se.VolumesZeroingError(path) Line 226:
Line 223: except Exception: Line 224: log.exception('zeroing operation failed') Line 225: raise se.VolumesZeroingError(path) Line 226: Line 227: deleteVolumes(sdUUID, volUUID) We can have 100-150 threads running this in the same time - does it make sense to run concurrent deleteVolumes like this? Line 228: log.debug('zeroing of volume %s on domain %s for task %s ' Line 229: 'completed successfully', volUUID, sdUUID, taskid) Line 230: Line 231: misc.tmap(zeroVolume, volUUIDs)
Line 227: deleteVolumes(sdUUID, volUUID) Line 228: log.debug('zeroing of volume %s on domain %s for task %s ' Line 229: 'completed successfully', volUUID, sdUUID, taskid) Line 230: Line 231: misc.tmap(zeroVolume, volUUIDs) We can use itmap to get one uuid of zeroed and discarded volume and delete it. This is more similar to the old code, running one deleteVolumes operation per vdsm task at the same time. Line 232: Line 233: Line 234: class VGTagMetadataRW(object): Line 235: log = logging.getLogger("Storage.Metadata.VGTagMetadataRW")
vdsm-patches@lists.fedorahosted.org