Commit | Line | Data |
---|---|---|
5970e15d JL |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_FILELOCK_H | |
3 | #define _LINUX_FILELOCK_H | |
4 | ||
5 | #include <linux/fs.h> | |
6 | ||
7 | #define FL_POSIX 1 | |
8 | #define FL_FLOCK 2 | |
9 | #define FL_DELEG 4 /* NFSv4 delegation */ | |
10 | #define FL_ACCESS 8 /* not trying to lock, just looking */ | |
11 | #define FL_EXISTS 16 /* when unlocking, test for existence */ | |
12 | #define FL_LEASE 32 /* lease held on this file */ | |
13 | #define FL_CLOSE 64 /* unlock on close */ | |
14 | #define FL_SLEEP 128 /* A blocking lock */ | |
15 | #define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */ | |
16 | #define FL_UNLOCK_PENDING 512 /* Lease is being broken */ | |
17 | #define FL_OFDLCK 1024 /* lock is "owned" by struct file */ | |
18 | #define FL_LAYOUT 2048 /* outstanding pNFS layout */ | |
19 | #define FL_RECLAIM 4096 /* reclaiming from a reboot server */ | |
20 | ||
21 | #define FL_CLOSE_POSIX (FL_POSIX | FL_CLOSE) | |
22 | ||
23 | /* | |
24 | * Special return value from posix_lock_file() and vfs_lock_file() for | |
25 | * asynchronous locking. | |
26 | */ | |
27 | #define FILE_LOCK_DEFERRED 1 | |
28 | ||
29 | struct file_lock; | |
30 | ||
31 | struct file_lock_operations { | |
32 | void (*fl_copy_lock)(struct file_lock *, struct file_lock *); | |
33 | void (*fl_release_private)(struct file_lock *); | |
34 | }; | |
35 | ||
36 | struct lock_manager_operations { | |
37 | void *lm_mod_owner; | |
38 | fl_owner_t (*lm_get_owner)(fl_owner_t); | |
39 | void (*lm_put_owner)(fl_owner_t); | |
40 | void (*lm_notify)(struct file_lock *); /* unblock callback */ | |
41 | int (*lm_grant)(struct file_lock *, int); | |
42 | bool (*lm_break)(struct file_lock *); | |
43 | int (*lm_change)(struct file_lock *, int, struct list_head *); | |
44 | void (*lm_setup)(struct file_lock *, void **); | |
45 | bool (*lm_breaker_owns_lease)(struct file_lock *); | |
46 | bool (*lm_lock_expirable)(struct file_lock *cfl); | |
47 | void (*lm_expire_lock)(void); | |
48 | }; | |
49 | ||
50 | struct lock_manager { | |
51 | struct list_head list; | |
52 | /* | |
53 | * NFSv4 and up also want opens blocked during the grace period; | |
54 | * NLM doesn't care: | |
55 | */ | |
56 | bool block_opens; | |
57 | }; | |
58 | ||
59 | struct net; | |
60 | void locks_start_grace(struct net *, struct lock_manager *); | |
61 | void locks_end_grace(struct lock_manager *); | |
62 | bool locks_in_grace(struct net *); | |
63 | bool opens_in_grace(struct net *); | |
64 | ||
65 | /* | |
66 | * struct file_lock has a union that some filesystems use to track | |
67 | * their own private info. The NFS side of things is defined here: | |
68 | */ | |
69 | #include <linux/nfs_fs_i.h> | |
70 | ||
71 | /* | |
72 | * struct file_lock represents a generic "file lock". It's used to represent | |
73 | * POSIX byte range locks, BSD (flock) locks, and leases. It's important to | |
74 | * note that the same struct is used to represent both a request for a lock and | |
75 | * the lock itself, but the same object is never used for both. | |
76 | * | |
77 | * FIXME: should we create a separate "struct lock_request" to help distinguish | |
78 | * these two uses? | |
79 | * | |
80 | * The varous i_flctx lists are ordered by: | |
81 | * | |
82 | * 1) lock owner | |
83 | * 2) lock range start | |
84 | * 3) lock range end | |
85 | * | |
86 | * Obviously, the last two criteria only matter for POSIX locks. | |
87 | */ | |
88 | struct file_lock { | |
89 | struct file_lock *fl_blocker; /* The lock, that is blocking us */ | |
90 | struct list_head fl_list; /* link into file_lock_context */ | |
91 | struct hlist_node fl_link; /* node in global lists */ | |
92 | struct list_head fl_blocked_requests; /* list of requests with | |
93 | * ->fl_blocker pointing here | |
94 | */ | |
95 | struct list_head fl_blocked_member; /* node in | |
96 | * ->fl_blocker->fl_blocked_requests | |
97 | */ | |
98 | fl_owner_t fl_owner; | |
99 | unsigned int fl_flags; | |
100 | unsigned char fl_type; | |
101 | unsigned int fl_pid; | |
102 | int fl_link_cpu; /* what cpu's list is this on? */ | |
103 | wait_queue_head_t fl_wait; | |
104 | struct file *fl_file; | |
105 | loff_t fl_start; | |
106 | loff_t fl_end; | |
107 | ||
108 | struct fasync_struct * fl_fasync; /* for lease break notifications */ | |
109 | /* for lease breaks: */ | |
110 | unsigned long fl_break_time; | |
111 | unsigned long fl_downgrade_time; | |
112 | ||
113 | const struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ | |
114 | const struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ | |
115 | union { | |
116 | struct nfs_lock_info nfs_fl; | |
117 | struct nfs4_lock_info nfs4_fl; | |
118 | struct { | |
119 | struct list_head link; /* link in AFS vnode's pending_locks list */ | |
120 | int state; /* state of grant or error if -ve */ | |
121 | unsigned int debug_id; | |
122 | } afs; | |
123 | struct { | |
124 | struct inode *inode; | |
125 | } ceph; | |
126 | } fl_u; | |
127 | } __randomize_layout; | |
128 | ||
129 | struct file_lock_context { | |
130 | spinlock_t flc_lock; | |
131 | struct list_head flc_flock; | |
132 | struct list_head flc_posix; | |
133 | struct list_head flc_lease; | |
134 | }; | |
135 | ||
5970e15d JL |
136 | #ifdef CONFIG_FILE_LOCKING |
137 | int fcntl_getlk(struct file *, unsigned int, struct flock *); | |
138 | int fcntl_setlk(unsigned int, struct file *, unsigned int, | |
139 | struct flock *); | |
140 | ||
141 | #if BITS_PER_LONG == 32 | |
142 | int fcntl_getlk64(struct file *, unsigned int, struct flock64 *); | |
143 | int fcntl_setlk64(unsigned int, struct file *, unsigned int, | |
144 | struct flock64 *); | |
145 | #endif | |
146 | ||
147 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg); | |
148 | int fcntl_getlease(struct file *filp); | |
149 | ||
150 | /* fs/locks.c */ | |
151 | void locks_free_lock_context(struct inode *inode); | |
152 | void locks_free_lock(struct file_lock *fl); | |
153 | void locks_init_lock(struct file_lock *); | |
154 | struct file_lock * locks_alloc_lock(void); | |
155 | void locks_copy_lock(struct file_lock *, struct file_lock *); | |
156 | void locks_copy_conflock(struct file_lock *, struct file_lock *); | |
157 | void locks_remove_posix(struct file *, fl_owner_t); | |
158 | void locks_remove_file(struct file *); | |
159 | void locks_release_private(struct file_lock *); | |
160 | void posix_test_lock(struct file *, struct file_lock *); | |
161 | int posix_lock_file(struct file *, struct file_lock *, struct file_lock *); | |
162 | int locks_delete_block(struct file_lock *); | |
163 | int vfs_test_lock(struct file *, struct file_lock *); | |
164 | int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *); | |
165 | int vfs_cancel_lock(struct file *filp, struct file_lock *fl); | |
166 | bool vfs_inode_has_locks(struct inode *inode); | |
167 | int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl); | |
168 | int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); | |
169 | void lease_get_mtime(struct inode *, struct timespec64 *time); | |
170 | int generic_setlease(struct file *, long, struct file_lock **, void **priv); | |
171 | int vfs_setlease(struct file *, long, struct file_lock **, void **); | |
172 | int lease_modify(struct file_lock *, int, struct list_head *); | |
173 | ||
174 | struct notifier_block; | |
175 | int lease_register_notifier(struct notifier_block *); | |
176 | void lease_unregister_notifier(struct notifier_block *); | |
177 | ||
178 | struct files_struct; | |
179 | void show_fd_locks(struct seq_file *f, | |
180 | struct file *filp, struct files_struct *files); | |
181 | bool locks_owner_has_blockers(struct file_lock_context *flctx, | |
182 | fl_owner_t owner); | |
183 | ||
184 | static inline struct file_lock_context * | |
185 | locks_inode_context(const struct inode *inode) | |
186 | { | |
187 | return smp_load_acquire(&inode->i_flctx); | |
188 | } | |
189 | ||
190 | #else /* !CONFIG_FILE_LOCKING */ | |
191 | static inline int fcntl_getlk(struct file *file, unsigned int cmd, | |
192 | struct flock __user *user) | |
193 | { | |
194 | return -EINVAL; | |
195 | } | |
196 | ||
197 | static inline int fcntl_setlk(unsigned int fd, struct file *file, | |
198 | unsigned int cmd, struct flock __user *user) | |
199 | { | |
200 | return -EACCES; | |
201 | } | |
202 | ||
203 | #if BITS_PER_LONG == 32 | |
204 | static inline int fcntl_getlk64(struct file *file, unsigned int cmd, | |
205 | struct flock64 *user) | |
206 | { | |
207 | return -EINVAL; | |
208 | } | |
209 | ||
210 | static inline int fcntl_setlk64(unsigned int fd, struct file *file, | |
211 | unsigned int cmd, struct flock64 *user) | |
212 | { | |
213 | return -EACCES; | |
214 | } | |
215 | #endif | |
216 | static inline int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | |
217 | { | |
218 | return -EINVAL; | |
219 | } | |
220 | ||
221 | static inline int fcntl_getlease(struct file *filp) | |
222 | { | |
223 | return F_UNLCK; | |
224 | } | |
225 | ||
226 | static inline void | |
227 | locks_free_lock_context(struct inode *inode) | |
228 | { | |
229 | } | |
230 | ||
231 | static inline void locks_init_lock(struct file_lock *fl) | |
232 | { | |
233 | return; | |
234 | } | |
235 | ||
236 | static inline void locks_copy_conflock(struct file_lock *new, struct file_lock *fl) | |
237 | { | |
238 | return; | |
239 | } | |
240 | ||
241 | static inline void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | |
242 | { | |
243 | return; | |
244 | } | |
245 | ||
246 | static inline void locks_remove_posix(struct file *filp, fl_owner_t owner) | |
247 | { | |
248 | return; | |
249 | } | |
250 | ||
251 | static inline void locks_remove_file(struct file *filp) | |
252 | { | |
253 | return; | |
254 | } | |
255 | ||
256 | static inline void posix_test_lock(struct file *filp, struct file_lock *fl) | |
257 | { | |
258 | return; | |
259 | } | |
260 | ||
261 | static inline int posix_lock_file(struct file *filp, struct file_lock *fl, | |
262 | struct file_lock *conflock) | |
263 | { | |
264 | return -ENOLCK; | |
265 | } | |
266 | ||
267 | static inline int locks_delete_block(struct file_lock *waiter) | |
268 | { | |
269 | return -ENOENT; | |
270 | } | |
271 | ||
272 | static inline int vfs_test_lock(struct file *filp, struct file_lock *fl) | |
273 | { | |
274 | return 0; | |
275 | } | |
276 | ||
277 | static inline int vfs_lock_file(struct file *filp, unsigned int cmd, | |
278 | struct file_lock *fl, struct file_lock *conf) | |
279 | { | |
280 | return -ENOLCK; | |
281 | } | |
282 | ||
283 | static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl) | |
284 | { | |
285 | return 0; | |
286 | } | |
287 | ||
288 | static inline bool vfs_inode_has_locks(struct inode *inode) | |
289 | { | |
290 | return false; | |
291 | } | |
292 | ||
293 | static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl) | |
294 | { | |
295 | return -ENOLCK; | |
296 | } | |
297 | ||
298 | static inline int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) | |
299 | { | |
300 | return 0; | |
301 | } | |
302 | ||
303 | static inline void lease_get_mtime(struct inode *inode, | |
304 | struct timespec64 *time) | |
305 | { | |
306 | return; | |
307 | } | |
308 | ||
309 | static inline int generic_setlease(struct file *filp, long arg, | |
310 | struct file_lock **flp, void **priv) | |
311 | { | |
312 | return -EINVAL; | |
313 | } | |
314 | ||
315 | static inline int vfs_setlease(struct file *filp, long arg, | |
316 | struct file_lock **lease, void **priv) | |
317 | { | |
318 | return -EINVAL; | |
319 | } | |
320 | ||
321 | static inline int lease_modify(struct file_lock *fl, int arg, | |
322 | struct list_head *dispose) | |
323 | { | |
324 | return -EINVAL; | |
325 | } | |
326 | ||
327 | struct files_struct; | |
328 | static inline void show_fd_locks(struct seq_file *f, | |
329 | struct file *filp, struct files_struct *files) {} | |
330 | static inline bool locks_owner_has_blockers(struct file_lock_context *flctx, | |
331 | fl_owner_t owner) | |
332 | { | |
333 | return false; | |
334 | } | |
335 | ||
336 | static inline struct file_lock_context * | |
337 | locks_inode_context(const struct inode *inode) | |
338 | { | |
339 | return NULL; | |
340 | } | |
341 | ||
342 | #endif /* !CONFIG_FILE_LOCKING */ | |
343 | ||
344 | static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) | |
345 | { | |
c65454a9 | 346 | return locks_lock_inode_wait(file_inode(filp), fl); |
5970e15d JL |
347 | } |
348 | ||
349 | #ifdef CONFIG_FILE_LOCKING | |
350 | static inline int break_lease(struct inode *inode, unsigned int mode) | |
351 | { | |
352 | /* | |
353 | * Since this check is lockless, we must ensure that any refcounts | |
354 | * taken are done before checking i_flctx->flc_lease. Otherwise, we | |
355 | * could end up racing with tasks trying to set a new lease on this | |
356 | * file. | |
357 | */ | |
358 | smp_mb(); | |
359 | if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) | |
360 | return __break_lease(inode, mode, FL_LEASE); | |
361 | return 0; | |
362 | } | |
363 | ||
364 | static inline int break_deleg(struct inode *inode, unsigned int mode) | |
365 | { | |
366 | /* | |
367 | * Since this check is lockless, we must ensure that any refcounts | |
368 | * taken are done before checking i_flctx->flc_lease. Otherwise, we | |
369 | * could end up racing with tasks trying to set a new lease on this | |
370 | * file. | |
371 | */ | |
372 | smp_mb(); | |
373 | if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) | |
374 | return __break_lease(inode, mode, FL_DELEG); | |
375 | return 0; | |
376 | } | |
377 | ||
378 | static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) | |
379 | { | |
380 | int ret; | |
381 | ||
382 | ret = break_deleg(inode, O_WRONLY|O_NONBLOCK); | |
383 | if (ret == -EWOULDBLOCK && delegated_inode) { | |
384 | *delegated_inode = inode; | |
385 | ihold(inode); | |
386 | } | |
387 | return ret; | |
388 | } | |
389 | ||
390 | static inline int break_deleg_wait(struct inode **delegated_inode) | |
391 | { | |
392 | int ret; | |
393 | ||
394 | ret = break_deleg(*delegated_inode, O_WRONLY); | |
395 | iput(*delegated_inode); | |
396 | *delegated_inode = NULL; | |
397 | return ret; | |
398 | } | |
399 | ||
400 | static inline int break_layout(struct inode *inode, bool wait) | |
401 | { | |
402 | smp_mb(); | |
403 | if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) | |
404 | return __break_lease(inode, | |
405 | wait ? O_WRONLY : O_WRONLY | O_NONBLOCK, | |
406 | FL_LAYOUT); | |
407 | return 0; | |
408 | } | |
409 | ||
410 | #else /* !CONFIG_FILE_LOCKING */ | |
411 | static inline int break_lease(struct inode *inode, unsigned int mode) | |
412 | { | |
413 | return 0; | |
414 | } | |
415 | ||
416 | static inline int break_deleg(struct inode *inode, unsigned int mode) | |
417 | { | |
418 | return 0; | |
419 | } | |
420 | ||
421 | static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) | |
422 | { | |
423 | return 0; | |
424 | } | |
425 | ||
426 | static inline int break_deleg_wait(struct inode **delegated_inode) | |
427 | { | |
428 | BUG(); | |
429 | return 0; | |
430 | } | |
431 | ||
432 | static inline int break_layout(struct inode *inode, bool wait) | |
433 | { | |
434 | return 0; | |
435 | } | |
436 | ||
437 | #endif /* CONFIG_FILE_LOCKING */ | |
438 | ||
439 | #endif /* _LINUX_FILELOCK_H */ |