lo_refcnt is only incremented in lo_open and decremented in lo_release,
and thus protected by open_mutex. Only take lo_mutex when lo_release
actually takes action for the final release.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Darrick J. Wong <djwong@kernel.org>
{
struct loop_device *lo = disk->private_data;
- mutex_lock(&lo->lo_mutex);
- if (atomic_dec_return(&lo->lo_refcnt))
- goto out_unlock;
+ /*
+ * Note: this requires disk->open_mutex to protect against races
+ * with lo_open.
+ */
+ if (!atomic_dec_and_test(&lo->lo_refcnt))
+ return;
+ mutex_lock(&lo->lo_mutex);
if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
if (lo->lo_state != Lo_bound)
goto out_unlock;