提交 96a02703 编写于 作者: M Michal Privoznik

sanlock: Retry after EINPROGRESS

It may take some time for sanlock to add a lockspace. And if user
restart libvirtd service meanwhile, the fresh daemon can fail adding
the same lockspace with EINPROGRESS. Recent sanlock has
sanlock_inq_lockspace() function which should block until lockspace
changes state. If we are building against older sanlock we should
retry a few times before claiming an error. This issue can be easily
reproduced:

for i in {1..1000} ; do echo $i; service libvirtd restart; sleep 2; done
20
Stopping libvirtd daemon:                                  [FAILED]
Starting libvirtd daemon:                                  [  OK  ]
21
Stopping libvirtd daemon:                                  [  OK  ]
Starting libvirtd daemon:                                  [  OK  ]
22
Stopping libvirtd daemon:                                  [  OK  ]
Starting libvirtd daemon:                                  [  OK  ]

 error : virLockManagerSanlockSetupLockspace:334 : Unable to add
 lockspace /var/lib/libvirt/sanlock/__LIBVIRT__DISKS__: Operation now in
 progress
上级 58110b48
......@@ -1223,6 +1223,13 @@ if test "x$with_sanlock" != "xno"; then
AC_DEFINE_UNQUOTED([HAVE_SANLOCK_KILLPATH], 1,
[whether Sanlock supports sanlock_killpath])
fi
AC_CHECK_LIB([sanlock_client], [sanlock_inq_lockspace],
[sanlock_inq_lockspace=yes], [sanlock_inq_lockspace=no])
if test "x$sanlock_inq_lockspace" = "xyes" ; then
AC_DEFINE_UNQUOTED([HAVE_SANLOCK_INQ_LOCKSPACE], 1,
[whether sanlock supports sanlock_inq_lockspace])
fi
fi
fi
AM_CONDITIONAL([HAVE_SANLOCK], [test "x$with_sanlock" = "xyes"])
......
......@@ -184,6 +184,11 @@ static int virLockManagerSanlockLoadConfig(const char *configFile)
return 0;
}
/* How much ms sleep before retrying to add a lockspace? */
#define LOCKSPACE_SLEEP 100
/* How many times try adding a lockspace? */
#define LOCKSPACE_RETRIES 10
static int virLockManagerSanlockSetupLockspace(void)
{
int fd = -1;
......@@ -192,6 +197,9 @@ static int virLockManagerSanlockSetupLockspace(void)
struct sanlk_lockspace ls;
char *path = NULL;
char *dir = NULL;
#ifndef HAVE_SANLOCK_INQ_LOCKSPACE
int retries = LOCKSPACE_RETRIES;
#endif
if (virAsprintf(&path, "%s/%s",
driver->autoDiskLeasePath,
......@@ -318,11 +326,32 @@ static int virLockManagerSanlockSetupLockspace(void)
}
ls.host_id = driver->hostID;
/* Stage 2: Try to register the lockspace with the daemon.
* If the lockspace is already registered, we should get EEXIST back
* in which case we can just carry on with life
/* Stage 2: Try to register the lockspace with the daemon. If the lockspace
* is already registered, we should get EEXIST back in which case we can
* just carry on with life. If EINPROGRESS is returned, we have two options:
* either call a sanlock API that blocks us until lockspace changes state,
* or we can fallback to polling.
*/
#ifndef HAVE_SANLOCK_INQ_LOCKSPACE
retry:
#endif
if ((rv = sanlock_add_lockspace(&ls, 0)) < 0) {
if (-rv == EINPROGRESS) {
#ifdef HAVE_SANLOCK_INQ_LOCKSPACE
/* we have this function which blocks until lockspace change the
* state. It returns 0 if lockspace has been added, -ENOENT if it
* hasn't. XXX should we goto retry? */
VIR_DEBUG("Inquiring lockspace");
rv = sanlock_inq_lockspace(&ls, SANLK_INQ_WAIT);
#else
/* fall back to polling */
if (retries--) {
usleep(LOCKSPACE_SLEEP * 1000);
VIR_DEBUG("Retrying to add lockspace (left %d)", retries);
goto retry;
}
#endif
}
if (-rv != EEXIST) {
if (rv <= -200)
virReportError(VIR_ERR_INTERNAL_ERROR,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册