Skip to content
This repository was archived by the owner on Jan 20, 2022. It is now read-only.

Commit d884d36

Browse files
committed
fixup! [LibOS] Implement POSIX locks (fcntl)
Signed-off-by: Paweł Marczewski <[email protected]>
1 parent cbb432c commit d884d36

File tree

1 file changed

+43
-35
lines changed

1 file changed

+43
-35
lines changed

LibOS/shim/src/fs/shim_fs_lock.c

+43-35
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,27 @@
1414
* Describes a pending request for a POSIX lock. After processing the request, the object is
1515
* removed, and a possible waiter is notified (see below).
1616
*
17-
* If the request is initiated by another process over IPC, `vmid` and `seq` should be set to
18-
* parameters of IPC message. After processing the request, IPC response will be sent.
17+
* If the request is initiated by another process over IPC, `notify.vmid` and `notify.seq` should be
18+
* set to parameters of IPC message. After processing the request, IPC response will be sent.
1919
*
20-
* If the request is initiated by process leader, `vmid` should be set to 0, and `event` should be
21-
* set to an event handle. After processing the request, the event will be triggered, and `*result`
22-
* will be set to the result.
20+
* If the request is initiated by process leader, `notify.vmid` should be set to 0, and
21+
* `notify.event` should be set to an event handle. After processing the request, the event will be
22+
* triggered, and `*notify.result` will be set to the result.
2323
*/
2424
DEFINE_LISTP(posix_lock_request);
2525
DEFINE_LIST(posix_lock_request);
2626
struct posix_lock_request {
2727
struct posix_lock pl;
2828

29-
IDTYPE vmid;
30-
unsigned int seq;
29+
struct {
30+
IDTYPE vmid;
31+
unsigned int seq;
3132

32-
PAL_HANDLE event;
33-
int* result;
33+
/* Note that `event` and `result` are owned by the side making the request, and outlive this
34+
* object (we delete it as soon as the request is processed). */
35+
PAL_HANDLE event;
36+
int* result;
37+
} notify;
3438

3539
LIST_TYPE(posix_lock_request) list;
3640
};
@@ -41,8 +45,8 @@ DEFINE_LIST(fs_lock);
4145
struct fs_lock {
4246
struct shim_dentry* dent;
4347

44-
/* POSIX locks, sorted by PID and then by start position. The ranges do not overlap within a
45-
* given PID. */
48+
/* POSIX locks, sorted by PID and then by start position (so that we are able to merge and split
49+
* locks). The ranges do not overlap within a given PID. */
4650
LISTP_TYPE(posix_lock) posix_locks;
4751

4852
/* Pending requests. */
@@ -156,8 +160,8 @@ static struct posix_lock* posix_lock_find_conflict(struct fs_lock* fs_lock, stru
156160
}
157161

158162
/*
159-
* Add a new lock request. Before releasing `g_fs_lock_lock`, the caller has to add notification
160-
* info to the request (see `struct posix_lock_request` above).
163+
* Add a new lock request. Before releasing `g_fs_lock_lock`, the caller has to initialize the
164+
* `notify` part of the request (see `struct posix_lock_request` above).
161165
*/
162166
static int posix_lock_add_request(struct fs_lock* fs_lock, struct posix_lock* pl,
163167
struct posix_lock_request** out_req) {
@@ -201,7 +205,8 @@ static int _posix_lock_set(struct fs_lock* fs_lock, struct posix_lock* pl) {
201205
}
202206

203207
/* Target range: we will be changing it when merging existing locks. */
204-
uint64_t start = pl->start, end = pl->end;
208+
uint64_t start = pl->start;
209+
uint64_t end = pl->end;
205210

206211
/* `prev` will be set to the last lock before target range, so that we add the new lock just
207212
* after `prev`. */
@@ -218,7 +223,7 @@ static int _posix_lock_set(struct fs_lock* fs_lock, struct posix_lock* pl) {
218223
break;
219224
}
220225

221-
if (pl->type == cur->type) {
226+
if (cur->type == pl->type) {
222227
/* Same lock type: we can possibly merge the locks. */
223228

224229
if (start > 0 && cur->end < start - 1) {
@@ -301,7 +306,7 @@ static int _posix_lock_set(struct fs_lock* fs_lock, struct posix_lock* pl) {
301306
* cur: ==
302307
*/
303308
assert(start <= cur->start && end < cur->end);
304-
assert (end < FS_LOCK_EOF);
309+
assert(end < FS_LOCK_EOF);
305310
cur->start = end + 1;
306311
break;
307312
}
@@ -362,16 +367,17 @@ static void posix_lock_process_requests(struct fs_lock* fs_lock) {
362367

363368
/* Notify the waiter that we processed their request. Note that the result might
364369
* still be a failure (-ENOMEM). */
365-
if (req->vmid == 0) {
366-
assert(req->event);
367-
assert(req->result);
368-
*req->result = result;
369-
DkEventSet(req->event);
370+
if (req->notify.vmid == 0) {
371+
assert(req->notify.event);
372+
assert(req->notify.result);
373+
*req->notify.result = result;
374+
DkEventSet(req->notify.event);
370375
} else {
371-
assert(!req->event);
372-
assert(!req->result);
376+
assert(!req->notify.event);
377+
assert(!req->notify.result);
373378

374-
int ret = ipc_posix_lock_set_send_response(req->vmid, req->seq, result);
379+
int ret = ipc_posix_lock_set_send_response(req->notify.vmid, req->notify.seq,
380+
result);
375381
if (ret < 0) {
376382
log_warning("posix lock: error sending result over IPC: %d", ret);
377383
}
@@ -383,6 +389,8 @@ static void posix_lock_process_requests(struct fs_lock* fs_lock) {
383389
} while (changed);
384390
}
385391

392+
/* Add/remove a lock if possible. On conflict, returns -EAGAIN (if `wait` is false) or adds a new
393+
* request (if `wait` is true). */
386394
static int posix_lock_set_or_add_request(struct shim_dentry* dent, struct posix_lock* pl, bool wait,
387395
struct posix_lock_request** out_req) {
388396
assert(locked(&g_fs_lock_lock));
@@ -429,8 +437,8 @@ static int posix_lock_set_or_add_request(struct shim_dentry* dent, struct posix_
429437
int posix_lock_set(struct shim_dentry* dent, struct posix_lock* pl, bool wait) {
430438
int ret;
431439
if (g_process_ipc_ids.leader_vmid) {
432-
/* In the IPC version, we use `dent->maybe_has_fs_locks` to short-circuit unlocking files that
433-
* we never locked. This is to prevent unnecessary IPC calls on a handle. */
440+
/* In the IPC version, we use `dent->maybe_has_fs_locks` to short-circuit unlocking files
441+
* that we never locked. This is to prevent unnecessary IPC calls on a handle. */
434442
lock(&g_fs_lock_lock);
435443
if (pl->type == F_RDLCK || pl->type == F_WRLCK) {
436444
dent->maybe_has_fs_locks = true;
@@ -465,10 +473,10 @@ int posix_lock_set(struct shim_dentry* dent, struct posix_lock* pl, bool wait) {
465473
ret = DkEventCreate(&event, /*init_signaled=*/false, /*auto_clear=*/false);
466474
if (ret < 0)
467475
goto out;
468-
req->vmid = 0;
469-
req->seq = 0;
470-
req->event = event;
471-
req->result = &result;
476+
req->notify.vmid = 0;
477+
req->notify.seq = 0;
478+
req->notify.event = event;
479+
req->notify.result = &result;
472480

473481
unlock(&g_fs_lock_lock);
474482
ret = object_wait_with_retry(event);
@@ -508,10 +516,10 @@ int posix_lock_set_from_ipc(const char* path, struct posix_lock* pl, bool wait,
508516

509517
if (req) {
510518
assert(wait);
511-
req->vmid = vmid;
512-
req->seq = seq;
513-
req->event = NULL;
514-
req->result = NULL;
519+
req->notify.vmid = vmid;
520+
req->notify.seq = seq;
521+
req->notify.event = NULL;
522+
req->notify.result = NULL;
515523
}
516524
ret = 0;
517525
out:
@@ -610,7 +618,7 @@ int posix_lock_clear_pid(IDTYPE pid) {
610618
struct posix_lock_request* req_tmp;
611619
LISTP_FOR_EACH_ENTRY_SAFE(req, req_tmp, &fs_lock->posix_lock_requests, list) {
612620
if (req->pl.pid == pid) {
613-
assert(!req->event);
621+
assert(!req->notify.event);
614622
LISTP_DEL(req, &fs_lock->posix_lock_requests, list);
615623
free(req);
616624
}

0 commit comments

Comments
 (0)