980
989
FileUnlockIntrinsic(FileLockToken *tokenPtr) // IN:
984
993
ASSERT(tokenPtr && (tokenPtr->signature == FILELOCK_TOKEN_SIGNATURE));
986
995
LOG(1, ("Requesting unlock on %s\n", UTF8(tokenPtr->pathName)));
989
* If the lockFilePath (a pointer) is the fixed-address token representing
990
* an implicit read lock, there is no lock file and the token can simply
994
if (tokenPtr->lockFilePath == &implicitReadToken) {
997
free(tokenPtr->pathName);
997
if (tokenPtr->portable) {
1000
* If the lockFilePath (a pointer) is the fixed-address token representing
1001
* an implicit read lock, there is no lock file and the token can simply
1005
if (tokenPtr->u.portable.lockFilePath != &implicitReadToken) {
1008
/* The lock directory path */
1009
lockDir = Unicode_Append(tokenPtr->pathName, FILELOCK_SUFFIX);
1012
* TODO: under vmx86_debug validate the contents of the lock file as
1013
* matching the machineID and executionID.
1016
err = FileDeletionRobust(tokenPtr->u.portable.lockFilePath, FALSE);
1018
FileRemoveDirectoryRobust(lockDir); // just in case we can clean up
1020
if (err && vmx86_debug) {
1021
Log(LGPFX" %s failed for '%s': %s\n", __FUNCTION__,
1022
UTF8(tokenPtr->u.portable.lockFilePath), strerror(err));
1024
Unicode_Free(lockDir);
1025
Unicode_Free(tokenPtr->u.portable.lockFilePath);
1028
tokenPtr->u.portable.lockFilePath = NULL; // Just in case...
1001
/* The lock directory path */
1002
lockDir = Unicode_Append(tokenPtr->pathName, FILELOCK_SUFFIX);
1005
* TODO: under vmx86_debug validate the contents of the lock file as
1006
* matching the machineID and executionID.
1009
err = FileDeletionRobust(tokenPtr->lockFilePath, FALSE);
1011
if (err && vmx86_debug) {
1012
Log(LGPFX" %s failed for '%s': %s\n", __FUNCTION__,
1013
UTF8(tokenPtr->lockFilePath), strerror(err));
1030
ASSERT(FileIO_IsValid(&tokenPtr->u.mandatory.lockFd));
1032
if (FileIO_CloseAndUnlink(&tokenPtr->u.mandatory.lockFd)) {
1034
* Should succeed, but there is an unavoidable race:
1035
* close() must preceed unlink(), but another locker could acquire
1036
* lock between close() and unlink(). Solution: treat EBUSY as
1039
if (Err_Errno() == EBUSY) {
1040
LOG(0, ("Tolerating EBUSY on unlink of advisory lock at %s\n",
1041
UTF8(tokenPtr->pathName)));
1017
* Attempt to clean up the locking directory.
1020
FileRemoveDirectoryRobust(lockDir); // just in case we can clean up
1022
Unicode_Free(lockDir);
1023
Unicode_Free(tokenPtr->pathName);
1024
Unicode_Free(tokenPtr->lockFilePath);
1048
Unicode_Free(tokenPtr->pathName);
1027
1049
tokenPtr->signature = 0; // Just in case...
1028
1050
tokenPtr->pathName = NULL; // Just in case...
1029
tokenPtr->lockFilePath = NULL; // Just in case...
1030
1051
free(tokenPtr);
1524
1549
*-----------------------------------------------------------------------------
1528
FileLockIntrinsic(ConstUnicode pathName, // IN:
1529
Bool exclusivity, // IN:
1530
uint32 msecMaxWaitTime, // IN:
1534
LockValues myValues;
1552
static FileLockToken *
1553
FileLockIntrinsicMandatory(ConstUnicode pathName, // IN:
1554
ConstUnicode lockFile, // IN:
1555
LockValues *myValues, // IN/OUT:
1560
FileIOResult result;
1561
FileLockToken *tokenPtr = Util_SafeMalloc(sizeof(FileLockToken));
1563
tokenPtr->signature = FILELOCK_TOKEN_SIGNATURE;
1564
tokenPtr->portable = FALSE;
1565
tokenPtr->pathName = Unicode_Duplicate(pathName);
1566
FileIO_Invalidate(&tokenPtr->u.mandatory.lockFd);
1568
access = myValues->exclusivity ? FILEIO_OPEN_ACCESS_WRITE
1569
: FILEIO_OPEN_ACCESS_READ;
1570
access |= FILEIO_OPEN_EXCLUSIVE_LOCK;
1573
result = FileIOCreateRetry(&tokenPtr->u.mandatory.lockFd,
1575
FILEIO_OPEN_CREATE, 0600,
1577
if (result != FILEIO_LOCK_FAILED) {
1580
} while (FileLockSleeper(myValues, &loopCount) == 0);
1582
if (FileIO_IsSuccess(result)) {
1583
ASSERT(FileIO_IsValid(&tokenPtr->u.mandatory.lockFd));
1588
*err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
1589
Unicode_Free(tokenPtr->pathName);
1590
ASSERT(!FileIO_IsValid(&tokenPtr->u.mandatory.lockFd));
1599
*-----------------------------------------------------------------------------
1601
* FileLockIntrinsicPortable --
1603
* Obtain a lock on a file; shared or exclusive access.
1605
* This implementation uses a HIGHLY portable directory-namespace +
1606
* Lamport bakery scheme that works on all filesystems that provide atomicity
1607
* of the directory namespace. (That is, all known filesystems.)
1608
* The various files involved are hidden within a "pathName.lck/"
1611
* The lock can be broken by removing the subdirectory. The lock
1612
* is self-cleaning on the same host (e.g. will detect a dead process
1613
* and will break the lock), but NOT self-cleaning across hosts. The
1614
* lock does not require any sort of time-based leases or heartbeats.
1617
* NULL Lock not acquired. Check err.
1618
* err 0 Lock Timed Out
1620
* !NULL Lock Acquired. This is the "lockToken" for an unlock.
1625
*-----------------------------------------------------------------------------
1628
static FileLockToken *
1629
FileLockIntrinsicPortable(ConstUnicode pathName, // IN:
1630
ConstUnicode lockDir, // IN:
1631
LockValues *myValues, // IN/OUT:
1535
1635
FileIOResult result;
1536
1636
FileIODescriptor desc;
1537
1637
FileLockToken *tokenPtr;
1539
Unicode lockDir = NULL;
1540
1639
Unicode entryFilePath = NULL;
1541
1640
Unicode memberFilePath = NULL;
1542
1641
Unicode entryDirectory = NULL;
1544
1643
ASSERT(pathName);
1547
/* Construct the locking directory path */
1548
lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX);
1550
/* establish our values */
1552
myValues.machineID = (char *) FileLockGetMachineID(); // don't free this!
1553
myValues.executionID = FileLockGetExecutionID(); // free this!
1554
myValues.lockType = exclusivity ? LOCK_EXCLUSIVE : LOCK_SHARED;
1555
myValues.lamportNumber = 0;
1556
myValues.locationChecksum = FileLockLocationChecksum(lockDir); // free this!
1557
myValues.waitTime = 0;
1558
myValues.msecMaxWaitTime = msecMaxWaitTime;
1559
myValues.memberName = NULL;
1561
LOG(1, ("Requesting %s lock on %s (%s, %s, %u).\n",
1562
myValues.lockType, UTF8(pathName), myValues.machineID,
1563
myValues.executionID, myValues.msecMaxWaitTime));
1566
1647
* Attempt to create the locking and entry directories; obtain the
1567
1648
* entry and member path names.
1707
1785
*-----------------------------------------------------------------------------
1709
* FileLockIsLocked --
1711
* Is a file currently locked (at the time of the call)?
1715
* FALSE NO; if err is not NULL may check *err for an error
1720
*-----------------------------------------------------------------------------
1724
FileLockIsLocked(ConstUnicode pathName, // IN:
1787
* FileLockIntrinsic --
1789
* Obtain a lock on a file; shared or exclusive access.
1791
* All FileLock_-based locks are advisory locks (i.e. the
1792
* lock is maintained separately from the file so only FileLock_
1793
* callers experience locking). Advisory locks have an inherent problem
1794
* that they are difficult to break in the event one of the cooperating
1795
* entities fails, particularly across distributed filesystems.
1797
* This wrapper function will adaptively switch between a scheme
1798
* implemented via mandatory locks and a more portable scheme depending
1799
* on host OS support.
1801
* msecMaxWaitTime specifies the maximum amount of time, in
1802
* milliseconds, to wait for the lock before returning the "not
1803
* acquired" status. A value of FILELOCK_TRYLOCK_WAIT is the
1804
* equivalent of a "try lock" - the lock will be acquired only if
1805
* there is no contention. A value of FILELOCK_INFINITE_WAIT
1806
* specifies "waiting forever" to acquire the lock.
1809
* NULL Lock not acquired. Check err.
1810
* err 0 Lock Timed Out
1812
* !NULL Lock Acquired. This is the "lockToken" for an unlock.
1817
*-----------------------------------------------------------------------------
1821
FileLockIntrinsic(ConstUnicode pathName, // IN:
1822
Bool exclusivity, // IN:
1823
uint32 msecMaxWaitTime, // IN:
1827
LockValues myValues = { 0 };
1828
FileLockToken *tokenPtr;
1830
/* Construct the locking directory path */
1831
lockBase = Unicode_Append(pathName, FILELOCK_SUFFIX);
1833
myValues.lockType = exclusivity ? LOCK_EXCLUSIVE : LOCK_SHARED;
1834
myValues.waitTime = 0;
1835
myValues.msecMaxWaitTime = msecMaxWaitTime;
1837
if (File_SupportsMandatoryLock(pathName)) {
1838
LOG(1, ("Requesting %s lock on %s (mandatory, %u).\n",
1839
myValues.lockType, UTF8(pathName), myValues.msecMaxWaitTime));
1841
tokenPtr = FileLockIntrinsicMandatory(pathName, lockBase, &myValues, err);
1843
myValues.machineID = (char *) FileLockGetMachineID(); // don't free this!
1844
myValues.executionID = FileLockGetExecutionID(); // free this!
1845
myValues.lamportNumber = 0;
1846
myValues.locationChecksum = FileLockLocationChecksum(lockBase); // free this!
1847
myValues.memberName = NULL;
1849
LOG(1, ("Requesting %s lock on %s (%s, %s, %u).\n",
1850
myValues.lockType, UTF8(pathName), myValues.machineID,
1851
myValues.executionID, myValues.msecMaxWaitTime));
1853
tokenPtr = FileLockIntrinsicPortable(pathName, lockBase, &myValues, err);
1855
Unicode_Free(myValues.memberName);
1856
free(myValues.locationChecksum);
1857
free(myValues.executionID);
1860
Unicode_Free(lockBase);
1867
*-----------------------------------------------------------------------------
1869
* FileLockIsLockedMandatory --
1871
* Is a file currently locked (at the time of the call)?
1873
* The only way to check for a mandatory lock is to try opening
1874
* the file (and quickly closing it again). If the lock is held,
1875
* attempting to open the file will return FILEIO_LOCK_FAILED.
1879
* FALSE NO; if err is not NULL may check *err for an error
1884
*-----------------------------------------------------------------------------
1888
FileLockIsLockedMandatory(ConstUnicode lockFile, // IN:
1889
int *err) // OUT/OPT:
1892
FileIOResult result;
1893
FileIODescriptor desc;
1895
FileIO_Invalidate(&desc);
1898
* Check for lock by actually locking file, and dropping
1899
* lock quickly if open was successful.
1902
access = FILEIO_OPEN_ACCESS_READ | FILEIO_OPEN_ACCESS_WRITE |
1903
FILEIO_OPEN_EXCLUSIVE_LOCK;
1905
result = FileIOCreateRetry(&desc, lockFile, access, FILEIO_OPEN, 0644, 0);
1907
if (FileIO_IsSuccess(result)) {
1910
ret = FileIO_Close(&desc);
1914
} else if (result == FILEIO_LOCK_FAILED) {
1915
return TRUE; // locked
1916
} else if (result == FILEIO_FILE_NOT_FOUND) {
1917
return FALSE; // no lock file means unlocked
1920
*err = FileMapErrorToErrno(__FUNCTION__, Err_Errno());
1929
*-----------------------------------------------------------------------------
1931
* FileLockIsLockedPortable --
1933
* Is a file currently locked (at the time of the call)?
1935
* The "portable" lock is held if the lock directory exists and
1936
* there are any "M" entries (representing held locks).
1938
* FileLocks implemented via mandatory locking are reported
1939
* as held locks (errno == ENOTDIR).
1943
* FALSE NO; if err is not NULL may check *err for an error
1948
*-----------------------------------------------------------------------------
1952
FileLockIsLockedPortable(ConstUnicode lockDir, // IN:
1953
int *err) // OUT/OPT:
1728
1956
int numEntries;
1732
1957
Bool isLocked = FALSE;
1733
1958
Unicode *fileList = NULL;
1735
lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX);
1737
1960
numEntries = FileListDirectoryRobust(lockDir, &fileList);
1739
1962
if (numEntries == -1) {