[dm-devel] [PATCH 36/57] libmultipath: pass in 'cookie' as argument for dm_addmap()
Hannes Reinecke
hare at suse.de
Tue May 3 09:31:19 UTC 2016
On 05/03/2016 12:23 AM, Benjamin Marzinski wrote:
> On Wed, Apr 27, 2016 at 01:10:37PM +0200, Hannes Reinecke wrote:
>> Instead of generating the cookie internally we should be
>> passing in the cookie to dm_addmap().
>
> These look like they could actually cause problems. With
> dm_addmap_create and dm_addmap_reload, you could be in a situation where
> you get a cookie back on your first call to dm_task_set_cookie, wait on
> it, so that cookie is no longer in use, and then use that same cookie
> id again. It's possible that after you first waited on the cookie,
> someone else could have been given that cookie id (without looking into
> the dm cookie code more, I'm not sure how likely this is). If that is
> so, the second call to dm_addmap would be adding its command to the list
> of other commands for that cookie (since you are allowed to use a cookie
> for multiple dm commands). Calling dm_udev_wait would make it wait of
> all the commands.
>
> We can use a cookie multiple times and then wait on it once. But we
> can't keep reusing the cookie after we've waited on it, because someone
> else could be using the same cookie.
>
> -Ben
>
>>
>> Signed-off-by: Hannes Reinecke <hare at suse.de>
>> ---
>> libmultipath/devmapper.c | 23 ++++++++++++++---------
>> 1 file changed, 14 insertions(+), 9 deletions(-)
>>
>> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
>> index e6156f7..a96cc0e 100644
>> --- a/libmultipath/devmapper.c
>> +++ b/libmultipath/devmapper.c
>> @@ -274,11 +274,10 @@ dm_device_remove (const char *name, int needsync, int deferred_remove) {
>>
>> extern int
>> dm_addmap (int task, const char *target, struct multipath *mpp,
>> - char * params, int ro) {
>> + char * params, int ro, uint32_t *cookie) {
>> int r = 0;
>> struct dm_task *dmt;
>> char *prefixed_uuid = NULL;
>> - uint32_t cookie = 0;
>>
>> if (!(dmt = dm_task_create (task)))
>> return 0;
>> @@ -319,18 +318,18 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
>> dm_task_no_open_count(dmt);
>>
>> if (task == DM_DEVICE_CREATE &&
>> - !dm_task_set_cookie(dmt, &cookie,
>> + !dm_task_set_cookie(dmt, cookie,
>> DM_UDEV_DISABLE_LIBRARY_FALLBACK)) {
>> - dm_udev_complete(cookie);
>> + dm_udev_complete(*cookie);
>> goto freeout;
>> }
>> r = dm_task_run (dmt);
>>
>> if (task == DM_DEVICE_CREATE) {
>> if (!r)
>> - dm_udev_complete(cookie);
>> + dm_udev_complete(*cookie);
>> else
>> - dm_udev_wait(cookie);
>> + dm_udev_wait(*cookie);
>> }
>> freeout:
>> if (prefixed_uuid)
>> @@ -345,11 +344,13 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
>> extern int
>> dm_addmap_create (struct multipath *mpp, char * params) {
>> int ro;
>> + uint32_t cookie = 0;
>>
>> for (ro = 0; ro <= 1; ro++) {
>> int err;
>>
>> - if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro))
>> + if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH,
>> + mpp, params, ro, &cookie))
>> return 1;
>> /*
>> * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
>> @@ -374,11 +375,15 @@ dm_addmap_create (struct multipath *mpp, char * params) {
>>
>> extern int
>> dm_addmap_reload (struct multipath *mpp, char *params) {
>> - if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, ADDMAP_RW))
>> + uint32_t cookie = 0;
>> +
>> + if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params,
>> + ADDMAP_RW, &cookie))
>> return 1;
>> if (errno != EROFS)
>> return 0;
>> - return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, ADDMAP_RO);
>> + return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params,
>> + ADDMAP_RO, &cookie);
>> }
>>
>> extern int
>> --
>> 2.6.6
Looking closer, this entire section looks fishy.
>From the lvm source code I couldn't figure out _how_ we could get
into a situation where dm_task_run() would return 0 (ie no error
occurred), but errno would be set to EROFS.
_If_ we could rely on dm_task_run() to return an error here this
whole issue wouldn't occur, as we haven't actually waited on the
cookie, and the second dm_addmap() call would be legit, even with
the same cookie.
Checking with git how the above came about.
Cheers,
Hannes
--
Dr. Hannes Reinecke Teamlead Storage & Networking
hare at suse.de +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
More information about the dm-devel
mailing list