[dm-devel] [PATCH 36/57] libmultipath: pass in 'cookie' as argument for dm_addmap()
Benjamin Marzinski
bmarzins at redhat.com
Tue May 3 14:39:40 UTC 2016
On Tue, May 03, 2016 at 11:31:19AM +0200, Hannes Reinecke wrote:
> 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.
dm_task_run returns a 0 on error, not success.
-Ben
>
> _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