|
| static const char * | shmdstrfromoff (off_t off) |
| static int | set_lock (int fd, int cmd, struct flock *lock) |
| static int | XLATE_FCNTL_LOCK (int type) |
| static int | OVERLAP (off_t a, off_t alen, off_t b, off_t blen) |
| static void | adf_relockrange (struct ad_fd *ad, int fd, off_t off, off_t len) |
| static void | adf_freelock (struct ad_fd *ad, const int i) |
| static void | adf_unlock (struct adouble *ad, struct ad_fd *adf, const int fork) |
| void | adf_lock_init (struct ad_fd *adf) |
| | Initialize lock tracking for an ad_fd structure.
|
| void | adf_lock_free (struct ad_fd *adf) |
| | Free all locks in an ad_fd structure.
|
| static int | adf_findlock (struct ad_fd *ad, const int fork, const int type, const off_t off, const off_t len) |
| static int | adf_findxlock (struct ad_fd *ad, const int fork, const int type, const off_t off, const off_t len) |
| static off_t | rf2off (off_t off) |
| static int | testlock (const struct ad_fd *adf, off_t off, off_t len) |
| | Test a lock.
|
| static const char * | locktypetostr (int type) |
| int | ad_lock (struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len, int fork) |
| int | ad_tmplock (struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len, int fork) |
| void | ad_unlock (struct adouble *ad, const int fork) |
| int | ad_testlock (struct adouble *ad, int eid, const off_t off) |
| | Test for a share mode lock.
|
| int | ad_testlock_range (struct adouble *ad, int eid, off_t off, off_t len) |
| | GET-only range probe: does another process hold a conflicting lock?
|
| int | ad_testlock_whole (struct adouble *ad, int eid) |
| | GET-only whole-fd probe: does another process hold any lock on the fd?
|
| uint16_t | ad_openforks (struct adouble *ad, uint16_t attrbits) |
| | Return if a file is open by another process.
|
| int ad_testlock_range |
( |
struct adouble * | ad, |
|
|
int | eid, |
|
|
off_t | off, |
|
|
off_t | len ) |
GET-only range probe: does another process hold a conflicting lock?
Tests whether another process holds a conflicting lock on [off, off+len) of fork eid. Unlike ad_testlock()/testlock() this does not scan our own adf_lock[] array first: it is kernel F_GETLK only. By POSIX, F_GETLK never reports the calling process's own locks, so this can be called through a fd of a fork we hold open without self-reporting our own band/byte entries — exactly the conflict read a delete needs (it must see only other holders). It never issues F_SETLK, so it has no acquire/release lifetime and cannot strand a lock.
Key behaviours:
- No adf_lock[] array scan — kernel F_GETLK only (no self-report).
- Always probes with an explicit F_WRLCK. A write probe conflicts with a peer's read or write lock, so it sees the F_RDLCK share-mode band entries. F_GETLK only tests, so the probe type is independent of the fd's O_RDWR/O_RDONLY mode (cf. testlock(), which picks F_RDLCK on an RO fd and would miss the band).
- eid dispatch: ADEID_DFORK uses the data fd at the literal offset, which also covers the whole share-mode band (OPEN, DENY and RSRC mirrors), since the band lives on the data fd via rf2off(). ADEID_RFORK uses the resource fork's own fd (ad_rfp) at off + ad_getentryoff(), matching ad_lock()'s rfork non-FILELOCK branch. Band offsets are never passed with ADEID_RFORK; a band offset is recognised as off >= AD_FILELOCK_BASE.
- Zone clamp on data-zone requests only (off < AD_FILELOCK_BASE): a len == 0 ("whole data zone") or over-long request is bounded to the data zone, never a POSIX l_len == 0 ("to infinity") that would sweep the share-mode band. An explicit band probe (off >= AD_FILELOCK_BASE) passes through unclamped.
- Parameters
-
| [in,out] | ad | handle |
| [in] | eid | ADEID_DFORK (data + band) or ADEID_RFORK (rfork content) |
| [in] | off | offset (content) or a band offset (>= AD_FILELOCK_BASE) |
| [in] | len | length; 0 == whole data zone (data-zone requests only) |
- Returns
- 1 = a conflicting lock exists (incl. F_GETLK EACCES/EAGAIN, reported as locked/indeterminate — fail safe, matching testlock()); 0 = no conflict (incl. no fd to probe); -1 = hard error (caller must refuse the operation, never proceed).
| int ad_testlock_whole |
( |
struct adouble * | ad, |
|
|
int | eid ) |
GET-only whole-fd probe: does another process hold any lock on the fd?
The negative-case fast path. Issues one F_GETLK over the entire fd of fork eid — deliberately unclamped (l_start = 0, l_len = 0 = "to infinity"), so on the data fd it spans the data content zone and the whole share-mode band, a strict superset of every ad_testlock_range dimension on that fd. A clear (0) result proves the fd holds nothing, letting a caller skip the per-dimension content + per-bit band probes; a hit (1) forces the fidelity-preserving per-dimension resolution.
This is the one probe that must span the band, so unlike ad_testlock_range it is not zone-clamped. That is sound only because its sole use is the all-or-nothing fast path, never a per-dimension result. Like ad_testlock_range it is kernel F_GETLK only (no array scan), probes with an explicit F_WRLCK, and shares the same fail-safe contract.
Callers pass ADEID_DFORK: the rfork fd carries only a content range and no band, so a whole-fd probe there would collapse 1->1 and force the real range probe anyway (a net extra syscall) — the rfork is read with ad_testlock_range directly.
- Returns
- 1 = some lock exists (incl. F_GETLK EACCES/EAGAIN — fail safe); 0 = wholly clear (incl. no fd to probe); -1 = hard error (caller must fail closed).