14
14
* Describes a pending request for a POSIX lock. After processing the request, the object is
15
15
* removed, and a possible waiter is notified (see below).
16
16
*
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.
19
19
*
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.
23
23
*/
24
24
DEFINE_LISTP (posix_lock_request );
25
25
DEFINE_LIST (posix_lock_request );
26
26
struct posix_lock_request {
27
27
struct posix_lock pl ;
28
28
29
- IDTYPE vmid ;
30
- unsigned int seq ;
29
+ struct {
30
+ IDTYPE vmid ;
31
+ unsigned int seq ;
31
32
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 ;
34
38
35
39
LIST_TYPE (posix_lock_request ) list ;
36
40
};
@@ -41,8 +45,8 @@ DEFINE_LIST(fs_lock);
41
45
struct fs_lock {
42
46
struct shim_dentry * dent ;
43
47
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. */
46
50
LISTP_TYPE (posix_lock ) posix_locks ;
47
51
48
52
/* Pending requests. */
@@ -156,8 +160,8 @@ static struct posix_lock* posix_lock_find_conflict(struct fs_lock* fs_lock, stru
156
160
}
157
161
158
162
/*
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).
161
165
*/
162
166
static int posix_lock_add_request (struct fs_lock * fs_lock , struct posix_lock * pl ,
163
167
struct posix_lock_request * * out_req ) {
@@ -201,7 +205,8 @@ static int _posix_lock_set(struct fs_lock* fs_lock, struct posix_lock* pl) {
201
205
}
202
206
203
207
/* 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 ;
205
210
206
211
/* `prev` will be set to the last lock before target range, so that we add the new lock just
207
212
* after `prev`. */
@@ -218,7 +223,7 @@ static int _posix_lock_set(struct fs_lock* fs_lock, struct posix_lock* pl) {
218
223
break ;
219
224
}
220
225
221
- if (pl -> type == cur -> type ) {
226
+ if (cur -> type == pl -> type ) {
222
227
/* Same lock type: we can possibly merge the locks. */
223
228
224
229
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) {
301
306
* cur: ==
302
307
*/
303
308
assert (start <= cur -> start && end < cur -> end );
304
- assert (end < FS_LOCK_EOF );
309
+ assert (end < FS_LOCK_EOF );
305
310
cur -> start = end + 1 ;
306
311
break ;
307
312
}
@@ -362,16 +367,17 @@ static void posix_lock_process_requests(struct fs_lock* fs_lock) {
362
367
363
368
/* Notify the waiter that we processed their request. Note that the result might
364
369
* 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 );
370
375
} else {
371
- assert (!req -> event );
372
- assert (!req -> result );
376
+ assert (!req -> notify . event );
377
+ assert (!req -> notify . result );
373
378
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 );
375
381
if (ret < 0 ) {
376
382
log_warning ("posix lock: error sending result over IPC: %d" , ret );
377
383
}
@@ -383,6 +389,8 @@ static void posix_lock_process_requests(struct fs_lock* fs_lock) {
383
389
} while (changed );
384
390
}
385
391
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). */
386
394
static int posix_lock_set_or_add_request (struct shim_dentry * dent , struct posix_lock * pl , bool wait ,
387
395
struct posix_lock_request * * out_req ) {
388
396
assert (locked (& g_fs_lock_lock ));
@@ -429,8 +437,8 @@ static int posix_lock_set_or_add_request(struct shim_dentry* dent, struct posix_
429
437
int posix_lock_set (struct shim_dentry * dent , struct posix_lock * pl , bool wait ) {
430
438
int ret ;
431
439
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. */
434
442
lock (& g_fs_lock_lock );
435
443
if (pl -> type == F_RDLCK || pl -> type == F_WRLCK ) {
436
444
dent -> maybe_has_fs_locks = true;
@@ -465,10 +473,10 @@ int posix_lock_set(struct shim_dentry* dent, struct posix_lock* pl, bool wait) {
465
473
ret = DkEventCreate (& event , /*init_signaled=*/ false, /*auto_clear=*/ false);
466
474
if (ret < 0 )
467
475
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 ;
472
480
473
481
unlock (& g_fs_lock_lock );
474
482
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,
508
516
509
517
if (req ) {
510
518
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 ;
515
523
}
516
524
ret = 0 ;
517
525
out :
@@ -610,7 +618,7 @@ int posix_lock_clear_pid(IDTYPE pid) {
610
618
struct posix_lock_request * req_tmp ;
611
619
LISTP_FOR_EACH_ENTRY_SAFE (req , req_tmp , & fs_lock -> posix_lock_requests , list ) {
612
620
if (req -> pl .pid == pid ) {
613
- assert (!req -> event );
621
+ assert (!req -> notify . event );
614
622
LISTP_DEL (req , & fs_lock -> posix_lock_requests , list );
615
623
free (req );
616
624
}
0 commit comments