Merge lp:~raharper/curtin/trunk.bcache-toctou-v2 into lp:~curtin-dev/curtin/trunk

Proposed by Ryan Harper
Status: Merged
Approved by: Scott Moser
Approved revision: 542
Merged at revision: 540
Proposed branch: lp:~raharper/curtin/trunk.bcache-toctou-v2
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 65 lines (+16/-14)
2 files modified
curtin/block/clear_holders.py (+10/-8)
tests/unittests/test_clear_holders.py (+6/-6)
To merge this branch: bzr merge lp:~raharper/curtin/trunk.bcache-toctou-v2
Reviewer Review Type Date Requested Status
Scott Moser (community) Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+333095@code.launchpad.net

Description of the change

clear_holders: bcache log IO/OS exceptions but do not raise

While stopping bcache devices, curtin races with the kernel w.r.t how
quickly it removes the bcache device (and the sysfs tree related).
The result is that as curtin attempts to write "1" into the sysfs tree
of bcache device to stop it, the range of errors changes depending on
when we race with the kernel asynchronously removing the sysfs path.
Therefore we log the exception errno we got but do not re-raise. The
the calling process is watching whether the same sysfs path is being
removed; if the bcache device fails to go away then curtin will have a
log of the exceptions to debug.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

Thanks Ryan

review: Approve
Revision history for this message
Ryan Harper (raharper) wrote :

vmtest on jenkins approves as well

https://jenkins.ubuntu.com/server/view/curtin/job/curtin-vmtest-devel-debug/17/console

----------------------------------------------------------------------
Ran 2219 tests in 8642.899s

OK (SKIP=162)
Thu, 02 Nov 2017 16:43:35 +0000: vmtest end [0] in 8646s

Merging to trunk now.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/block/clear_holders.py'
2--- curtin/block/clear_holders.py 2017-10-23 16:49:46 +0000
3+++ curtin/block/clear_holders.py 2017-11-01 20:23:47 +0000
4@@ -99,14 +99,16 @@
5 try:
6 util.write_file(bcache_stop, '1', mode=None)
7 except (IOError, OSError) as e:
8- # Note: if we get a write failure and the exception is that the
9- # file is not found; we log this expected behavior; any other
10- # exception is raised
11- if e.errno == errno.ENOENT:
12- LOG.debug('bcache stop file %s missing, device removed: %s',
13- bcache_stop, e)
14- else:
15- raise e
16+ # Note: if we get any exceptions in the above exception classes
17+ # it is a result of attempting to write "1" into the sysfs path
18+ # The range of errors changes depending on when we race with
19+ # the kernel asynchronously removing the sysfs path. Therefore
20+ # we log the exception errno we got, but do not re-raise as
21+ # the calling process is watching whether the same sysfs path
22+ # is being removed; if it fails to go away then we'll have
23+ # a log of the exceptions to debug.
24+ LOG.debug('Error writing to bcache stop file %s, device removed: %s',
25+ bcache_stop, e)
26
27
28 def shutdown_bcache(device):
29
30=== modified file 'tests/unittests/test_clear_holders.py'
31--- tests/unittests/test_clear_holders.py 2017-10-13 17:48:29 +0000
32+++ tests/unittests/test_clear_holders.py 2017-11-01 20:23:47 +0000
33@@ -580,11 +580,11 @@
34
35 @mock.patch('curtin.block.clear_holders.util.write_file')
36 def test_maybe_stop_bcache_device_raises_errors(self, m_write_file):
37- """Unexpected exceptions are raised by maybe_stop_bcache_device."""
38- m_write_file.side_effect = OSError(errno.EAGAIN, 'Unexpected errno')
39- with self.assertRaises(OSError) as cm:
40+ """Non-IO/OS exceptions are raised by maybe_stop_bcache_device."""
41+ m_write_file.side_effect = ValueError('Crazy Value Error')
42+ with self.assertRaises(ValueError) as cm:
43 clear_holders.maybe_stop_bcache_device('does/not/matter')
44- self.assertEqual('[Errno 11] Unexpected errno', str(cm.exception))
45+ self.assertEqual('Crazy Value Error', str(cm.exception))
46 self.assertEqual(
47 mock.call('does/not/matter/stop', '1', mode=None),
48 m_write_file.call_args)
49@@ -597,7 +597,7 @@
50 m_write_file.side_effect = OSError(errno.ENOENT, 'Expected oserror')
51 clear_holders.maybe_stop_bcache_device('does/not/matter')
52 self.assertEqual(
53- 'bcache stop file %s missing, device removed: %s',
54+ 'Error writing to bcache stop file %s, device removed: %s',
55 m_log.debug.call_args[0][0])
56 self.assertEqual('does/not/matter/stop', m_log.debug.call_args[0][1])
57
58@@ -609,7 +609,7 @@
59 m_write_file.side_effect = IOError(errno.ENOENT, 'Expected ioerror')
60 clear_holders.maybe_stop_bcache_device('does/not/matter')
61 self.assertEqual(
62- 'bcache stop file %s missing, device removed: %s',
63+ 'Error writing to bcache stop file %s, device removed: %s',
64 m_log.debug.call_args[0][0])
65 self.assertEqual('does/not/matter/stop', m_log.debug.call_args[0][1])
66

Subscribers

People subscribed via source and target branches