diff options
author | NeilBrown <neilb@suse.de> | 2013-08-27 16:44:13 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-08-27 16:45:00 +1000 |
commit | 260fa034ef7a4ff8b73068b48ac497edd5217491 (patch) | |
tree | 6a328502545c8f155b34c08c72f7023166991bce /drivers/char | |
parent | 7a0a5355cbc71efa430c3730ffbd67ae04abfe31 (diff) |
md: avoid deadlock when dirty buffers during md_stop.
When the last process closes /dev/mdX sync_blockdev will be called so
that all buffers get flushed.
So if it is then opened for the STOP_ARRAY ioctl to be sent there will
be nothing to flush.
However if we open /dev/mdX in order to send the STOP_ARRAY ioctl just
moments before some other process which was writing closes their file
descriptor, then there won't be a 'last close' and the buffers might
not get flushed.
So do_md_stop() calls sync_blockdev(). However at this point it is
holding ->reconfig_mutex. So if the array is currently 'clean' then
the writes from sync_blockdev() will not complete until the array
can be marked dirty and that won't happen until some other thread
can get ->reconfig_mutex. So we deadlock.
We need to move the sync_blockdev() call to before we take
->reconfig_mutex.
However then some other thread could open /dev/mdX and write to it
after we call sync_blockdev() and before we actually stop the array.
This can leave dirty data in the page cache which is awkward.
So introduce new flag MD_STILL_CLOSED. Set it before calling
sync_blockdev(), clear it if anyone does open the file, and abort the
STOP_ARRAY attempt if it gets set before we lock against further
opens.
It is still possible to get problems if you open /dev/mdX, write to
it, then issue the STOP_ARRAY ioctl. Just don't do that.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/char')
0 files changed, 0 insertions, 0 deletions