mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 18:54:13 +08:00
mdbx-posix: checking for file removal during LCK-seizing.
Change-Id: I7626ceda62fc4dac86323bec4194ae46bc19d9d3
This commit is contained in:
parent
ccb45730f2
commit
e3d328621e
@ -220,6 +220,65 @@ MDBX_INTERNAL_FUNC int mdbx_ipclock_destroy(mdbx_ipclock_t *ipc) {
|
|||||||
}
|
}
|
||||||
#endif /* MDBX_LOCKING > MDBX_LOCKING_SYSV */
|
#endif /* MDBX_LOCKING > MDBX_LOCKING_SYSV */
|
||||||
|
|
||||||
|
static int check_fstat(MDBX_env *env) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
int rc = MDBX_SUCCESS;
|
||||||
|
if (fstat(env->me_lazy_fd, &st)) {
|
||||||
|
rc = errno;
|
||||||
|
mdbx_error("fstat(%s), err %d", "DXB", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode) || st.st_nlink < 1) {
|
||||||
|
#ifdef EBADFD
|
||||||
|
rc = EBADFD;
|
||||||
|
#else
|
||||||
|
rc = EPERM;
|
||||||
|
#endif
|
||||||
|
mdbx_error("%s %s, err %d", "DXB",
|
||||||
|
(st.st_nlink < 1) ? "file was removed" : "not a regular file",
|
||||||
|
rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size < (off_t)(MDBX_MIN_PAGESIZE * NUM_METAS)) {
|
||||||
|
mdbx_verbose("dxb-file is too short (%u), exclusive-lock needed",
|
||||||
|
(unsigned)st.st_size);
|
||||||
|
rc = MDBX_RESULT_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if (fstat(env->me_lfd, &st)) {
|
||||||
|
rc = errno;
|
||||||
|
mdbx_error("fstat(%s), err %d", "LCK", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode) || st.st_nlink < 1) {
|
||||||
|
#ifdef EBADFD
|
||||||
|
rc = EBADFD;
|
||||||
|
#else
|
||||||
|
rc = EPERM;
|
||||||
|
#endif
|
||||||
|
mdbx_error("%s %s, err %d", "LCK",
|
||||||
|
(st.st_nlink < 1) ? "file was removed" : "not a regular file",
|
||||||
|
rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking file size for detect the situation when we got the shared lock
|
||||||
|
* immediately after mdbx_lck_destroy(). */
|
||||||
|
if (st.st_size < (off_t)(sizeof(MDBX_lockinfo) + sizeof(MDBX_reader))) {
|
||||||
|
mdbx_verbose("lck-file is too short (%u), exclusive-lock needed",
|
||||||
|
(unsigned)st.st_size);
|
||||||
|
rc = MDBX_RESULT_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) {
|
MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) {
|
||||||
assert(env->me_lazy_fd != INVALID_HANDLE_VALUE);
|
assert(env->me_lazy_fd != INVALID_HANDLE_VALUE);
|
||||||
if (unlikely(mdbx_getpid() != env->me_pid))
|
if (unlikely(mdbx_getpid() != env->me_pid))
|
||||||
@ -229,7 +288,7 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) {
|
|||||||
choice_fcntl();
|
choice_fcntl();
|
||||||
#endif /* MDBX_USE_OFDLOCKS */
|
#endif /* MDBX_USE_OFDLOCKS */
|
||||||
|
|
||||||
int rc;
|
int rc = MDBX_SUCCESS;
|
||||||
if (env->me_lfd == INVALID_HANDLE_VALUE) {
|
if (env->me_lfd == INVALID_HANDLE_VALUE) {
|
||||||
/* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */
|
/* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */
|
||||||
rc =
|
rc =
|
||||||
@ -242,11 +301,27 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) {
|
|||||||
}
|
}
|
||||||
return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */;
|
return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */;
|
||||||
}
|
}
|
||||||
|
#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
|
||||||
|
sched_yield();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (rc == MDBX_RESULT_TRUE) {
|
||||||
|
rc = lck_op(env->me_lfd, op_setlk, F_UNLCK, 0, 1);
|
||||||
|
if (rc != MDBX_SUCCESS) {
|
||||||
|
mdbx_error("%s, err %u", "unlock-before-retry", rc);
|
||||||
|
mdbx_assert(env, MDBX_IS_ERROR(rc));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
retry_exclusive:
|
|
||||||
/* Firstly try to get exclusive locking. */
|
/* Firstly try to get exclusive locking. */
|
||||||
rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1);
|
rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1);
|
||||||
if (rc == MDBX_SUCCESS) {
|
if (rc == MDBX_SUCCESS) {
|
||||||
|
rc = check_fstat(env);
|
||||||
|
if (MDBX_IS_ERROR(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
continue_dxb_exclusive:
|
continue_dxb_exclusive:
|
||||||
rc =
|
rc =
|
||||||
lck_op(env->me_lazy_fd, op_setlk,
|
lck_op(env->me_lazy_fd, op_setlk,
|
||||||
@ -254,6 +329,10 @@ retry_exclusive:
|
|||||||
if (rc == MDBX_SUCCESS)
|
if (rc == MDBX_SUCCESS)
|
||||||
return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */;
|
return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */;
|
||||||
|
|
||||||
|
int err = check_fstat(env);
|
||||||
|
if (MDBX_IS_ERROR(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
/* the cause may be a collision with POSIX's file-lock recovery. */
|
/* the cause may be a collision with POSIX's file-lock recovery. */
|
||||||
if (!(rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK ||
|
if (!(rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK ||
|
||||||
rc == EDEADLK)) {
|
rc == EDEADLK)) {
|
||||||
@ -263,6 +342,11 @@ retry_exclusive:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fallback to lck-shared */
|
/* Fallback to lck-shared */
|
||||||
|
} else if (!(rc == EAGAIN || rc == EACCES || rc == EBUSY ||
|
||||||
|
rc == EWOULDBLOCK || rc == EDEADLK)) {
|
||||||
|
mdbx_error("%s, err %u", "try-exclusive", rc);
|
||||||
|
mdbx_assert(env, MDBX_IS_ERROR(rc));
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here could be one of two:
|
/* Here could be one of two:
|
||||||
@ -282,6 +366,14 @@ retry_exclusive:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = check_fstat(env);
|
||||||
|
if (rc == MDBX_RESULT_TRUE)
|
||||||
|
goto retry;
|
||||||
|
if (rc != MDBX_SUCCESS) {
|
||||||
|
mdbx_error("%s, err %u", "lck_fstat", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* got shared, retry exclusive */
|
/* got shared, retry exclusive */
|
||||||
rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1);
|
rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1);
|
||||||
if (rc == MDBX_SUCCESS)
|
if (rc == MDBX_SUCCESS)
|
||||||
@ -294,27 +386,6 @@ retry_exclusive:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checking file size for detect the situation when we got the shared lock
|
|
||||||
* immediately after mdbx_lck_destroy(). */
|
|
||||||
struct stat st;
|
|
||||||
if (fstat(env->me_lfd, &st)) {
|
|
||||||
rc = errno;
|
|
||||||
mdbx_error("%s(%s) failed: errcode %u", __func__, "check-filesize", rc);
|
|
||||||
mdbx_assert(env, MDBX_IS_ERROR(rc));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if (st.st_size < (unsigned)(sizeof(MDBX_lockinfo) + sizeof(MDBX_reader))) {
|
|
||||||
mdbx_verbose("lck-file is too short (%u), retry exclusive-lock",
|
|
||||||
(unsigned)st.st_size);
|
|
||||||
rc = lck_op(env->me_lfd, op_setlk, F_UNLCK, 0, 1);
|
|
||||||
if (rc != MDBX_SUCCESS) {
|
|
||||||
mdbx_error("%s(%s) failed: errcode %u", __func__, "retry-exclusive", rc);
|
|
||||||
mdbx_assert(env, MDBX_IS_ERROR(rc));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
goto retry_exclusive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lock against another process operating in without-lck or exclusive mode. */
|
/* Lock against another process operating in without-lck or exclusive mode. */
|
||||||
rc =
|
rc =
|
||||||
lck_op(env->me_lazy_fd, op_setlk,
|
lck_op(env->me_lazy_fd, op_setlk,
|
||||||
@ -357,10 +428,13 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env,
|
|||||||
return MDBX_PANIC;
|
return MDBX_PANIC;
|
||||||
|
|
||||||
int rc = MDBX_SUCCESS;
|
int rc = MDBX_SUCCESS;
|
||||||
|
struct stat lck_info;
|
||||||
if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor &&
|
if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor &&
|
||||||
env->me_lck &&
|
env->me_lck &&
|
||||||
/* try get exclusive access */
|
/* try get exclusive access */
|
||||||
lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, OFF_T_MAX) == 0 &&
|
lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, OFF_T_MAX) == 0 &&
|
||||||
|
/* if LCK was not removed */
|
||||||
|
fstat(env->me_lfd, &lck_info) == 0 && lck_info.st_nlink > 0 &&
|
||||||
lck_op(env->me_lazy_fd, op_setlk,
|
lck_op(env->me_lazy_fd, op_setlk,
|
||||||
(env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0,
|
(env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0,
|
||||||
OFF_T_MAX) == 0) {
|
OFF_T_MAX) == 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user