On Thu, Aug 02, 2018 at 05:29:12PM +0800, Anand Jain wrote:
> 
> 
> On 08/01/2018 10:29 PM, David Sterba wrote:
> > On Thu, Jul 26, 2018 at 02:53:32PM +0800, Anand Jain wrote:
> >> From: Anand Jain <anand.j...@oracle.com>
> >>
> >> %fs_devices can be free-ed by btrfs_free_stale_devices() when the
> >> close_fs_devices() drops fs_devices::opened to zero, but close_fs_devices
> >> tries to access the %fs_devices again without the device_list_mutex.
> >>
> >> Fix this by bringing the %fs_devices access with in the device_list_mutex.
> > 
> > AFAICS this cannot happen anymore because the two calls are serialized
> > by the uuid_mutex. But this was not the case when syzbot reported the
> > problem where your patch would apply.
> > 
> > The parallell access to opened and device list cannot happen when:
> > 
> > * btrfs_scan_one_device that wants to call btrfs_free_stale_devices
> > * btrfs_close_devices calls close_fs_devices
> > 
> > Fixed by the series:
> > 
> > btrfs: lift uuid_mutex to callers of btrfs_scan_one_device
> > btrfs: lift uuid_mutex to callers of btrfs_open_devices
> > btrfs: lift uuid_mutex to callers of btrfs_parse_early_options
> > btrfs: reorder initialization before the mount locks uuid_mutex
> > btrfs: fix mount and ioctl device scan ioctl race
> > 
> > If there's a race I don't see, please describe in more detail.
> 
>   Right. There is no race with the uuid_mutex patches as above.
> 
>   And I just found this- can we make close be consistent with its
>   open part.
>   btrfs_open_devices() hold device_list_mutex before the update to
>   fs_devices::opened. So close_fs_device() could do the same, and be
>   theoretically correct.

Or it can be the other way around, to push the device_list_mutex only
around the list_sort and open_fs_devices like:

--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1144,15 +1144,15 @@ int btrfs_open_devices(struct btrfs_fs_devices 
*fs_devices,
 
        lockdep_assert_held(&uuid_mutex);
 
-       mutex_lock(&fs_devices->device_list_mutex);
        if (fs_devices->opened) {
                fs_devices->opened++;
                ret = 0;
        } else {
+               mutex_lock(&fs_devices->device_list_mutex);
                list_sort(NULL, &fs_devices->devices, devid_cmp);
                ret = open_fs_devices(fs_devices, flags, holder);
+               mutex_unlock(&fs_devices->device_list_mutex);
        }
-       mutex_unlock(&fs_devices->device_list_mutex);
 
        return ret;
 }
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to