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 | |
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, int 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 *, int, struct file_lock **, void **priv); |
171 | int vfs_setlease(struct file *, int, 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, int 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, int arg, |
310 | struct file_lock **flp, void **priv) |
311 | { |
312 | return -EINVAL; |
313 | } |
314 | |
315 | static inline int vfs_setlease(struct file *filp, int 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 | { |
346 | return locks_lock_inode_wait(inode: file_inode(f: filp), fl); |
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(head: &inode->i_flctx->flc_lease)) |
360 | return __break_lease(inode, flags: 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(head: &inode->i_flctx->flc_lease)) |
374 | return __break_lease(inode, flags: 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(inode: *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(head: &inode->i_flctx->flc_lease)) |
404 | return __break_lease(inode, |
405 | flags: 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 */ |
440 | |