This repository has been archived by the owner on Jan 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 261
/
Copy pathshim_fs_lock.h
104 lines (84 loc) · 3.44 KB
/
shim_fs_lock.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2021 Intel Corporation
* Paweł Marczewski <[email protected]>
*/
/*
* File locks. Currently POSIX locks are implemented.
*/
#ifndef SHIM_FS_LOCK_H_
#define SHIM_FS_LOCK_H_
#include <stdbool.h>
#include "list.h"
#include "shim_types.h"
#define FS_LOCK_EOF ((uint64_t)-1)
struct shim_dentry;
/* Initialize the file locking subsystem. */
int init_fs_lock(void);
/*
* POSIX locks (also known as advisory record locks). See `man fcntl` for details.
*
* The current implementation works over IPC and handles all requests in the main process. It has
* the following caveats:
*
* - Lock requests from other processes will always have the overhead of IPC round-trip, even if the
* lock is uncontested.
* - The main process has to be able to look up the same file, so locking will not work for files in
* local-process-only filesystems (tmpfs).
* - There is no deadlock detection (EDEADLK).
* - The lock requests cannot be interrupted (EINTR).
* - The locks work only on files that have a dentry (no pipes, sockets etc.)
*/
DEFINE_LISTP(posix_lock);
DEFINE_LIST(posix_lock);
struct posix_lock {
/* Lock type: F_RDLCK, F_WRLCK, F_UNLCK */
int type;
/* First byte of range */
uint64_t start;
/* Last byte of range (use FS_LOCK_EOF for a range until end of file) */
uint64_t end;
/* PID of process taking the lock */
IDTYPE pid;
/* List node, used internally */
LIST_TYPE(posix_lock) list;
};
/*!
* \brief Set or remove a lock on a file
*
* \param dent the dentry for a file
* \param pl parameters of new lock
* \param wait if true, will wait until a lock can be taken
*
* This is the equivalent of `fnctl(F_SETLK/F_SETLKW)`.
*
* If `pl->type` is `F_UNLCK`, the function will remove any locks held by the given PID for the
* given range. Removing a locks never waits.
*
* If `pl->type` is `F_RDLCK` or `F_WRLCK`, the function will create a new lock for the given PID
* and range, replacing the existing locks held by the given PID for that range. If there are
* conflicting locks, the function either waits (if `wait` is true), or fails with `-EAGAIN` (if
* `wait` is false).
*/
int posix_lock_set(struct shim_dentry* dent, struct posix_lock* pl, bool wait);
/*!
* \brief Check for conflicting locks on a file
*
* \param dent the dentry for a file
* \param pl parameters of new lock (type cannot be `F_UNLCK`)
* \param[out] out_pl on success, set to `F_UNLCK` or details of a conflicting lock
*
* This is the equivalent of `fcntl(F_GETLK)`.
*
* The function checks if there are locks by other PIDs preventing the proposed lock from being
* placed. If the lock could be placed, `out_pl->type` is set to `F_UNLCK`. Otherwise, `out_pl`
* fields (`type`, `start, `end`, `pid`) are set to details of a conflicting lock.
*/
int posix_lock_get(struct shim_dentry* dent, struct posix_lock* pl, struct posix_lock* out_pl);
/* Removes all locks for a given PID. Should be called before process exit. */
int posix_lock_clear_pid(IDTYPE pid);
/* Version of `posix_lock_set` called from IPC callback. */
int posix_lock_set_from_ipc(const char* path, struct posix_lock* pl, bool wait, IDTYPE vmid,
unsigned long seq, bool* postponed);
/* Version of `posix_lock_get` called from IPC callback. */
int posix_lock_get_from_ipc(const char* path, struct posix_lock* pl, struct posix_lock* out_pl);
#endif /* SHIM_FS_LOCK_H */