diff --git a/src/api-copy.c b/src/api-copy.c index bb7cda78..a87c6ea7 100644 --- a/src/api-copy.c +++ b/src/api-copy.c @@ -756,35 +756,67 @@ __cold static int copy2pathname(MDBX_txn *txn, const pathchar_t *dest_path, MDBX S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP #endif ); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; #if defined(_WIN32) || defined(_WIN64) /* no locking required since the file opened with ShareMode == 0 */ #else - if (rc == MDBX_SUCCESS) { - MDBX_STRUCT_FLOCK lock_op; - memset(&lock_op, 0, sizeof(lock_op)); - lock_op.l_type = F_WRLCK; - lock_op.l_whence = SEEK_SET; - lock_op.l_start = 0; - lock_op.l_len = OFF_T_MAX; - if (MDBX_FCNTL(newfd, MDBX_F_SETLK, &lock_op)) - rc = errno; - } + MDBX_STRUCT_FLOCK lock_op; + memset(&lock_op, 0, sizeof(lock_op)); + lock_op.l_type = F_WRLCK; + lock_op.l_whence = SEEK_SET; + lock_op.l_start = 0; + lock_op.l_len = OFF_T_MAX; + const int err_fcntl = MDBX_FCNTL(newfd, MDBX_F_SETLK, &lock_op) ? errno : MDBX_SUCCESS; -#if defined(LOCK_EX) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 24) - if (rc == MDBX_SUCCESS && flock(newfd, LOCK_EX | LOCK_NB)) { - const int err_flock = errno, err_fs = osal_check_fs_local(newfd, 0); - if (err_flock != EAGAIN || err_fs != MDBX_EREMOTE) { - ERROR("%s flock(%" MDBX_PRIsPATH ") error %d, remote-fs check status %d", "unexpected", dest_path, err_flock, - err_fs); - rc = err_flock; - } else { - WARNING("%s flock(%" MDBX_PRIsPATH ") error %d, remote-fs check status %d", "ignore", dest_path, err_flock, - err_fs); + const int err_flock = +#ifdef LOCK_EX + flock(newfd, LOCK_EX | LOCK_NB) ? errno : MDBX_SUCCESS; +#else + MDBX_ENOSYS; +#endif /* LOCK_EX */ + + const int err_check_fs_local = + /* avoid call osal_check_fs_local() on success */ + (!err_fcntl && !err_flock && !MDBX_DEBUG) ? MDBX_SUCCESS : +#if !defined(__ANDROID_API__) || __ANDROID_API__ >= 24 + osal_check_fs_local(newfd, 0); +#else + MDBX_ENOSYS; +#endif + + const bool flock_may_fail = +#if defined(__linux__) || defined(__gnu_linux__) + err_check_fs_local != 0; +#else + true; +#endif /* Linux */ + + if (!err_fcntl && + (err_flock == EWOULDBLOCK || err_flock == EAGAIN || ignore_enosys_and_eremote(err_flock) == MDBX_RESULT_TRUE)) { + rc = err_flock; + if (flock_may_fail) { + WARNING("ignore %s(%" MDBX_PRIsPATH ") error %d: since %s done, local/remote-fs check %d", "flock", dest_path, + err_flock, "fcntl-lock", err_check_fs_local); + rc = MDBX_SUCCESS; } + } else if (!err_flock && err_check_fs_local == MDBX_RESULT_TRUE && + ignore_enosys_and_eremote(err_fcntl) == MDBX_RESULT_TRUE) { + WARNING("ignore %s(%" MDBX_PRIsPATH ") error %d: since %s done, local/remote-fs check %d", "fcntl-lock", dest_path, + err_fcntl, "flock", err_check_fs_local); + } else if (err_fcntl || err_flock) { + ERROR("file-lock(%" MDBX_PRIsPATH ") failed: fcntl-lock %d, flock %d, local/remote-fs check %d", dest_path, + err_fcntl, err_flock, err_check_fs_local); + if (err_fcntl == ENOLCK || err_flock == ENOLCK) + rc = ENOLCK; + else if (err_fcntl == EWOULDBLOCK || err_flock == EWOULDBLOCK) + rc = EWOULDBLOCK; + else if (EWOULDBLOCK != EAGAIN && (err_fcntl == EAGAIN || err_flock == EAGAIN)) + rc = EAGAIN; + else + rc = (err_fcntl && ignore_enosys_and_eremote(err_fcntl) != MDBX_RESULT_TRUE) ? err_fcntl : err_flock; } -#endif /* LOCK_EX && ANDROID_API >= 24 */ - #endif /* Windows / POSIX */ if (rc == MDBX_SUCCESS) diff --git a/src/cogs.h b/src/cogs.h index 70836997..0b75702c 100644 --- a/src/cogs.h +++ b/src/cogs.h @@ -389,6 +389,11 @@ MDBX_MAYBE_UNUSED MDBX_CONST_FUNCTION static inline int ignore_enosys_and_eagain MDBX_MAYBE_UNUSED MDBX_CONST_FUNCTION static inline int ignore_enosys_and_einval(int err) { return (err == EINVAL) ? MDBX_RESULT_TRUE : ignore_enosys(err); } + +MDBX_MAYBE_UNUSED MDBX_CONST_FUNCTION static inline int ignore_enosys_and_eremote(int err) { + return (err == MDBX_EREMOTE) ? MDBX_RESULT_TRUE : ignore_enosys(err); +} + #endif /* defined(_WIN32) || defined(_WIN64) */ static inline int check_env(const MDBX_env *env, const bool wanna_active) {