Blame view
fs/locks.c
73.1 KB
1da177e4c Linux-2.6.12-rc2 |
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 |
/* * linux/fs/locks.c * * Provide support for fcntl()'s F_GETLK, F_SETLK, and F_SETLKW calls. * Doug Evans (dje@spiff.uucp), August 07, 1992 * * Deadlock detection added. * FIXME: one thing isn't handled yet: * - mandatory locks (requires lots of changes elsewhere) * Kelly Carmichael (kelly@[142.24.8.65]), September 17, 1994. * * Miscellaneous edits, and a total rewrite of posix_lock_file() code. * Kai Petzke (wpp@marie.physik.tu-berlin.de), 1994 * * Converted file_lock_table to a linked list from an array, which eliminates * the limits on how many active file locks are open. * Chad Page (pageone@netcom.com), November 27, 1994 * * Removed dependency on file descriptors. dup()'ed file descriptors now * get the same locks as the original file descriptors, and a close() on * any file descriptor removes ALL the locks on the file for the current * process. Since locks still depend on the process id, locks are inherited * after an exec() but not after a fork(). This agrees with POSIX, and both * BSD and SVR4 practice. * Andy Walker (andy@lysaker.kvaerner.no), February 14, 1995 * * Scrapped free list which is redundant now that we allocate locks * dynamically with kmalloc()/kfree(). * Andy Walker (andy@lysaker.kvaerner.no), February 21, 1995 * * Implemented two lock personalities - FL_FLOCK and FL_POSIX. * * FL_POSIX locks are created with calls to fcntl() and lockf() through the * fcntl() system call. They have the semantics described above. * * FL_FLOCK locks are created with calls to flock(), through the flock() * system call, which is new. Old C libraries implement flock() via fcntl() * and will continue to use the old, broken implementation. * * FL_FLOCK locks follow the 4.4 BSD flock() semantics. They are associated * with a file pointer (filp). As a result they can be shared by a parent * process and its children after a fork(). They are removed when the last * file descriptor referring to the file pointer is closed (unless explicitly * unlocked). * * FL_FLOCK locks never deadlock, an existing lock is always removed before * upgrading from shared to exclusive (or vice versa). When this happens * any processes blocked by the current lock are woken up and allowed to * run before the new lock is applied. * Andy Walker (andy@lysaker.kvaerner.no), June 09, 1995 * * Removed some race conditions in flock_lock_file(), marked other possible * races. Just grep for FIXME to see them. * Dmitry Gorodchanin (pgmdsg@ibi.com), February 09, 1996. * * Addressed Dmitry's concerns. Deadlock checking no longer recursive. * Lock allocation changed to GFP_ATOMIC as we can't afford to sleep * once we've checked for blocking and deadlocking. * Andy Walker (andy@lysaker.kvaerner.no), April 03, 1996. * * Initial implementation of mandatory locks. SunOS turned out to be * a rotten model, so I implemented the "obvious" semantics. |
395cf9691 doc: fix broken r... |
63 |
* See 'Documentation/filesystems/mandatory-locking.txt' for details. |
1da177e4c Linux-2.6.12-rc2 |
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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
* Andy Walker (andy@lysaker.kvaerner.no), April 06, 1996. * * Don't allow mandatory locks on mmap()'ed files. Added simple functions to * check if a file has mandatory locks, used by mmap(), open() and creat() to * see if system call should be rejected. Ref. HP-UX/SunOS/Solaris Reference * Manual, Section 2. * Andy Walker (andy@lysaker.kvaerner.no), April 09, 1996. * * Tidied up block list handling. Added '/proc/locks' interface. * Andy Walker (andy@lysaker.kvaerner.no), April 24, 1996. * * Fixed deadlock condition for pathological code that mixes calls to * flock() and fcntl(). * Andy Walker (andy@lysaker.kvaerner.no), April 29, 1996. * * Allow only one type of locking scheme (FL_POSIX or FL_FLOCK) to be in use * for a given file at a time. Changed the CONFIG_LOCK_MANDATORY scheme to * guarantee sensible behaviour in the case where file system modules might * be compiled with different options than the kernel itself. * Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996. * * Added a couple of missing wake_up() calls. Thanks to Thomas Meckel * (Thomas.Meckel@mni.fh-giessen.de) for spotting this. * Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996. * * Changed FL_POSIX locks to use the block list in the same way as FL_FLOCK * locks. Changed process synchronisation to avoid dereferencing locks that * have already been freed. * Andy Walker (andy@lysaker.kvaerner.no), Sep 21, 1996. * * Made the block list a circular list to minimise searching in the list. * Andy Walker (andy@lysaker.kvaerner.no), Sep 25, 1996. * * Made mandatory locking a mount option. Default is not to allow mandatory * locking. * Andy Walker (andy@lysaker.kvaerner.no), Oct 04, 1996. * * Some adaptations for NFS support. * Olaf Kirch (okir@monad.swb.de), Dec 1996, * * Fixed /proc/locks interface so that we can't overrun the buffer we are handed. * Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997. * * Use slab allocator instead of kmalloc/kfree. * Use generic list implementation from <linux/list.h>. * Sped up posix_locks_deadlock by only considering blocked locks. * Matthew Wilcox <willy@debian.org>, March, 2000. * * Leases and LOCK_MAND * Matthew Wilcox <willy@debian.org>, June, 2000. * Stephen Rothwell <sfr@canb.auug.org.au>, June, 2000. */ #include <linux/capability.h> #include <linux/file.h> |
9f3acc314 [PATCH] split lin... |
119 |
#include <linux/fdtable.h> |
1da177e4c Linux-2.6.12-rc2 |
120 121 |
#include <linux/fs.h> #include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
122 123 |
#include <linux/security.h> #include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
124 125 |
#include <linux/syscalls.h> #include <linux/time.h> |
4fb3a5386 [PATCH] files: fi... |
126 |
#include <linux/rcupdate.h> |
ab1f16116 pid-namespaces-vs... |
127 |
#include <linux/pid_namespace.h> |
48f741865 locks: turn the b... |
128 |
#include <linux/hashtable.h> |
7012b02a2 locks: move file_... |
129 |
#include <linux/percpu.h> |
1da177e4c Linux-2.6.12-rc2 |
130 |
|
62af4f1f7 locks: add some t... |
131 132 |
#define CREATE_TRACE_POINTS #include <trace/events/filelock.h> |
7c0f6ba68 Replace <asm/uacc... |
133 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 |
#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) |
11afe9f76 fs: add FL_LAYOUT... |
137 |
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT)) |
cff2fce58 locks: rename FL_... |
138 |
#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK) |
9d5b86ac1 fs/locks: Remove ... |
139 |
#define IS_REMOTELCK(fl) (fl->fl_pid <= 0) |
1da177e4c Linux-2.6.12-rc2 |
140 |
|
ab83fa4b4 locks: minor leas... |
141 142 |
static bool lease_breaking(struct file_lock *fl) { |
778fc546f locks: fix tracki... |
143 144 145 146 147 148 149 150 151 152 |
return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING); } static int target_leasetype(struct file_lock *fl) { if (fl->fl_flags & FL_UNLOCK_PENDING) return F_UNLCK; if (fl->fl_flags & FL_DOWNGRADE_PENDING) return F_RDLCK; return fl->fl_type; |
ab83fa4b4 locks: minor leas... |
153 |
} |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
int leases_enable = 1; int lease_break_time = 45; |
1c8c601a8 locks: protect mo... |
156 |
/* |
7012b02a2 locks: move file_... |
157 |
* The global file_lock_list is only used for displaying /proc/locks, so we |
7c3f654d8 fs/locks: Replace... |
158 159 160 161 162 |
* keep a list on each CPU, with each list protected by its own spinlock. * Global serialization is done using file_rwsem. * * Note that alterations to the list also require that the relevant flc_lock is * held. |
1c8c601a8 locks: protect mo... |
163 |
*/ |
7c3f654d8 fs/locks: Replace... |
164 165 166 167 168 |
struct file_lock_list_struct { spinlock_t lock; struct hlist_head hlist; }; static DEFINE_PER_CPU(struct file_lock_list_struct, file_lock_list); |
aba376607 fs/locks: Replace... |
169 |
DEFINE_STATIC_PERCPU_RWSEM(file_rwsem); |
889746917 locks: encapsulat... |
170 |
|
1c8c601a8 locks: protect mo... |
171 |
/* |
48f741865 locks: turn the b... |
172 |
* The blocked_hash is used to find POSIX lock loops for deadlock detection. |
7b2296afb locks: give the b... |
173 |
* It is protected by blocked_lock_lock. |
48f741865 locks: turn the b... |
174 175 176 177 178 179 180 |
* * We hash locks by lockowner in order to optimize searching for the lock a * particular lockowner is waiting on. * * FIXME: make this value scale via some heuristic? We generally will want more * buckets when we have more lockowners holding locks, but that's a little * difficult to determine without knowing what the workload will look like. |
1c8c601a8 locks: protect mo... |
181 |
*/ |
48f741865 locks: turn the b... |
182 183 |
#define BLOCKED_HASH_BITS 7 static DEFINE_HASHTABLE(blocked_hash, BLOCKED_HASH_BITS); |
889746917 locks: encapsulat... |
184 |
|
1c8c601a8 locks: protect mo... |
185 |
/* |
7b2296afb locks: give the b... |
186 187 |
* This lock protects the blocked_hash. Generally, if you're accessing it, you * want to be holding this lock. |
1c8c601a8 locks: protect mo... |
188 189 190 191 192 193 |
* * In addition, it also protects the fl->fl_block list, and the fl->fl_next * pointer for file_lock structures that are acting as lock requests (in * contrast to those that are acting as records of acquired locks). * * Note that when we acquire this lock in order to change the above fields, |
6109c8503 locks: add a dedi... |
194 |
* we often hold the flc_lock as well. In certain cases, when reading the fields |
1c8c601a8 locks: protect mo... |
195 |
* protected by this lock, we can skip acquiring it iff we already hold the |
6109c8503 locks: add a dedi... |
196 |
* flc_lock. |
1c8c601a8 locks: protect mo... |
197 |
*/ |
7b2296afb locks: give the b... |
198 |
static DEFINE_SPINLOCK(blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
199 |
|
4a075e39c locks: add a new ... |
200 |
static struct kmem_cache *flctx_cache __read_mostly; |
e18b890bb [PATCH] slab: rem... |
201 |
static struct kmem_cache *filelock_cache __read_mostly; |
1da177e4c Linux-2.6.12-rc2 |
202 |
|
4a075e39c locks: add a new ... |
203 |
static struct file_lock_context * |
5c1c669a1 locks: don't allo... |
204 |
locks_get_lock_context(struct inode *inode, int type) |
4a075e39c locks: add a new ... |
205 |
{ |
128a37852 fs: fix data race... |
206 |
struct file_lock_context *ctx; |
4a075e39c locks: add a new ... |
207 |
|
128a37852 fs: fix data race... |
208 209 210 |
/* paired with cmpxchg() below */ ctx = smp_load_acquire(&inode->i_flctx); if (likely(ctx) || type == F_UNLCK) |
4a075e39c locks: add a new ... |
211 |
goto out; |
128a37852 fs: fix data race... |
212 213 |
ctx = kmem_cache_alloc(flctx_cache, GFP_KERNEL); if (!ctx) |
4a075e39c locks: add a new ... |
214 |
goto out; |
128a37852 fs: fix data race... |
215 216 217 218 |
spin_lock_init(&ctx->flc_lock); INIT_LIST_HEAD(&ctx->flc_flock); INIT_LIST_HEAD(&ctx->flc_posix); INIT_LIST_HEAD(&ctx->flc_lease); |
4a075e39c locks: add a new ... |
219 220 221 222 223 |
/* * Assign the pointer if it's not already assigned. If it is, then * free the context we just allocated. */ |
128a37852 fs: fix data race... |
224 225 226 227 |
if (cmpxchg(&inode->i_flctx, NULL, ctx)) { kmem_cache_free(flctx_cache, ctx); ctx = smp_load_acquire(&inode->i_flctx); } |
4a075e39c locks: add a new ... |
228 |
out: |
1890910fd locks: sprinkle s... |
229 |
trace_locks_get_lock_context(inode, type, ctx); |
128a37852 fs: fix data race... |
230 |
return ctx; |
4a075e39c locks: add a new ... |
231 |
} |
e24dadab0 locks: prink more... |
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
static void locks_dump_ctx_list(struct list_head *list, char *list_type) { struct file_lock *fl; list_for_each_entry(fl, list, fl_list) { pr_warn("%s: fl_owner=%p fl_flags=0x%x fl_type=0x%x fl_pid=%u ", list_type, fl->fl_owner, fl->fl_flags, fl->fl_type, fl->fl_pid); } } static void locks_check_ctx_lists(struct inode *inode) { struct file_lock_context *ctx = inode->i_flctx; if (unlikely(!list_empty(&ctx->flc_flock) || !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_lease))) { pr_warn("Leaked locks on dev=0x%x:0x%x ino=0x%lx: ", MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), inode->i_ino); locks_dump_ctx_list(&ctx->flc_flock, "FLOCK"); locks_dump_ctx_list(&ctx->flc_posix, "POSIX"); locks_dump_ctx_list(&ctx->flc_lease, "LEASE"); } } |
3953704fd locks: restore a ... |
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
static void locks_check_ctx_file_list(struct file *filp, struct list_head *list, char *list_type) { struct file_lock *fl; struct inode *inode = locks_inode(filp); list_for_each_entry(fl, list, fl_list) if (fl->fl_file == filp) pr_warn("Leaked %s lock on dev=0x%x:0x%x ino=0x%lx " " fl_owner=%p fl_flags=0x%x fl_type=0x%x fl_pid=%u ", list_type, MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), inode->i_ino, fl->fl_owner, fl->fl_flags, fl->fl_type, fl->fl_pid); } |
4a075e39c locks: add a new ... |
276 |
void |
f27a0fe08 locks: pass inode... |
277 |
locks_free_lock_context(struct inode *inode) |
4a075e39c locks: add a new ... |
278 |
{ |
f27a0fe08 locks: pass inode... |
279 |
struct file_lock_context *ctx = inode->i_flctx; |
e24dadab0 locks: prink more... |
280 281 |
if (unlikely(ctx)) { locks_check_ctx_lists(inode); |
4a075e39c locks: add a new ... |
282 283 284 |
kmem_cache_free(flctx_cache, ctx); } } |
ee19cc406 fs: locks: remove... |
285 |
static void locks_init_lock_heads(struct file_lock *fl) |
a51cb91d8 fs: fix lock init... |
286 |
{ |
139ca04ee locks: convert fl... |
287 |
INIT_HLIST_NODE(&fl->fl_link); |
6dee60f69 locks: add new st... |
288 |
INIT_LIST_HEAD(&fl->fl_list); |
ee19cc406 fs: locks: remove... |
289 290 |
INIT_LIST_HEAD(&fl->fl_block); init_waitqueue_head(&fl->fl_wait); |
a51cb91d8 fs: fix lock init... |
291 |
} |
1da177e4c Linux-2.6.12-rc2 |
292 |
/* Allocate an empty lock structure. */ |
c5b1f0d92 locks/nfsd: alloc... |
293 |
struct file_lock *locks_alloc_lock(void) |
1da177e4c Linux-2.6.12-rc2 |
294 |
{ |
ee19cc406 fs: locks: remove... |
295 |
struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL); |
a51cb91d8 fs: fix lock init... |
296 297 |
if (fl) |
ee19cc406 fs: locks: remove... |
298 |
locks_init_lock_heads(fl); |
a51cb91d8 fs: fix lock init... |
299 300 |
return fl; |
1da177e4c Linux-2.6.12-rc2 |
301 |
} |
c5b1f0d92 locks/nfsd: alloc... |
302 |
EXPORT_SYMBOL_GPL(locks_alloc_lock); |
1da177e4c Linux-2.6.12-rc2 |
303 |
|
a9e61e25f lockd: call locks... |
304 |
void locks_release_private(struct file_lock *fl) |
47831f35b VFS: Fix __posix_... |
305 306 307 308 309 310 |
{ if (fl->fl_ops) { if (fl->fl_ops->fl_release_private) fl->fl_ops->fl_release_private(fl); fl->fl_ops = NULL; } |
47831f35b VFS: Fix __posix_... |
311 |
|
5c97d7b14 locks: New ops in... |
312 |
if (fl->fl_lmops) { |
cae80b305 locks: change lm_... |
313 314 315 316 |
if (fl->fl_lmops->lm_put_owner) { fl->fl_lmops->lm_put_owner(fl->fl_owner); fl->fl_owner = NULL; } |
5c97d7b14 locks: New ops in... |
317 318 |
fl->fl_lmops = NULL; } |
47831f35b VFS: Fix __posix_... |
319 |
} |
a9e61e25f lockd: call locks... |
320 |
EXPORT_SYMBOL_GPL(locks_release_private); |
47831f35b VFS: Fix __posix_... |
321 |
|
1da177e4c Linux-2.6.12-rc2 |
322 |
/* Free a lock which is not in use. */ |
05fa3135f locks: fix setlea... |
323 |
void locks_free_lock(struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
324 |
{ |
5ce29646e [PATCH] locks: do... |
325 |
BUG_ON(waitqueue_active(&fl->fl_wait)); |
6dee60f69 locks: add new st... |
326 |
BUG_ON(!list_empty(&fl->fl_list)); |
5ce29646e [PATCH] locks: do... |
327 |
BUG_ON(!list_empty(&fl->fl_block)); |
139ca04ee locks: convert fl... |
328 |
BUG_ON(!hlist_unhashed(&fl->fl_link)); |
1da177e4c Linux-2.6.12-rc2 |
329 |
|
47831f35b VFS: Fix __posix_... |
330 |
locks_release_private(fl); |
1da177e4c Linux-2.6.12-rc2 |
331 332 |
kmem_cache_free(filelock_cache, fl); } |
05fa3135f locks: fix setlea... |
333 |
EXPORT_SYMBOL(locks_free_lock); |
1da177e4c Linux-2.6.12-rc2 |
334 |
|
ed9814d85 locks: defer free... |
335 336 337 338 339 340 |
static void locks_dispose_list(struct list_head *dispose) { struct file_lock *fl; while (!list_empty(dispose)) { |
6dee60f69 locks: add new st... |
341 342 |
fl = list_first_entry(dispose, struct file_lock, fl_list); list_del_init(&fl->fl_list); |
ed9814d85 locks: defer free... |
343 344 345 |
locks_free_lock(fl); } } |
1da177e4c Linux-2.6.12-rc2 |
346 347 |
void locks_init_lock(struct file_lock *fl) { |
ee19cc406 fs: locks: remove... |
348 349 |
memset(fl, 0, sizeof(struct file_lock)); locks_init_lock_heads(fl); |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 |
} EXPORT_SYMBOL(locks_init_lock); |
1da177e4c Linux-2.6.12-rc2 |
353 354 355 |
/* * Initialize a new lock from an existing file_lock structure. */ |
3fe0fff18 locks: Rename __l... |
356 |
void locks_copy_conflock(struct file_lock *new, struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
357 358 359 |
{ new->fl_owner = fl->fl_owner; new->fl_pid = fl->fl_pid; |
0996905f9 lockd: posix_test... |
360 |
new->fl_file = NULL; |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
new->fl_flags = fl->fl_flags; new->fl_type = fl->fl_type; new->fl_start = fl->fl_start; new->fl_end = fl->fl_end; |
f328296e2 locks: Copy fl_lm... |
365 |
new->fl_lmops = fl->fl_lmops; |
0996905f9 lockd: posix_test... |
366 |
new->fl_ops = NULL; |
f328296e2 locks: Copy fl_lm... |
367 368 369 |
if (fl->fl_lmops) { if (fl->fl_lmops->lm_get_owner) |
cae80b305 locks: change lm_... |
370 |
fl->fl_lmops->lm_get_owner(fl->fl_owner); |
f328296e2 locks: Copy fl_lm... |
371 |
} |
0996905f9 lockd: posix_test... |
372 |
} |
3fe0fff18 locks: Rename __l... |
373 |
EXPORT_SYMBOL(locks_copy_conflock); |
0996905f9 lockd: posix_test... |
374 375 376 |
void locks_copy_lock(struct file_lock *new, struct file_lock *fl) { |
566709bd6 locks: don't call... |
377 378 |
/* "new" must be a freshly-initialized lock */ WARN_ON_ONCE(new->fl_ops); |
0996905f9 lockd: posix_test... |
379 |
|
3fe0fff18 locks: Rename __l... |
380 |
locks_copy_conflock(new, fl); |
f328296e2 locks: Copy fl_lm... |
381 |
|
0996905f9 lockd: posix_test... |
382 |
new->fl_file = fl->fl_file; |
1da177e4c Linux-2.6.12-rc2 |
383 |
new->fl_ops = fl->fl_ops; |
47831f35b VFS: Fix __posix_... |
384 |
|
f328296e2 locks: Copy fl_lm... |
385 386 387 388 |
if (fl->fl_ops) { if (fl->fl_ops->fl_copy_lock) fl->fl_ops->fl_copy_lock(new, fl); } |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
} EXPORT_SYMBOL(locks_copy_lock); static inline int flock_translate_cmd(int cmd) { if (cmd & LOCK_MAND) return cmd & (LOCK_MAND | LOCK_RW); switch (cmd) { case LOCK_SH: return F_RDLCK; case LOCK_EX: return F_WRLCK; case LOCK_UN: return F_UNLCK; } return -EINVAL; } /* Fill in a file_lock structure with an appropriate FLOCK lock. */ |
6e129d006 locks: flock_make... |
408 409 |
static struct file_lock * flock_make_lock(struct file *filp, unsigned int cmd) |
1da177e4c Linux-2.6.12-rc2 |
410 411 412 |
{ struct file_lock *fl; int type = flock_translate_cmd(cmd); |
6e129d006 locks: flock_make... |
413 |
|
1da177e4c Linux-2.6.12-rc2 |
414 |
if (type < 0) |
6e129d006 locks: flock_make... |
415 |
return ERR_PTR(type); |
1da177e4c Linux-2.6.12-rc2 |
416 417 418 |
fl = locks_alloc_lock(); if (fl == NULL) |
6e129d006 locks: flock_make... |
419 |
return ERR_PTR(-ENOMEM); |
1da177e4c Linux-2.6.12-rc2 |
420 421 |
fl->fl_file = filp; |
73a8f5f7e locks: purge fl_o... |
422 |
fl->fl_owner = filp; |
1da177e4c Linux-2.6.12-rc2 |
423 424 425 426 427 |
fl->fl_pid = current->tgid; fl->fl_flags = FL_FLOCK; fl->fl_type = type; fl->fl_end = OFFSET_MAX; |
6e129d006 locks: flock_make... |
428 |
return fl; |
1da177e4c Linux-2.6.12-rc2 |
429 |
} |
0ec4f431e locks: fix checki... |
430 |
static int assign_type(struct file_lock *fl, long type) |
1da177e4c Linux-2.6.12-rc2 |
431 432 433 434 435 436 437 438 439 440 441 442 |
{ switch (type) { case F_RDLCK: case F_WRLCK: case F_UNLCK: fl->fl_type = type; break; default: return -EINVAL; } return 0; } |
ef12e72a0 locks: fix posix ... |
443 444 |
static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, struct flock64 *l) |
1da177e4c Linux-2.6.12-rc2 |
445 |
{ |
1da177e4c Linux-2.6.12-rc2 |
446 |
switch (l->l_whence) { |
f5579f8c7 [PATCH] VFS: Use ... |
447 |
case SEEK_SET: |
ef12e72a0 locks: fix posix ... |
448 |
fl->fl_start = 0; |
1da177e4c Linux-2.6.12-rc2 |
449 |
break; |
f5579f8c7 [PATCH] VFS: Use ... |
450 |
case SEEK_CUR: |
ef12e72a0 locks: fix posix ... |
451 |
fl->fl_start = filp->f_pos; |
1da177e4c Linux-2.6.12-rc2 |
452 |
break; |
f5579f8c7 [PATCH] VFS: Use ... |
453 |
case SEEK_END: |
ef12e72a0 locks: fix posix ... |
454 |
fl->fl_start = i_size_read(file_inode(filp)); |
1da177e4c Linux-2.6.12-rc2 |
455 456 457 458 |
break; default: return -EINVAL; } |
ef12e72a0 locks: fix posix ... |
459 460 461 462 463 |
if (l->l_start > OFFSET_MAX - fl->fl_start) return -EOVERFLOW; fl->fl_start += l->l_start; if (fl->fl_start < 0) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 |
/* POSIX-1996 leaves the case l->l_len < 0 undefined; POSIX-2001 defines it. */ |
4c780a468 Fix Connectathon ... |
467 |
if (l->l_len > 0) { |
ef12e72a0 locks: fix posix ... |
468 469 470 |
if (l->l_len - 1 > OFFSET_MAX - fl->fl_start) return -EOVERFLOW; fl->fl_end = fl->fl_start + l->l_len - 1; |
4c780a468 Fix Connectathon ... |
471 |
} else if (l->l_len < 0) { |
ef12e72a0 locks: fix posix ... |
472 |
if (fl->fl_start + l->l_len < 0) |
4c780a468 Fix Connectathon ... |
473 |
return -EINVAL; |
ef12e72a0 locks: fix posix ... |
474 475 476 477 |
fl->fl_end = fl->fl_start - 1; fl->fl_start += l->l_len; } else fl->fl_end = OFFSET_MAX; |
1da177e4c Linux-2.6.12-rc2 |
478 479 480 481 482 483 484 485 486 |
fl->fl_owner = current->files; fl->fl_pid = current->tgid; fl->fl_file = filp; fl->fl_flags = FL_POSIX; fl->fl_ops = NULL; fl->fl_lmops = NULL; return assign_type(fl, l->l_type); } |
ef12e72a0 locks: fix posix ... |
487 488 489 490 491 |
/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX * style lock. */ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, struct flock *l) |
1da177e4c Linux-2.6.12-rc2 |
492 |
{ |
ef12e72a0 locks: fix posix ... |
493 494 495 496 497 498 499 500 |
struct flock64 ll = { .l_type = l->l_type, .l_whence = l->l_whence, .l_start = l->l_start, .l_len = l->l_len, }; return flock64_to_posix_lock(filp, fl, &ll); |
1da177e4c Linux-2.6.12-rc2 |
501 |
} |
1da177e4c Linux-2.6.12-rc2 |
502 503 |
/* default lease lock manager operations */ |
4d01b7f5e locks: give lm_br... |
504 505 |
static bool lease_break_callback(struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
506 507 |
{ kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); |
4d01b7f5e locks: give lm_br... |
508 |
return false; |
1da177e4c Linux-2.6.12-rc2 |
509 |
} |
1c7dd2ff4 locks: define a l... |
510 511 512 513 514 515 516 517 518 519 520 521 522 |
static void lease_setup(struct file_lock *fl, void **priv) { struct file *filp = fl->fl_file; struct fasync_struct *fa = *priv; /* * fasync_insert_entry() returns the old entry if any. If there was no * old entry, then it used "priv" and inserted it into the fasync list. * Clear the pointer to indicate that it shouldn't be freed. */ if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa)) *priv = NULL; |
019191342 signal: Use PIDTY... |
523 |
__f_setown(filp, task_pid(current), PIDTYPE_TGID, 0); |
1c7dd2ff4 locks: define a l... |
524 |
} |
7b021967c const: make lock_... |
525 |
static const struct lock_manager_operations lease_manager_ops = { |
8fb47a4fb locks: rename loc... |
526 |
.lm_break = lease_break_callback, |
8fb47a4fb locks: rename loc... |
527 |
.lm_change = lease_modify, |
1c7dd2ff4 locks: define a l... |
528 |
.lm_setup = lease_setup, |
1da177e4c Linux-2.6.12-rc2 |
529 530 531 532 533 |
}; /* * Initialize a lease, use the default lock manager operations */ |
0ec4f431e locks: fix checki... |
534 |
static int lease_init(struct file *filp, long type, struct file_lock *fl) |
447a5647c treewide: Align f... |
535 |
{ |
75dff55af [PATCH] fs/locks.... |
536 537 |
if (assign_type(fl, type) != 0) return -EINVAL; |
7ca76311f locks: set fl_own... |
538 |
fl->fl_owner = filp; |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 542 |
fl->fl_pid = current->tgid; fl->fl_file = filp; fl->fl_flags = FL_LEASE; |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 548 549 550 |
fl->fl_start = 0; fl->fl_end = OFFSET_MAX; fl->fl_ops = NULL; fl->fl_lmops = &lease_manager_ops; return 0; } /* Allocate a file_lock initialised to this type of lease */ |
0ec4f431e locks: fix checki... |
551 |
static struct file_lock *lease_alloc(struct file *filp, long type) |
1da177e4c Linux-2.6.12-rc2 |
552 553 |
{ struct file_lock *fl = locks_alloc_lock(); |
75dff55af [PATCH] fs/locks.... |
554 |
int error = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
555 556 |
if (fl == NULL) |
e32b8ee27 locks: clean up l... |
557 |
return ERR_PTR(error); |
1da177e4c Linux-2.6.12-rc2 |
558 559 |
error = lease_init(filp, type, fl); |
75dff55af [PATCH] fs/locks.... |
560 561 |
if (error) { locks_free_lock(fl); |
e32b8ee27 locks: clean up l... |
562 |
return ERR_PTR(error); |
75dff55af [PATCH] fs/locks.... |
563 |
} |
e32b8ee27 locks: clean up l... |
564 |
return fl; |
1da177e4c Linux-2.6.12-rc2 |
565 566 567 568 569 570 571 572 573 574 575 576 577 |
} /* Check if two locks overlap each other. */ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2) { return ((fl1->fl_end >= fl2->fl_start) && (fl2->fl_end >= fl1->fl_start)); } /* * Check whether two locks have the same owner. */ |
33443c42f [PATCH] tiny: Uni... |
578 |
static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2) |
1da177e4c Linux-2.6.12-rc2 |
579 |
{ |
8fb47a4fb locks: rename loc... |
580 |
if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner) |
1da177e4c Linux-2.6.12-rc2 |
581 |
return fl2->fl_lmops == fl1->fl_lmops && |
8fb47a4fb locks: rename loc... |
582 |
fl1->fl_lmops->lm_compare_owner(fl1, fl2); |
1da177e4c Linux-2.6.12-rc2 |
583 584 |
return fl1->fl_owner == fl2->fl_owner; } |
6109c8503 locks: add a dedi... |
585 |
/* Must be called with the flc_lock held! */ |
6ca10ed8e locks: remove "in... |
586 |
static void locks_insert_global_locks(struct file_lock *fl) |
889746917 locks: encapsulat... |
587 |
{ |
7c3f654d8 fs/locks: Replace... |
588 |
struct file_lock_list_struct *fll = this_cpu_ptr(&file_lock_list); |
aba376607 fs/locks: Replace... |
589 |
percpu_rwsem_assert_held(&file_rwsem); |
7c3f654d8 fs/locks: Replace... |
590 |
spin_lock(&fll->lock); |
7012b02a2 locks: move file_... |
591 |
fl->fl_link_cpu = smp_processor_id(); |
7c3f654d8 fs/locks: Replace... |
592 593 |
hlist_add_head(&fl->fl_link, &fll->hlist); spin_unlock(&fll->lock); |
889746917 locks: encapsulat... |
594 |
} |
6109c8503 locks: add a dedi... |
595 |
/* Must be called with the flc_lock held! */ |
6ca10ed8e locks: remove "in... |
596 |
static void locks_delete_global_locks(struct file_lock *fl) |
889746917 locks: encapsulat... |
597 |
{ |
7c3f654d8 fs/locks: Replace... |
598 |
struct file_lock_list_struct *fll; |
aba376607 fs/locks: Replace... |
599 |
percpu_rwsem_assert_held(&file_rwsem); |
7012b02a2 locks: move file_... |
600 601 |
/* * Avoid taking lock if already unhashed. This is safe since this check |
6109c8503 locks: add a dedi... |
602 |
* is done while holding the flc_lock, and new insertions into the list |
7012b02a2 locks: move file_... |
603 604 605 606 |
* also require that it be held. */ if (hlist_unhashed(&fl->fl_link)) return; |
7c3f654d8 fs/locks: Replace... |
607 608 609 |
fll = per_cpu_ptr(&file_lock_list, fl->fl_link_cpu); spin_lock(&fll->lock); |
139ca04ee locks: convert fl... |
610 |
hlist_del_init(&fl->fl_link); |
7c3f654d8 fs/locks: Replace... |
611 |
spin_unlock(&fll->lock); |
889746917 locks: encapsulat... |
612 |
} |
3999e4936 locks: add a new ... |
613 614 615 616 617 618 619 |
static unsigned long posix_owner_key(struct file_lock *fl) { if (fl->fl_lmops && fl->fl_lmops->lm_owner_key) return fl->fl_lmops->lm_owner_key(fl); return (unsigned long)fl->fl_owner; } |
6ca10ed8e locks: remove "in... |
620 |
static void locks_insert_global_blocked(struct file_lock *waiter) |
889746917 locks: encapsulat... |
621 |
{ |
663d5af75 locks: Add lockde... |
622 |
lockdep_assert_held(&blocked_lock_lock); |
3999e4936 locks: add a new ... |
623 |
hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter)); |
889746917 locks: encapsulat... |
624 |
} |
6ca10ed8e locks: remove "in... |
625 |
static void locks_delete_global_blocked(struct file_lock *waiter) |
889746917 locks: encapsulat... |
626 |
{ |
663d5af75 locks: Add lockde... |
627 |
lockdep_assert_held(&blocked_lock_lock); |
48f741865 locks: turn the b... |
628 |
hash_del(&waiter->fl_link); |
889746917 locks: encapsulat... |
629 |
} |
1da177e4c Linux-2.6.12-rc2 |
630 631 |
/* Remove waiter from blocker's block list. * When blocker ends up pointing to itself then the list is empty. |
1c8c601a8 locks: protect mo... |
632 |
* |
7b2296afb locks: give the b... |
633 |
* Must be called with blocked_lock_lock held. |
1da177e4c Linux-2.6.12-rc2 |
634 |
*/ |
33443c42f [PATCH] tiny: Uni... |
635 |
static void __locks_delete_block(struct file_lock *waiter) |
1da177e4c Linux-2.6.12-rc2 |
636 |
{ |
889746917 locks: encapsulat... |
637 |
locks_delete_global_blocked(waiter); |
1da177e4c Linux-2.6.12-rc2 |
638 |
list_del_init(&waiter->fl_block); |
1da177e4c Linux-2.6.12-rc2 |
639 640 |
waiter->fl_next = NULL; } |
1a9e64a71 cifs: use posix_u... |
641 |
static void locks_delete_block(struct file_lock *waiter) |
1da177e4c Linux-2.6.12-rc2 |
642 |
{ |
7b2296afb locks: give the b... |
643 |
spin_lock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
644 |
__locks_delete_block(waiter); |
7b2296afb locks: give the b... |
645 |
spin_unlock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
646 647 648 649 650 651 |
} /* Insert waiter into blocker's block list. * We use a circular list so that processes can be easily woken up in * the order they blocked. The documentation doesn't require this but * it seems like the reasonable thing to do. |
1c8c601a8 locks: protect mo... |
652 |
* |
6109c8503 locks: add a dedi... |
653 654 655 656 |
* Must be called with both the flc_lock and blocked_lock_lock held. The * fl_block list itself is protected by the blocked_lock_lock, but by ensuring * that the flc_lock is also held on insertions we can avoid taking the * blocked_lock_lock in some cases when we see that the fl_block list is empty. |
1da177e4c Linux-2.6.12-rc2 |
657 |
*/ |
1c8c601a8 locks: protect mo... |
658 659 |
static void __locks_insert_block(struct file_lock *blocker, struct file_lock *waiter) |
1da177e4c Linux-2.6.12-rc2 |
660 |
{ |
6dc0fe8f8 [PATCH] VFS,fs/lo... |
661 |
BUG_ON(!list_empty(&waiter->fl_block)); |
1da177e4c Linux-2.6.12-rc2 |
662 |
waiter->fl_next = blocker; |
889746917 locks: encapsulat... |
663 |
list_add_tail(&waiter->fl_block, &blocker->fl_block); |
cff2fce58 locks: rename FL_... |
664 |
if (IS_POSIX(blocker) && !IS_OFDLCK(blocker)) |
1c8c601a8 locks: protect mo... |
665 666 |
locks_insert_global_blocked(waiter); } |
6109c8503 locks: add a dedi... |
667 |
/* Must be called with flc_lock held. */ |
1c8c601a8 locks: protect mo... |
668 669 670 |
static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter) { |
7b2296afb locks: give the b... |
671 |
spin_lock(&blocked_lock_lock); |
1c8c601a8 locks: protect mo... |
672 |
__locks_insert_block(blocker, waiter); |
7b2296afb locks: give the b... |
673 |
spin_unlock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
674 |
} |
1cb360125 locks: comment cl... |
675 676 677 |
/* * Wake up processes blocked waiting for blocker. * |
6109c8503 locks: add a dedi... |
678 |
* Must be called with the inode->flc_lock held! |
1da177e4c Linux-2.6.12-rc2 |
679 680 681 |
*/ static void locks_wake_up_blocks(struct file_lock *blocker) { |
4e8c765d3 locks: avoid taki... |
682 683 |
/* * Avoid taking global lock if list is empty. This is safe since new |
6109c8503 locks: add a dedi... |
684 685 686 |
* blocked requests are only added to the list under the flc_lock, and * the flc_lock is always held here. Note that removal from the fl_block * list does not require the flc_lock, so we must recheck list_empty() |
7b2296afb locks: give the b... |
687 |
* after acquiring the blocked_lock_lock. |
4e8c765d3 locks: avoid taki... |
688 689 690 |
*/ if (list_empty(&blocker->fl_block)) return; |
7b2296afb locks: give the b... |
691 |
spin_lock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
692 |
while (!list_empty(&blocker->fl_block)) { |
f0c1cd0ea Use list_first_en... |
693 694 695 |
struct file_lock *waiter; waiter = list_first_entry(&blocker->fl_block, |
1da177e4c Linux-2.6.12-rc2 |
696 697 |
struct file_lock, fl_block); __locks_delete_block(waiter); |
8fb47a4fb locks: rename loc... |
698 699 |
if (waiter->fl_lmops && waiter->fl_lmops->lm_notify) waiter->fl_lmops->lm_notify(waiter); |
1da177e4c Linux-2.6.12-rc2 |
700 701 702 |
else wake_up(&waiter->fl_wait); } |
7b2296afb locks: give the b... |
703 |
spin_unlock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
704 |
} |
5263e31e4 locks: move flock... |
705 |
static void |
e084c1bd4 Revert "locks: ke... |
706 |
locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before) |
5263e31e4 locks: move flock... |
707 |
{ |
5263e31e4 locks: move flock... |
708 709 710 |
list_add_tail(&fl->fl_list, before); locks_insert_global_locks(fl); } |
8634b51f6 locks: convert le... |
711 |
static void |
e084c1bd4 Revert "locks: ke... |
712 |
locks_unlink_lock_ctx(struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
713 |
{ |
889746917 locks: encapsulat... |
714 |
locks_delete_global_locks(fl); |
8634b51f6 locks: convert le... |
715 |
list_del_init(&fl->fl_list); |
1da177e4c Linux-2.6.12-rc2 |
716 |
locks_wake_up_blocks(fl); |
24cbe7845 locks: close pote... |
717 |
} |
8634b51f6 locks: convert le... |
718 |
static void |
e084c1bd4 Revert "locks: ke... |
719 |
locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose) |
24cbe7845 locks: close pote... |
720 |
{ |
e084c1bd4 Revert "locks: ke... |
721 |
locks_unlink_lock_ctx(fl); |
ed9814d85 locks: defer free... |
722 |
if (dispose) |
6dee60f69 locks: add new st... |
723 |
list_add(&fl->fl_list, dispose); |
ed9814d85 locks: defer free... |
724 725 |
else locks_free_lock(fl); |
1da177e4c Linux-2.6.12-rc2 |
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 |
} /* Determine if lock sys_fl blocks lock caller_fl. Common functionality * checks for shared/exclusive status of overlapping locks. */ static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { if (sys_fl->fl_type == F_WRLCK) return 1; if (caller_fl->fl_type == F_WRLCK) return 1; return 0; } /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific * checking before calling the locks_conflict(). */ static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { /* POSIX locks owned by the same process do not conflict with * each other. */ |
9b8c86956 locks: remove ext... |
748 |
if (posix_same_owner(caller_fl, sys_fl)) |
1da177e4c Linux-2.6.12-rc2 |
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 |
return (0); /* Check whether they overlap */ if (!locks_overlap(caller_fl, sys_fl)) return 0; return (locks_conflict(caller_fl, sys_fl)); } /* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific * checking before calling the locks_conflict(). */ static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { /* FLOCK locks referring to the same filp do not conflict with * each other. */ |
9b8c86956 locks: remove ext... |
766 |
if (caller_fl->fl_file == sys_fl->fl_file) |
1da177e4c Linux-2.6.12-rc2 |
767 768 769 770 771 772 |
return (0); if ((caller_fl->fl_type & LOCK_MAND) || (sys_fl->fl_type & LOCK_MAND)) return 0; return (locks_conflict(caller_fl, sys_fl)); } |
6d34ac199 locks: make posix... |
773 |
void |
9d6a8c5c2 locks: give posix... |
774 |
posix_test_lock(struct file *filp, struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
775 776 |
{ struct file_lock *cfl; |
bd61e0a9c locks: convert po... |
777 |
struct file_lock_context *ctx; |
c568d6834 locks: fix file l... |
778 |
struct inode *inode = locks_inode(filp); |
1da177e4c Linux-2.6.12-rc2 |
779 |
|
128a37852 fs: fix data race... |
780 |
ctx = smp_load_acquire(&inode->i_flctx); |
bd61e0a9c locks: convert po... |
781 782 783 784 |
if (!ctx || list_empty_careful(&ctx->flc_posix)) { fl->fl_type = F_UNLCK; return; } |
6109c8503 locks: add a dedi... |
785 |
spin_lock(&ctx->flc_lock); |
bd61e0a9c locks: convert po... |
786 787 788 |
list_for_each_entry(cfl, &ctx->flc_posix, fl_list) { if (posix_locks_conflict(fl, cfl)) { locks_copy_conflock(fl, cfl); |
bd61e0a9c locks: convert po... |
789 790 |
goto out; } |
1da177e4c Linux-2.6.12-rc2 |
791 |
} |
bd61e0a9c locks: convert po... |
792 793 |
fl->fl_type = F_UNLCK; out: |
6109c8503 locks: add a dedi... |
794 |
spin_unlock(&ctx->flc_lock); |
6d34ac199 locks: make posix... |
795 |
return; |
1da177e4c Linux-2.6.12-rc2 |
796 |
} |
1da177e4c Linux-2.6.12-rc2 |
797 |
EXPORT_SYMBOL(posix_test_lock); |
b533184fc locks: clarify po... |
798 799 800 801 802 |
/* * Deadlock detection: * * We attempt to detect deadlocks that are due purely to posix file * locks. |
1da177e4c Linux-2.6.12-rc2 |
803 |
* |
b533184fc locks: clarify po... |
804 805 806 807 808 809 810 |
* We assume that a task can be waiting for at most one lock at a time. * So for any acquired lock, the process holding that lock may be * waiting on at most one other lock. That lock in turns may be held by * someone waiting for at most one other lock. Given a requested lock * caller_fl which is about to wait for a conflicting lock block_fl, we * follow this chain of waiters to ensure we are not about to create a * cycle. |
1da177e4c Linux-2.6.12-rc2 |
811 |
* |
b533184fc locks: clarify po... |
812 813 814 |
* Since we do this before we ever put a process to sleep on a lock, we * are ensured that there is never a cycle; that is what guarantees that * the while() loop in posix_locks_deadlock() eventually completes. |
97855b49b locks: fix possib... |
815 |
* |
b533184fc locks: clarify po... |
816 817 818 |
* Note: the above assumption may not be true when handling lock * requests from a broken NFS client. It may also fail in the presence * of tasks (such as posix threads) sharing the same open file table. |
b533184fc locks: clarify po... |
819 |
* To handle those cases, we just bail out after a few iterations. |
57b65325f locks: skip deadl... |
820 |
* |
cff2fce58 locks: rename FL_... |
821 |
* For FL_OFDLCK locks, the owner is the filp, not the files_struct. |
57b65325f locks: skip deadl... |
822 823 824 825 |
* Because the owner is not even nominally tied to a thread of * execution, the deadlock detection below can't reasonably work well. Just * skip it for those. * |
cff2fce58 locks: rename FL_... |
826 |
* In principle, we could do a more limited deadlock detection on FL_OFDLCK |
57b65325f locks: skip deadl... |
827 828 |
* locks that just checks for the case where two tasks are attempting to * upgrade from read to write locks on the same inode. |
1da177e4c Linux-2.6.12-rc2 |
829 |
*/ |
97855b49b locks: fix possib... |
830 831 |
#define MAX_DEADLK_ITERATIONS 10 |
b533184fc locks: clarify po... |
832 833 834 835 |
/* Find a lock that the owner of the given block_fl is blocking on. */ static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl) { struct file_lock *fl; |
3999e4936 locks: add a new ... |
836 |
hash_for_each_possible(blocked_hash, fl, fl_link, posix_owner_key(block_fl)) { |
b533184fc locks: clarify po... |
837 838 839 840 841 |
if (posix_same_owner(fl, block_fl)) return fl->fl_next; } return NULL; } |
7b2296afb locks: give the b... |
842 |
/* Must be called with the blocked_lock_lock held! */ |
b0904e147 [PATCH] fs/locks.... |
843 |
static int posix_locks_deadlock(struct file_lock *caller_fl, |
1da177e4c Linux-2.6.12-rc2 |
844 845 |
struct file_lock *block_fl) { |
97855b49b locks: fix possib... |
846 |
int i = 0; |
1da177e4c Linux-2.6.12-rc2 |
847 |
|
663d5af75 locks: Add lockde... |
848 |
lockdep_assert_held(&blocked_lock_lock); |
57b65325f locks: skip deadl... |
849 850 |
/* * This deadlock detector can't reasonably detect deadlocks with |
cff2fce58 locks: rename FL_... |
851 |
* FL_OFDLCK locks, since they aren't owned by a process, per-se. |
57b65325f locks: skip deadl... |
852 |
*/ |
cff2fce58 locks: rename FL_... |
853 |
if (IS_OFDLCK(caller_fl)) |
57b65325f locks: skip deadl... |
854 |
return 0; |
b533184fc locks: clarify po... |
855 856 857 858 859 |
while ((block_fl = what_owner_is_waiting_for(block_fl))) { if (i++ > MAX_DEADLK_ITERATIONS) return 0; if (posix_same_owner(caller_fl, block_fl)) return 1; |
1da177e4c Linux-2.6.12-rc2 |
860 861 862 |
} return 0; } |
1da177e4c Linux-2.6.12-rc2 |
863 |
/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks |
02888f41e locks: fix flock_... |
864 |
* after any leases, but before any posix locks. |
f475ae957 VFS: Allow caller... |
865 866 867 868 |
* * Note that if called with an FL_EXISTS argument, the caller may determine * whether or not a lock was successfully freed by testing the return * value for -ENOENT. |
1da177e4c Linux-2.6.12-rc2 |
869 |
*/ |
bcd7f78d0 locks: have flock... |
870 |
static int flock_lock_inode(struct inode *inode, struct file_lock *request) |
1da177e4c Linux-2.6.12-rc2 |
871 |
{ |
993dfa877 [PATCH] fs/locks.... |
872 |
struct file_lock *new_fl = NULL; |
5263e31e4 locks: move flock... |
873 874 |
struct file_lock *fl; struct file_lock_context *ctx; |
1da177e4c Linux-2.6.12-rc2 |
875 |
int error = 0; |
5263e31e4 locks: move flock... |
876 |
bool found = false; |
ed9814d85 locks: defer free... |
877 |
LIST_HEAD(dispose); |
1da177e4c Linux-2.6.12-rc2 |
878 |
|
5c1c669a1 locks: don't allo... |
879 880 881 882 883 884 |
ctx = locks_get_lock_context(inode, request->fl_type); if (!ctx) { if (request->fl_type != F_UNLCK) return -ENOMEM; return (request->fl_flags & FL_EXISTS) ? -ENOENT : 0; } |
5263e31e4 locks: move flock... |
885 |
|
b89f43213 fs/locks.c: prepa... |
886 |
if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { |
84d535ade Memory shortage c... |
887 |
new_fl = locks_alloc_lock(); |
b89f43213 fs/locks.c: prepa... |
888 889 |
if (!new_fl) return -ENOMEM; |
84d535ade Memory shortage c... |
890 |
} |
87709e28d fs/locks: Use per... |
891 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
892 |
spin_lock(&ctx->flc_lock); |
b89f43213 fs/locks.c: prepa... |
893 894 |
if (request->fl_flags & FL_ACCESS) goto find_conflict; |
5263e31e4 locks: move flock... |
895 |
list_for_each_entry(fl, &ctx->flc_flock, fl_list) { |
bcd7f78d0 locks: have flock... |
896 |
if (request->fl_file != fl->fl_file) |
1da177e4c Linux-2.6.12-rc2 |
897 |
continue; |
993dfa877 [PATCH] fs/locks.... |
898 |
if (request->fl_type == fl->fl_type) |
1da177e4c Linux-2.6.12-rc2 |
899 |
goto out; |
5263e31e4 locks: move flock... |
900 |
found = true; |
e084c1bd4 Revert "locks: ke... |
901 |
locks_delete_lock_ctx(fl, &dispose); |
1da177e4c Linux-2.6.12-rc2 |
902 903 |
break; } |
1da177e4c Linux-2.6.12-rc2 |
904 |
|
f475ae957 VFS: Allow caller... |
905 906 907 |
if (request->fl_type == F_UNLCK) { if ((request->fl_flags & FL_EXISTS) && !found) error = -ENOENT; |
993dfa877 [PATCH] fs/locks.... |
908 |
goto out; |
f475ae957 VFS: Allow caller... |
909 |
} |
1da177e4c Linux-2.6.12-rc2 |
910 |
|
f07f18dd6 VFS: Add support ... |
911 |
find_conflict: |
5263e31e4 locks: move flock... |
912 |
list_for_each_entry(fl, &ctx->flc_flock, fl_list) { |
993dfa877 [PATCH] fs/locks.... |
913 |
if (!flock_locks_conflict(request, fl)) |
1da177e4c Linux-2.6.12-rc2 |
914 915 |
continue; error = -EAGAIN; |
bde74e4bc locks: add specia... |
916 917 918 919 |
if (!(request->fl_flags & FL_SLEEP)) goto out; error = FILE_LOCK_DEFERRED; locks_insert_block(fl, request); |
1da177e4c Linux-2.6.12-rc2 |
920 921 |
goto out; } |
f07f18dd6 VFS: Add support ... |
922 923 |
if (request->fl_flags & FL_ACCESS) goto out; |
993dfa877 [PATCH] fs/locks.... |
924 |
locks_copy_lock(new_fl, request); |
e084c1bd4 Revert "locks: ke... |
925 |
locks_insert_lock_ctx(new_fl, &ctx->flc_flock); |
993dfa877 [PATCH] fs/locks.... |
926 |
new_fl = NULL; |
9cedc194a [PATCH] Return er... |
927 |
error = 0; |
1da177e4c Linux-2.6.12-rc2 |
928 929 |
out: |
6109c8503 locks: add a dedi... |
930 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
931 |
percpu_up_read_preempt_enable(&file_rwsem); |
993dfa877 [PATCH] fs/locks.... |
932 933 |
if (new_fl) locks_free_lock(new_fl); |
ed9814d85 locks: defer free... |
934 |
locks_dispose_list(&dispose); |
c883da313 locks: add tracep... |
935 |
trace_flock_lock_inode(inode, request, error); |
1da177e4c Linux-2.6.12-rc2 |
936 937 |
return error; } |
b4d629a39 locks: rename __p... |
938 939 |
static int posix_lock_inode(struct inode *inode, struct file_lock *request, struct file_lock *conflock) |
1da177e4c Linux-2.6.12-rc2 |
940 |
{ |
bd61e0a9c locks: convert po... |
941 |
struct file_lock *fl, *tmp; |
39005d022 [PATCH] locks: do... |
942 943 |
struct file_lock *new_fl = NULL; struct file_lock *new_fl2 = NULL; |
1da177e4c Linux-2.6.12-rc2 |
944 945 |
struct file_lock *left = NULL; struct file_lock *right = NULL; |
bd61e0a9c locks: convert po... |
946 |
struct file_lock_context *ctx; |
b9746ef80 locks: make "adde... |
947 948 |
int error; bool added = false; |
ed9814d85 locks: defer free... |
949 |
LIST_HEAD(dispose); |
1da177e4c Linux-2.6.12-rc2 |
950 |
|
5c1c669a1 locks: don't allo... |
951 |
ctx = locks_get_lock_context(inode, request->fl_type); |
bd61e0a9c locks: convert po... |
952 |
if (!ctx) |
5c1c669a1 locks: don't allo... |
953 |
return (request->fl_type == F_UNLCK) ? 0 : -ENOMEM; |
bd61e0a9c locks: convert po... |
954 |
|
1da177e4c Linux-2.6.12-rc2 |
955 956 957 |
/* * We may need two file_lock structures for this operation, * so we get them in advance to avoid races. |
39005d022 [PATCH] locks: do... |
958 959 |
* * In some cases we can be sure, that no new locks will be needed |
1da177e4c Linux-2.6.12-rc2 |
960 |
*/ |
39005d022 [PATCH] locks: do... |
961 962 963 964 965 966 |
if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK || request->fl_start != 0 || request->fl_end != OFFSET_MAX)) { new_fl = locks_alloc_lock(); new_fl2 = locks_alloc_lock(); } |
1da177e4c Linux-2.6.12-rc2 |
967 |
|
87709e28d fs/locks: Use per... |
968 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
969 |
spin_lock(&ctx->flc_lock); |
1cb360125 locks: comment cl... |
970 971 972 |
/* * New lock request. Walk all POSIX locks and look for conflicts. If * there are any, either return error or put the request on the |
48f741865 locks: turn the b... |
973 |
* blocker's list of waiters and the global blocked_hash. |
1cb360125 locks: comment cl... |
974 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
975 |
if (request->fl_type != F_UNLCK) { |
bd61e0a9c locks: convert po... |
976 |
list_for_each_entry(fl, &ctx->flc_posix, fl_list) { |
1da177e4c Linux-2.6.12-rc2 |
977 978 |
if (!posix_locks_conflict(request, fl)) continue; |
5842add2f [PATCH] VFS,fs/lo... |
979 |
if (conflock) |
3fe0fff18 locks: Rename __l... |
980 |
locks_copy_conflock(conflock, fl); |
1da177e4c Linux-2.6.12-rc2 |
981 982 983 |
error = -EAGAIN; if (!(request->fl_flags & FL_SLEEP)) goto out; |
1c8c601a8 locks: protect mo... |
984 985 986 987 |
/* * Deadlock detection and insertion into the blocked * locks list must be done while holding the same lock! */ |
1da177e4c Linux-2.6.12-rc2 |
988 |
error = -EDEADLK; |
7b2296afb locks: give the b... |
989 |
spin_lock(&blocked_lock_lock); |
1c8c601a8 locks: protect mo... |
990 991 992 993 |
if (likely(!posix_locks_deadlock(request, fl))) { error = FILE_LOCK_DEFERRED; __locks_insert_block(fl, request); } |
7b2296afb locks: give the b... |
994 |
spin_unlock(&blocked_lock_lock); |
1da177e4c Linux-2.6.12-rc2 |
995 996 997 998 999 1000 1001 1002 |
goto out; } } /* If we're just looking for a conflict, we're done. */ error = 0; if (request->fl_flags & FL_ACCESS) goto out; |
bd61e0a9c locks: convert po... |
1003 1004 1005 1006 |
/* Find the first old lock with the same owner as the new lock */ list_for_each_entry(fl, &ctx->flc_posix, fl_list) { if (posix_same_owner(request, fl)) break; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
} |
1cb360125 locks: comment cl... |
1008 |
/* Process locks with this owner. */ |
bd61e0a9c locks: convert po... |
1009 1010 1011 1012 1013 |
list_for_each_entry_safe_from(fl, tmp, &ctx->flc_posix, fl_list) { if (!posix_same_owner(request, fl)) break; /* Detect adjacent or overlapping regions (if same lock type) */ |
1da177e4c Linux-2.6.12-rc2 |
1014 |
if (request->fl_type == fl->fl_type) { |
449231d6d From: Olaf Kirch ... |
1015 1016 1017 1018 |
/* In all comparisons of start vs end, use * "start - 1" rather than "end + 1". If end * is OFFSET_MAX, end + 1 will become negative. */ |
1da177e4c Linux-2.6.12-rc2 |
1019 |
if (fl->fl_end < request->fl_start - 1) |
bd61e0a9c locks: convert po... |
1020 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
1021 1022 1023 |
/* If the next lock in the list has entirely bigger * addresses than the new one, insert the lock here. */ |
449231d6d From: Olaf Kirch ... |
1024 |
if (fl->fl_start - 1 > request->fl_end) |
1da177e4c Linux-2.6.12-rc2 |
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
break; /* If we come here, the new and old lock are of the * same type and adjacent or overlapping. Make one * lock yielding from the lower start address of both * locks to the higher end address. */ if (fl->fl_start > request->fl_start) fl->fl_start = request->fl_start; else request->fl_start = fl->fl_start; if (fl->fl_end < request->fl_end) fl->fl_end = request->fl_end; else request->fl_end = fl->fl_end; if (added) { |
e084c1bd4 Revert "locks: ke... |
1041 |
locks_delete_lock_ctx(fl, &dispose); |
1da177e4c Linux-2.6.12-rc2 |
1042 1043 1044 |
continue; } request = fl; |
b9746ef80 locks: make "adde... |
1045 |
added = true; |
bd61e0a9c locks: convert po... |
1046 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
1047 1048 1049 1050 |
/* Processing for different lock types is a bit * more complex. */ if (fl->fl_end < request->fl_start) |
bd61e0a9c locks: convert po... |
1051 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
1052 1053 1054 |
if (fl->fl_start > request->fl_end) break; if (request->fl_type == F_UNLCK) |
b9746ef80 locks: make "adde... |
1055 |
added = true; |
1da177e4c Linux-2.6.12-rc2 |
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
if (fl->fl_start < request->fl_start) left = fl; /* If the next lock in the list has a higher end * address than the new one, insert the new one here. */ if (fl->fl_end > request->fl_end) { right = fl; break; } if (fl->fl_start >= request->fl_start) { /* The new lock completely replaces an old * one (This may happen several times). */ if (added) { |
e084c1bd4 Revert "locks: ke... |
1070 |
locks_delete_lock_ctx(fl, &dispose); |
1da177e4c Linux-2.6.12-rc2 |
1071 1072 |
continue; } |
b84d49f94 locks: don't reus... |
1073 1074 1075 1076 1077 1078 |
/* * Replace the old lock with new_fl, and * remove the old one. It's safe to do the * insert here since we know that we won't be * using new_fl later, and that the lock is * just replacing an existing lock. |
1da177e4c Linux-2.6.12-rc2 |
1079 |
*/ |
b84d49f94 locks: don't reus... |
1080 1081 1082 1083 1084 1085 |
error = -ENOLCK; if (!new_fl) goto out; locks_copy_lock(new_fl, request); request = new_fl; new_fl = NULL; |
e084c1bd4 Revert "locks: ke... |
1086 1087 |
locks_insert_lock_ctx(request, &fl->fl_list); locks_delete_lock_ctx(fl, &dispose); |
b9746ef80 locks: make "adde... |
1088 |
added = true; |
1da177e4c Linux-2.6.12-rc2 |
1089 1090 |
} } |
1da177e4c Linux-2.6.12-rc2 |
1091 |
} |
0d9a490ab [PATCH] locks: do... |
1092 |
/* |
1cb360125 locks: comment cl... |
1093 1094 1095 |
* The above code only modifies existing locks in case of merging or * replacing. If new lock(s) need to be inserted all modifications are * done below this, so it's safe yet to bail out. |
0d9a490ab [PATCH] locks: do... |
1096 1097 1098 1099 |
*/ error = -ENOLCK; /* "no luck" */ if (right && left == right && !new_fl2) goto out; |
1da177e4c Linux-2.6.12-rc2 |
1100 1101 |
error = 0; if (!added) { |
f475ae957 VFS: Allow caller... |
1102 1103 1104 |
if (request->fl_type == F_UNLCK) { if (request->fl_flags & FL_EXISTS) error = -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
1105 |
goto out; |
f475ae957 VFS: Allow caller... |
1106 |
} |
0d9a490ab [PATCH] locks: do... |
1107 1108 1109 1110 1111 |
if (!new_fl) { error = -ENOLCK; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
1112 |
locks_copy_lock(new_fl, request); |
e084c1bd4 Revert "locks: ke... |
1113 |
locks_insert_lock_ctx(new_fl, &fl->fl_list); |
2e2f756f8 locks: fix list i... |
1114 |
fl = new_fl; |
1da177e4c Linux-2.6.12-rc2 |
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 |
new_fl = NULL; } if (right) { if (left == right) { /* The new lock breaks the old one in two pieces, * so we have to use the second new lock. */ left = new_fl2; new_fl2 = NULL; locks_copy_lock(left, right); |
e084c1bd4 Revert "locks: ke... |
1125 |
locks_insert_lock_ctx(left, &fl->fl_list); |
1da177e4c Linux-2.6.12-rc2 |
1126 1127 1128 1129 1130 1131 1132 1133 1134 |
} right->fl_start = request->fl_end + 1; locks_wake_up_blocks(right); } if (left) { left->fl_end = request->fl_start - 1; locks_wake_up_blocks(left); } out: |
6109c8503 locks: add a dedi... |
1135 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
1136 |
percpu_up_read_preempt_enable(&file_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
1137 1138 1139 1140 1141 1142 1143 |
/* * Free any unused locks. */ if (new_fl) locks_free_lock(new_fl); if (new_fl2) locks_free_lock(new_fl2); |
ed9814d85 locks: defer free... |
1144 |
locks_dispose_list(&dispose); |
1890910fd locks: sprinkle s... |
1145 |
trace_posix_lock_inode(inode, request, error); |
1da177e4c Linux-2.6.12-rc2 |
1146 1147 1148 1149 1150 1151 1152 |
return error; } /** * posix_lock_file - Apply a POSIX-style lock to a file * @filp: The file to apply the lock to * @fl: The lock to be applied |
150b39345 locks: allow {vfs... |
1153 |
* @conflock: Place to return a copy of the conflicting lock, if found. |
1da177e4c Linux-2.6.12-rc2 |
1154 1155 1156 1157 |
* * Add a POSIX style lock to a file. * We merge adjacent & overlapping locks whenever possible. * POSIX locks are sorted by owner task, then by starting address |
f475ae957 VFS: Allow caller... |
1158 1159 1160 1161 |
* * Note that if called with an FL_EXISTS argument, the caller may determine * whether or not a lock was successfully freed by testing the return * value for -ENOENT. |
1da177e4c Linux-2.6.12-rc2 |
1162 |
*/ |
150b39345 locks: allow {vfs... |
1163 |
int posix_lock_file(struct file *filp, struct file_lock *fl, |
5842add2f [PATCH] VFS,fs/lo... |
1164 1165 |
struct file_lock *conflock) { |
c568d6834 locks: fix file l... |
1166 |
return posix_lock_inode(locks_inode(filp), fl, conflock); |
1da177e4c Linux-2.6.12-rc2 |
1167 |
} |
150b39345 locks: allow {vfs... |
1168 |
EXPORT_SYMBOL(posix_lock_file); |
1da177e4c Linux-2.6.12-rc2 |
1169 1170 |
/** |
29d01b22e locks: new helper... |
1171 1172 |
* posix_lock_inode_wait - Apply a POSIX-style lock to a file * @inode: inode of file to which lock request should be applied |
1da177e4c Linux-2.6.12-rc2 |
1173 1174 |
* @fl: The lock to be applied * |
616fb38fa locks: cleanup po... |
1175 |
* Apply a POSIX style lock request to an inode. |
1da177e4c Linux-2.6.12-rc2 |
1176 |
*/ |
616fb38fa locks: cleanup po... |
1177 |
static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
1178 1179 1180 1181 |
{ int error; might_sleep (); for (;;) { |
b4d629a39 locks: rename __p... |
1182 |
error = posix_lock_inode(inode, fl, NULL); |
bde74e4bc locks: add specia... |
1183 |
if (error != FILE_LOCK_DEFERRED) |
1da177e4c Linux-2.6.12-rc2 |
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 |
break; error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); if (!error) continue; locks_delete_block(fl); break; } return error; } |
29d01b22e locks: new helper... |
1194 |
|
9e8925b67 locks: Allow disa... |
1195 |
#ifdef CONFIG_MANDATORY_FILE_LOCKING |
29d01b22e locks: new helper... |
1196 |
/** |
1da177e4c Linux-2.6.12-rc2 |
1197 |
* locks_mandatory_locked - Check for an active lock |
d7a06983a locks: fix locks_... |
1198 |
* @file: the file to check |
1da177e4c Linux-2.6.12-rc2 |
1199 1200 1201 1202 |
* * Searches the inode's list of locks to find any POSIX locks which conflict. * This function is called from locks_verify_locked() only. */ |
d7a06983a locks: fix locks_... |
1203 |
int locks_mandatory_locked(struct file *file) |
1da177e4c Linux-2.6.12-rc2 |
1204 |
{ |
bd61e0a9c locks: convert po... |
1205 |
int ret; |
c568d6834 locks: fix file l... |
1206 |
struct inode *inode = locks_inode(file); |
bd61e0a9c locks: convert po... |
1207 |
struct file_lock_context *ctx; |
1da177e4c Linux-2.6.12-rc2 |
1208 |
struct file_lock *fl; |
128a37852 fs: fix data race... |
1209 |
ctx = smp_load_acquire(&inode->i_flctx); |
bd61e0a9c locks: convert po... |
1210 1211 |
if (!ctx || list_empty_careful(&ctx->flc_posix)) return 0; |
1da177e4c Linux-2.6.12-rc2 |
1212 1213 1214 |
/* * Search the lock list for this inode for any POSIX locks. */ |
6109c8503 locks: add a dedi... |
1215 |
spin_lock(&ctx->flc_lock); |
bd61e0a9c locks: convert po... |
1216 1217 |
ret = 0; list_for_each_entry(fl, &ctx->flc_posix, fl_list) { |
73a8f5f7e locks: purge fl_o... |
1218 |
if (fl->fl_owner != current->files && |
bd61e0a9c locks: convert po... |
1219 1220 |
fl->fl_owner != file) { ret = -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
1221 |
break; |
bd61e0a9c locks: convert po... |
1222 |
} |
1da177e4c Linux-2.6.12-rc2 |
1223 |
} |
6109c8503 locks: add a dedi... |
1224 |
spin_unlock(&ctx->flc_lock); |
bd61e0a9c locks: convert po... |
1225 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1226 1227 1228 1229 |
} /** * locks_mandatory_area - Check for a conflicting lock |
acc15575e locks: new locks_... |
1230 |
* @inode: the file to check |
1da177e4c Linux-2.6.12-rc2 |
1231 |
* @filp: how the file was opened (if it was) |
acc15575e locks: new locks_... |
1232 1233 1234 |
* @start: first byte in the file to check * @end: lastbyte in the file to check * @type: %F_WRLCK for a write lock, else %F_RDLCK |
1da177e4c Linux-2.6.12-rc2 |
1235 1236 |
* * Searches the inode's list of locks to find any POSIX locks which conflict. |
1da177e4c Linux-2.6.12-rc2 |
1237 |
*/ |
acc15575e locks: new locks_... |
1238 1239 |
int locks_mandatory_area(struct inode *inode, struct file *filp, loff_t start, loff_t end, unsigned char type) |
1da177e4c Linux-2.6.12-rc2 |
1240 1241 1242 |
{ struct file_lock fl; int error; |
29723adee locks: make locks... |
1243 |
bool sleep = false; |
1da177e4c Linux-2.6.12-rc2 |
1244 1245 |
locks_init_lock(&fl); |
1da177e4c Linux-2.6.12-rc2 |
1246 1247 1248 1249 |
fl.fl_pid = current->tgid; fl.fl_file = filp; fl.fl_flags = FL_POSIX | FL_ACCESS; if (filp && !(filp->f_flags & O_NONBLOCK)) |
29723adee locks: make locks... |
1250 |
sleep = true; |
acc15575e locks: new locks_... |
1251 1252 1253 |
fl.fl_type = type; fl.fl_start = start; fl.fl_end = end; |
1da177e4c Linux-2.6.12-rc2 |
1254 1255 |
for (;;) { |
29723adee locks: make locks... |
1256 |
if (filp) { |
73a8f5f7e locks: purge fl_o... |
1257 |
fl.fl_owner = filp; |
29723adee locks: make locks... |
1258 |
fl.fl_flags &= ~FL_SLEEP; |
b4d629a39 locks: rename __p... |
1259 |
error = posix_lock_inode(inode, &fl, NULL); |
29723adee locks: make locks... |
1260 1261 1262 1263 1264 1265 1266 |
if (!error) break; } if (sleep) fl.fl_flags |= FL_SLEEP; fl.fl_owner = current->files; |
b4d629a39 locks: rename __p... |
1267 |
error = posix_lock_inode(inode, &fl, NULL); |
bde74e4bc locks: add specia... |
1268 |
if (error != FILE_LOCK_DEFERRED) |
1da177e4c Linux-2.6.12-rc2 |
1269 1270 1271 1272 1273 1274 1275 |
break; error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); if (!error) { /* * If we've been sleeping someone might have * changed the permissions behind our back. */ |
a16877ca9 Cleanup macros fo... |
1276 |
if (__mandatory_lock(inode)) |
1da177e4c Linux-2.6.12-rc2 |
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 |
continue; } locks_delete_block(&fl); break; } return error; } EXPORT_SYMBOL(locks_mandatory_area); |
9e8925b67 locks: Allow disa... |
1288 |
#endif /* CONFIG_MANDATORY_FILE_LOCKING */ |
1da177e4c Linux-2.6.12-rc2 |
1289 |
|
778fc546f locks: fix tracki... |
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 |
static void lease_clear_pending(struct file_lock *fl, int arg) { switch (arg) { case F_UNLCK: fl->fl_flags &= ~FL_UNLOCK_PENDING; /* fall through: */ case F_RDLCK: fl->fl_flags &= ~FL_DOWNGRADE_PENDING; } } |
1da177e4c Linux-2.6.12-rc2 |
1300 |
/* We already had a lease on this file; just change its type */ |
7448cc37b locks: clean up t... |
1301 |
int lease_modify(struct file_lock *fl, int arg, struct list_head *dispose) |
1da177e4c Linux-2.6.12-rc2 |
1302 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1303 1304 1305 1306 |
int error = assign_type(fl, arg); if (error) return error; |
778fc546f locks: fix tracki... |
1307 |
lease_clear_pending(fl, arg); |
1da177e4c Linux-2.6.12-rc2 |
1308 |
locks_wake_up_blocks(fl); |
3b6e2723f locks: prevent si... |
1309 1310 1311 1312 1313 |
if (arg == F_UNLCK) { struct file *filp = fl->fl_file; f_delown(filp); filp->f_owner.signum = 0; |
96d6d59ce locks: move lease... |
1314 1315 1316 1317 1318 1319 |
fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); if (fl->fl_fasync != NULL) { printk(KERN_ERR "locks_delete_lock: fasync == %p ", fl->fl_fasync); fl->fl_fasync = NULL; } |
e084c1bd4 Revert "locks: ke... |
1320 |
locks_delete_lock_ctx(fl, dispose); |
3b6e2723f locks: prevent si... |
1321 |
} |
1da177e4c Linux-2.6.12-rc2 |
1322 1323 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1324 |
EXPORT_SYMBOL(lease_modify); |
778fc546f locks: fix tracki... |
1325 1326 1327 1328 1329 1330 1331 |
static bool past_time(unsigned long then) { if (!then) /* 0 is a special value meaning "this never expires": */ return false; return time_after(jiffies, then); } |
c45198eda locks: move freei... |
1332 |
static void time_out_leases(struct inode *inode, struct list_head *dispose) |
1da177e4c Linux-2.6.12-rc2 |
1333 |
{ |
8634b51f6 locks: convert le... |
1334 1335 |
struct file_lock_context *ctx = inode->i_flctx; struct file_lock *fl, *tmp; |
1da177e4c Linux-2.6.12-rc2 |
1336 |
|
6109c8503 locks: add a dedi... |
1337 |
lockdep_assert_held(&ctx->flc_lock); |
f82b4b678 locks: move i_loc... |
1338 |
|
8634b51f6 locks: convert le... |
1339 |
list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) { |
62af4f1f7 locks: add some t... |
1340 |
trace_time_out_leases(inode, fl); |
778fc546f locks: fix tracki... |
1341 |
if (past_time(fl->fl_downgrade_time)) |
7448cc37b locks: clean up t... |
1342 |
lease_modify(fl, F_RDLCK, dispose); |
778fc546f locks: fix tracki... |
1343 |
if (past_time(fl->fl_break_time)) |
7448cc37b locks: clean up t... |
1344 |
lease_modify(fl, F_UNLCK, dispose); |
1da177e4c Linux-2.6.12-rc2 |
1345 1346 |
} } |
df4e8d2c1 locks: implement ... |
1347 1348 |
static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker) { |
11afe9f76 fs: add FL_LAYOUT... |
1349 1350 |
if ((breaker->fl_flags & FL_LAYOUT) != (lease->fl_flags & FL_LAYOUT)) return false; |
df4e8d2c1 locks: implement ... |
1351 1352 1353 1354 |
if ((breaker->fl_flags & FL_DELEG) && (lease->fl_flags & FL_LEASE)) return false; return locks_conflict(breaker, lease); } |
03d12ddf8 locks: __break_le... |
1355 1356 1357 |
static bool any_leases_conflict(struct inode *inode, struct file_lock *breaker) { |
8634b51f6 locks: convert le... |
1358 |
struct file_lock_context *ctx = inode->i_flctx; |
03d12ddf8 locks: __break_le... |
1359 |
struct file_lock *fl; |
6109c8503 locks: add a dedi... |
1360 |
lockdep_assert_held(&ctx->flc_lock); |
03d12ddf8 locks: __break_le... |
1361 |
|
8634b51f6 locks: convert le... |
1362 |
list_for_each_entry(fl, &ctx->flc_lease, fl_list) { |
03d12ddf8 locks: __break_le... |
1363 1364 1365 1366 1367 |
if (leases_conflict(fl, breaker)) return true; } return false; } |
1da177e4c Linux-2.6.12-rc2 |
1368 1369 1370 |
/** * __break_lease - revoke all outstanding leases on file * @inode: the inode of the file to return |
df4e8d2c1 locks: implement ... |
1371 1372 1373 1374 |
* @mode: O_RDONLY: break only write leases; O_WRONLY or O_RDWR: * break all leases * @type: FL_LEASE: break leases and delegations; FL_DELEG: break * only delegations |
1da177e4c Linux-2.6.12-rc2 |
1375 |
* |
87250dd26 leases: minor bre... |
1376 1377 1378 |
* break_lease (inlined for speed) has checked there already is at least * some kind of lock (maybe a lease) on this file. Leases are broken on * a call to open() or truncate(). This function can sleep unless you |
1da177e4c Linux-2.6.12-rc2 |
1379 1380 |
* specified %O_NONBLOCK to your open(). */ |
df4e8d2c1 locks: implement ... |
1381 |
int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
1382 |
{ |
778fc546f locks: fix tracki... |
1383 |
int error = 0; |
128a37852 fs: fix data race... |
1384 |
struct file_lock_context *ctx; |
a901125c6 locks: fix file_l... |
1385 |
struct file_lock *new_fl, *fl, *tmp; |
1da177e4c Linux-2.6.12-rc2 |
1386 |
unsigned long break_time; |
8737c9305 Switch may_open()... |
1387 |
int want_write = (mode & O_ACCMODE) != O_RDONLY; |
c45198eda locks: move freei... |
1388 |
LIST_HEAD(dispose); |
1da177e4c Linux-2.6.12-rc2 |
1389 |
|
8737c9305 Switch may_open()... |
1390 |
new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK); |
6d4b9e38d vfs: fix handling... |
1391 1392 |
if (IS_ERR(new_fl)) return PTR_ERR(new_fl); |
df4e8d2c1 locks: implement ... |
1393 |
new_fl->fl_flags = type; |
1da177e4c Linux-2.6.12-rc2 |
1394 |
|
8634b51f6 locks: convert le... |
1395 |
/* typically we will check that ctx is non-NULL before calling */ |
128a37852 fs: fix data race... |
1396 |
ctx = smp_load_acquire(&inode->i_flctx); |
8634b51f6 locks: convert le... |
1397 1398 1399 1400 |
if (!ctx) { WARN_ON_ONCE(1); return error; } |
87709e28d fs/locks: Use per... |
1401 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
1402 |
spin_lock(&ctx->flc_lock); |
1da177e4c Linux-2.6.12-rc2 |
1403 |
|
c45198eda locks: move freei... |
1404 |
time_out_leases(inode, &dispose); |
1da177e4c Linux-2.6.12-rc2 |
1405 |
|
03d12ddf8 locks: __break_le... |
1406 |
if (!any_leases_conflict(inode, new_fl)) |
778fc546f locks: fix tracki... |
1407 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1408 1409 1410 1411 1412 1413 |
break_time = 0; if (lease_break_time > 0) { break_time = jiffies + lease_break_time * HZ; if (break_time == 0) break_time++; /* so that 0 means no break time */ } |
a901125c6 locks: fix file_l... |
1414 |
list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) { |
df4e8d2c1 locks: implement ... |
1415 1416 |
if (!leases_conflict(fl, new_fl)) continue; |
778fc546f locks: fix tracki... |
1417 1418 1419 1420 |
if (want_write) { if (fl->fl_flags & FL_UNLOCK_PENDING) continue; fl->fl_flags |= FL_UNLOCK_PENDING; |
1da177e4c Linux-2.6.12-rc2 |
1421 |
fl->fl_break_time = break_time; |
778fc546f locks: fix tracki... |
1422 |
} else { |
8634b51f6 locks: convert le... |
1423 |
if (lease_breaking(fl)) |
778fc546f locks: fix tracki... |
1424 1425 1426 |
continue; fl->fl_flags |= FL_DOWNGRADE_PENDING; fl->fl_downgrade_time = break_time; |
1da177e4c Linux-2.6.12-rc2 |
1427 |
} |
4d01b7f5e locks: give lm_br... |
1428 |
if (fl->fl_lmops->lm_break(fl)) |
e084c1bd4 Revert "locks: ke... |
1429 |
locks_delete_lock_ctx(fl, &dispose); |
1da177e4c Linux-2.6.12-rc2 |
1430 |
} |
8634b51f6 locks: convert le... |
1431 |
if (list_empty(&ctx->flc_lease)) |
4d01b7f5e locks: give lm_br... |
1432 |
goto out; |
843c6b2f4 locks: remove i_h... |
1433 |
if (mode & O_NONBLOCK) { |
62af4f1f7 locks: add some t... |
1434 |
trace_break_lease_noblock(inode, new_fl); |
1da177e4c Linux-2.6.12-rc2 |
1435 1436 1437 1438 1439 |
error = -EWOULDBLOCK; goto out; } restart: |
8634b51f6 locks: convert le... |
1440 1441 |
fl = list_first_entry(&ctx->flc_lease, struct file_lock, fl_list); break_time = fl->fl_break_time; |
f1c6bb2cb locks: allow __br... |
1442 |
if (break_time != 0) |
1da177e4c Linux-2.6.12-rc2 |
1443 |
break_time -= jiffies; |
f1c6bb2cb locks: allow __br... |
1444 1445 |
if (break_time == 0) break_time++; |
8634b51f6 locks: convert le... |
1446 |
locks_insert_block(fl, new_fl); |
62af4f1f7 locks: add some t... |
1447 |
trace_break_lease_block(inode, new_fl); |
6109c8503 locks: add a dedi... |
1448 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
1449 |
percpu_up_read_preempt_enable(&file_rwsem); |
aba376607 fs/locks: Replace... |
1450 |
|
c45198eda locks: move freei... |
1451 |
locks_dispose_list(&dispose); |
4321e01e7 file locks: Use w... |
1452 1453 |
error = wait_event_interruptible_timeout(new_fl->fl_wait, !new_fl->fl_next, break_time); |
aba376607 fs/locks: Replace... |
1454 |
|
87709e28d fs/locks: Use per... |
1455 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
1456 |
spin_lock(&ctx->flc_lock); |
62af4f1f7 locks: add some t... |
1457 |
trace_break_lease_unblock(inode, new_fl); |
1c8c601a8 locks: protect mo... |
1458 |
locks_delete_block(new_fl); |
1da177e4c Linux-2.6.12-rc2 |
1459 |
if (error >= 0) { |
778fc546f locks: fix tracki... |
1460 1461 1462 1463 |
/* * Wait for the next conflicting lease that has not been * broken yet */ |
03d12ddf8 locks: __break_le... |
1464 1465 1466 1467 |
if (error == 0) time_out_leases(inode, &dispose); if (any_leases_conflict(inode, new_fl)) goto restart; |
1da177e4c Linux-2.6.12-rc2 |
1468 1469 |
error = 0; } |
1da177e4c Linux-2.6.12-rc2 |
1470 |
out: |
6109c8503 locks: add a dedi... |
1471 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
1472 |
percpu_up_read_preempt_enable(&file_rwsem); |
c45198eda locks: move freei... |
1473 |
locks_dispose_list(&dispose); |
6d4b9e38d vfs: fix handling... |
1474 |
locks_free_lock(new_fl); |
1da177e4c Linux-2.6.12-rc2 |
1475 1476 1477 1478 1479 1480 |
return error; } EXPORT_SYMBOL(__break_lease); /** |
76c479480 nfsd: encode stat... |
1481 |
* lease_get_mtime - update modified time of an inode with exclusive lease |
1da177e4c Linux-2.6.12-rc2 |
1482 |
* @inode: the inode |
76c479480 nfsd: encode stat... |
1483 |
* @time: pointer to a timespec which contains the last modified time |
1da177e4c Linux-2.6.12-rc2 |
1484 1485 1486 |
* * This is to force NFS clients to flush their caches for files with * exclusive leases. The justification is that if someone has an |
a6b91919e fs: fix kernel-do... |
1487 |
* exclusive lease, then they could be modifying it. |
1da177e4c Linux-2.6.12-rc2 |
1488 |
*/ |
95582b008 vfs: change inode... |
1489 |
void lease_get_mtime(struct inode *inode, struct timespec64 *time) |
1da177e4c Linux-2.6.12-rc2 |
1490 |
{ |
bfe860243 locks: close pote... |
1491 |
bool has_lease = false; |
128a37852 fs: fix data race... |
1492 |
struct file_lock_context *ctx; |
8634b51f6 locks: convert le... |
1493 |
struct file_lock *fl; |
bfe860243 locks: close pote... |
1494 |
|
128a37852 fs: fix data race... |
1495 |
ctx = smp_load_acquire(&inode->i_flctx); |
8634b51f6 locks: convert le... |
1496 |
if (ctx && !list_empty_careful(&ctx->flc_lease)) { |
6109c8503 locks: add a dedi... |
1497 |
spin_lock(&ctx->flc_lock); |
8ace5dfb9 locks: use list_f... |
1498 1499 1500 1501 |
fl = list_first_entry_or_null(&ctx->flc_lease, struct file_lock, fl_list); if (fl && (fl->fl_type == F_WRLCK)) has_lease = true; |
6109c8503 locks: add a dedi... |
1502 |
spin_unlock(&ctx->flc_lock); |
bfe860243 locks: close pote... |
1503 1504 1505 |
} if (has_lease) |
c2050a454 fs: Replace curre... |
1506 |
*time = current_time(inode); |
1da177e4c Linux-2.6.12-rc2 |
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 |
} EXPORT_SYMBOL(lease_get_mtime); /** * fcntl_getlease - Enquire what lease is currently active * @filp: the file * * The value returned by this function will be one of * (if no lease break is pending): * * %F_RDLCK to indicate a shared lease is held. * * %F_WRLCK to indicate an exclusive lease is held. * * %F_UNLCK to indicate no lease is held. * * (if a lease break is pending): * * %F_RDLCK to indicate an exclusive lease needs to be * changed to a shared lease (or removed). * * %F_UNLCK to indicate the lease needs to be removed. * * XXX: sfr & willy disagree over whether F_INPROGRESS * should be returned to userspace. */ int fcntl_getlease(struct file *filp) { struct file_lock *fl; |
c568d6834 locks: fix file l... |
1537 |
struct inode *inode = locks_inode(filp); |
128a37852 fs: fix data race... |
1538 |
struct file_lock_context *ctx; |
1da177e4c Linux-2.6.12-rc2 |
1539 |
int type = F_UNLCK; |
c45198eda locks: move freei... |
1540 |
LIST_HEAD(dispose); |
1da177e4c Linux-2.6.12-rc2 |
1541 |
|
128a37852 fs: fix data race... |
1542 |
ctx = smp_load_acquire(&inode->i_flctx); |
8634b51f6 locks: convert le... |
1543 |
if (ctx && !list_empty_careful(&ctx->flc_lease)) { |
5f43086bb locking, fs/locks... |
1544 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
1545 |
spin_lock(&ctx->flc_lock); |
c568d6834 locks: fix file l... |
1546 |
time_out_leases(inode, &dispose); |
8634b51f6 locks: convert le... |
1547 1548 1549 |
list_for_each_entry(fl, &ctx->flc_lease, fl_list) { if (fl->fl_file != filp) continue; |
778fc546f locks: fix tracki... |
1550 |
type = target_leasetype(fl); |
1da177e4c Linux-2.6.12-rc2 |
1551 1552 |
break; } |
6109c8503 locks: add a dedi... |
1553 |
spin_unlock(&ctx->flc_lock); |
5f43086bb locking, fs/locks... |
1554 |
percpu_up_read_preempt_enable(&file_rwsem); |
8634b51f6 locks: convert le... |
1555 |
locks_dispose_list(&dispose); |
1da177e4c Linux-2.6.12-rc2 |
1556 |
} |
1da177e4c Linux-2.6.12-rc2 |
1557 1558 |
return type; } |
24cbe7845 locks: close pote... |
1559 1560 1561 1562 1563 1564 |
/** * check_conflicting_open - see if the given dentry points to a file that has * an existing open that would conflict with the * desired lease. * @dentry: dentry to check * @arg: type of lease that we're trying to acquire |
7fadc59cc fs: fix fs/locks.... |
1565 |
* @flags: current lock flags |
24cbe7845 locks: close pote... |
1566 1567 1568 1569 1570 |
* * Check to see if there's an existing open fd on this file that would * conflict with the lease we're trying to set. */ static int |
11afe9f76 fs: add FL_LAYOUT... |
1571 |
check_conflicting_open(const struct dentry *dentry, const long arg, int flags) |
24cbe7845 locks: close pote... |
1572 1573 1574 |
{ int ret = 0; struct inode *inode = dentry->d_inode; |
11afe9f76 fs: add FL_LAYOUT... |
1575 1576 |
if (flags & FL_LAYOUT) return 0; |
8cf9ee506 Revert "vfs: do g... |
1577 |
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) |
24cbe7845 locks: close pote... |
1578 1579 1580 1581 1582 1583 1584 1585 |
return -EAGAIN; if ((arg == F_WRLCK) && ((d_count(dentry) > 1) || (atomic_read(&inode->i_count) > 1))) ret = -EAGAIN; return ret; } |
e6f5c7893 locks: plumb a "p... |
1586 1587 |
static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv) |
1da177e4c Linux-2.6.12-rc2 |
1588 |
{ |
8634b51f6 locks: convert le... |
1589 |
struct file_lock *fl, *my_fl = NULL, *lease; |
0f7fc9e4d [PATCH] VFS: chan... |
1590 |
struct dentry *dentry = filp->f_path.dentry; |
c568d6834 locks: fix file l... |
1591 |
struct inode *inode = dentry->d_inode; |
8634b51f6 locks: convert le... |
1592 |
struct file_lock_context *ctx; |
df4e8d2c1 locks: implement ... |
1593 |
bool is_deleg = (*flp)->fl_flags & FL_DELEG; |
c1f24ef4e locks: setlease c... |
1594 |
int error; |
c45198eda locks: move freei... |
1595 |
LIST_HEAD(dispose); |
1da177e4c Linux-2.6.12-rc2 |
1596 |
|
096657b65 locks: fix leaks ... |
1597 |
lease = *flp; |
62af4f1f7 locks: add some t... |
1598 |
trace_generic_add_lease(inode, lease); |
5c1c669a1 locks: don't allo... |
1599 1600 |
/* Note that arg is never F_UNLCK here */ ctx = locks_get_lock_context(inode, arg); |
8634b51f6 locks: convert le... |
1601 1602 |
if (!ctx) return -ENOMEM; |
df4e8d2c1 locks: implement ... |
1603 1604 1605 1606 1607 1608 1609 1610 |
/* * In the delegation case we need mutual exclusion with * a number of operations that take the i_mutex. We trylock * because delegations are an optional optimization, and if * there's some chance of a conflict--we'd rather not * bother, maybe that's a sign this just isn't a good file to * hand out a delegation on. */ |
5955102c9 wrappers for ->i_... |
1611 |
if (is_deleg && !inode_trylock(inode)) |
df4e8d2c1 locks: implement ... |
1612 1613 1614 1615 |
return -EAGAIN; if (is_deleg && arg == F_WRLCK) { /* Write delegations are not currently supported: */ |
5955102c9 wrappers for ->i_... |
1616 |
inode_unlock(inode); |
df4e8d2c1 locks: implement ... |
1617 1618 1619 |
WARN_ON_ONCE(1); return -EINVAL; } |
096657b65 locks: fix leaks ... |
1620 |
|
87709e28d fs/locks: Use per... |
1621 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
1622 |
spin_lock(&ctx->flc_lock); |
c45198eda locks: move freei... |
1623 |
time_out_leases(inode, &dispose); |
11afe9f76 fs: add FL_LAYOUT... |
1624 |
error = check_conflicting_open(dentry, arg, lease->fl_flags); |
24cbe7845 locks: close pote... |
1625 |
if (error) |
096657b65 locks: fix leaks ... |
1626 |
goto out; |
6d5e8b05c locks: share more... |
1627 |
|
1da177e4c Linux-2.6.12-rc2 |
1628 1629 1630 1631 1632 1633 1634 1635 |
/* * At this point, we know that if there is an exclusive * lease on this file, then we hold it on this filp * (otherwise our open of this file would have blocked). * And if we are trying to acquire an exclusive lease, * then the file is not open by anyone (including us) * except for this filp. */ |
c1f24ef4e locks: setlease c... |
1636 |
error = -EAGAIN; |
8634b51f6 locks: convert le... |
1637 |
list_for_each_entry(fl, &ctx->flc_lease, fl_list) { |
2ab99ee12 fs: track fl_owne... |
1638 1639 |
if (fl->fl_file == filp && fl->fl_owner == lease->fl_owner) { |
8634b51f6 locks: convert le... |
1640 |
my_fl = fl; |
c1f24ef4e locks: setlease c... |
1641 1642 |
continue; } |
8634b51f6 locks: convert le... |
1643 |
|
c1f24ef4e locks: setlease c... |
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 |
/* * No exclusive leases if someone else has a lease on * this file: */ if (arg == F_WRLCK) goto out; /* * Modifying our existing lease is OK, but no getting a * new lease if someone else is opening for write: */ if (fl->fl_flags & FL_UNLOCK_PENDING) goto out; |
1da177e4c Linux-2.6.12-rc2 |
1656 |
} |
8634b51f6 locks: convert le... |
1657 |
if (my_fl != NULL) { |
0164bf023 locks: fix fasync... |
1658 1659 |
lease = my_fl; error = lease->fl_lmops->lm_change(lease, arg, &dispose); |
1c7dd2ff4 locks: define a l... |
1660 1661 1662 |
if (error) goto out; goto out_setup; |
1da177e4c Linux-2.6.12-rc2 |
1663 |
} |
1da177e4c Linux-2.6.12-rc2 |
1664 1665 1666 |
error = -EINVAL; if (!leases_enable) goto out; |
e084c1bd4 Revert "locks: ke... |
1667 |
locks_insert_lock_ctx(lease, &ctx->flc_lease); |
24cbe7845 locks: close pote... |
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 |
/* * The check in break_lease() is lockless. It's possible for another * open to race in after we did the earlier check for a conflicting * open but before the lease was inserted. Check again for a * conflicting open and cancel the lease if there is one. * * We also add a barrier here to ensure that the insertion of the lock * precedes these checks. */ smp_mb(); |
11afe9f76 fs: add FL_LAYOUT... |
1678 |
error = check_conflicting_open(dentry, arg, lease->fl_flags); |
8634b51f6 locks: convert le... |
1679 |
if (error) { |
e084c1bd4 Revert "locks: ke... |
1680 |
locks_unlink_lock_ctx(lease); |
8634b51f6 locks: convert le... |
1681 1682 |
goto out; } |
1c7dd2ff4 locks: define a l... |
1683 1684 1685 1686 |
out_setup: if (lease->fl_lmops->lm_setup) lease->fl_lmops->lm_setup(lease, priv); |
1da177e4c Linux-2.6.12-rc2 |
1687 |
out: |
6109c8503 locks: add a dedi... |
1688 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
1689 |
percpu_up_read_preempt_enable(&file_rwsem); |
c45198eda locks: move freei... |
1690 |
locks_dispose_list(&dispose); |
df4e8d2c1 locks: implement ... |
1691 |
if (is_deleg) |
5955102c9 wrappers for ->i_... |
1692 |
inode_unlock(inode); |
8634b51f6 locks: convert le... |
1693 |
if (!error && !my_fl) |
1c7dd2ff4 locks: define a l... |
1694 |
*flp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1695 1696 |
return error; } |
8335ebd94 leases: split up ... |
1697 |
|
2ab99ee12 fs: track fl_owne... |
1698 |
static int generic_delete_lease(struct file *filp, void *owner) |
8335ebd94 leases: split up ... |
1699 |
{ |
0efaa7e82 locks: generic_de... |
1700 |
int error = -EAGAIN; |
8634b51f6 locks: convert le... |
1701 |
struct file_lock *fl, *victim = NULL; |
c568d6834 locks: fix file l... |
1702 |
struct inode *inode = locks_inode(filp); |
128a37852 fs: fix data race... |
1703 |
struct file_lock_context *ctx; |
c45198eda locks: move freei... |
1704 |
LIST_HEAD(dispose); |
8335ebd94 leases: split up ... |
1705 |
|
128a37852 fs: fix data race... |
1706 |
ctx = smp_load_acquire(&inode->i_flctx); |
8634b51f6 locks: convert le... |
1707 1708 1709 1710 |
if (!ctx) { trace_generic_delete_lease(inode, NULL); return error; } |
87709e28d fs/locks: Use per... |
1711 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
1712 |
spin_lock(&ctx->flc_lock); |
8634b51f6 locks: convert le... |
1713 |
list_for_each_entry(fl, &ctx->flc_lease, fl_list) { |
2ab99ee12 fs: track fl_owne... |
1714 1715 |
if (fl->fl_file == filp && fl->fl_owner == owner) { |
8634b51f6 locks: convert le... |
1716 |
victim = fl; |
0efaa7e82 locks: generic_de... |
1717 |
break; |
8634b51f6 locks: convert le... |
1718 |
} |
8335ebd94 leases: split up ... |
1719 |
} |
a9b1b455c locks: fix generi... |
1720 |
trace_generic_delete_lease(inode, victim); |
8634b51f6 locks: convert le... |
1721 |
if (victim) |
7448cc37b locks: clean up t... |
1722 |
error = fl->fl_lmops->lm_change(victim, F_UNLCK, &dispose); |
6109c8503 locks: add a dedi... |
1723 |
spin_unlock(&ctx->flc_lock); |
87709e28d fs/locks: Use per... |
1724 |
percpu_up_read_preempt_enable(&file_rwsem); |
c45198eda locks: move freei... |
1725 |
locks_dispose_list(&dispose); |
0efaa7e82 locks: generic_de... |
1726 |
return error; |
8335ebd94 leases: split up ... |
1727 1728 1729 1730 |
} /** * generic_setlease - sets a lease on an open file |
1c7dd2ff4 locks: define a l... |
1731 1732 1733 1734 1735 |
* @filp: file pointer * @arg: type of lease to obtain * @flp: input - file_lock to use, output - file_lock inserted * @priv: private data for lm_setup (may be NULL if lm_setup * doesn't require it) |
8335ebd94 leases: split up ... |
1736 1737 1738 |
* * The (input) flp->fl_lmops->lm_break function is required * by break_lease(). |
8335ebd94 leases: split up ... |
1739 |
*/ |
e6f5c7893 locks: plumb a "p... |
1740 1741 |
int generic_setlease(struct file *filp, long arg, struct file_lock **flp, void **priv) |
8335ebd94 leases: split up ... |
1742 |
{ |
c568d6834 locks: fix file l... |
1743 |
struct inode *inode = locks_inode(filp); |
8335ebd94 leases: split up ... |
1744 |
int error; |
8e96e3b7b userns: Use uid_e... |
1745 |
if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE)) |
8335ebd94 leases: split up ... |
1746 1747 1748 1749 1750 1751 |
return -EACCES; if (!S_ISREG(inode->i_mode)) return -EINVAL; error = security_file_lock(filp, arg); if (error) return error; |
8335ebd94 leases: split up ... |
1752 1753 |
switch (arg) { case F_UNLCK: |
2ab99ee12 fs: track fl_owne... |
1754 |
return generic_delete_lease(filp, *priv); |
8335ebd94 leases: split up ... |
1755 1756 |
case F_RDLCK: case F_WRLCK: |
0efaa7e82 locks: generic_de... |
1757 1758 1759 1760 |
if (!(*flp)->fl_lmops->lm_break) { WARN_ON_ONCE(1); return -ENOLCK; } |
11afe9f76 fs: add FL_LAYOUT... |
1761 |
|
e6f5c7893 locks: plumb a "p... |
1762 |
return generic_add_lease(filp, arg, flp, priv); |
8335ebd94 leases: split up ... |
1763 |
default: |
8d657eb3b Remove easily use... |
1764 |
return -EINVAL; |
8335ebd94 leases: split up ... |
1765 1766 |
} } |
0af1a4504 rename setlease t... |
1767 |
EXPORT_SYMBOL(generic_setlease); |
1da177e4c Linux-2.6.12-rc2 |
1768 |
|
b89f43213 fs/locks.c: prepa... |
1769 |
/** |
e51673aa5 locks: clean up v... |
1770 |
* vfs_setlease - sets a lease on an open file |
1c7dd2ff4 locks: define a l... |
1771 1772 1773 1774 1775 |
* @filp: file pointer * @arg: type of lease to obtain * @lease: file_lock to use when adding a lease * @priv: private info for lm_setup when adding a lease (may be * NULL if lm_setup doesn't require it) |
e51673aa5 locks: clean up v... |
1776 1777 1778 |
* * Call this to establish a lease on the file. The "lease" argument is not * used for F_UNLCK requests and may be NULL. For commands that set or alter |
80b79dd0e fs: locks: Fix so... |
1779 1780 |
* an existing lease, the ``(*lease)->fl_lmops->lm_break`` operation must be * set; if not, this function will return -ENOLCK (and generate a scary-looking |
e51673aa5 locks: clean up v... |
1781 |
* stack trace). |
1c7dd2ff4 locks: define a l... |
1782 1783 1784 |
* * The "priv" pointer is passed directly to the lm_setup function as-is. It * may be NULL if the lm_setup operation doesn't require it. |
1da177e4c Linux-2.6.12-rc2 |
1785 |
*/ |
e6f5c7893 locks: plumb a "p... |
1786 1787 |
int vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) |
1da177e4c Linux-2.6.12-rc2 |
1788 |
{ |
de2a4a501 Partially revert ... |
1789 |
if (filp->f_op->setlease) |
f82b4b678 locks: move i_loc... |
1790 |
return filp->f_op->setlease(filp, arg, lease, priv); |
1c7dd2ff4 locks: define a l... |
1791 |
else |
f82b4b678 locks: move i_loc... |
1792 |
return generic_setlease(filp, arg, lease, priv); |
1da177e4c Linux-2.6.12-rc2 |
1793 |
} |
a9933cea7 locks: rename lea... |
1794 |
EXPORT_SYMBOL_GPL(vfs_setlease); |
1da177e4c Linux-2.6.12-rc2 |
1795 |
|
0ceaf6c70 locks: prevent EN... |
1796 |
static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) |
1da177e4c Linux-2.6.12-rc2 |
1797 |
{ |
1c7dd2ff4 locks: define a l... |
1798 |
struct file_lock *fl; |
f7347ce4e fasync: re-organi... |
1799 |
struct fasync_struct *new; |
1da177e4c Linux-2.6.12-rc2 |
1800 |
int error; |
c5b1f0d92 locks/nfsd: alloc... |
1801 1802 1803 |
fl = lease_alloc(filp, arg); if (IS_ERR(fl)) return PTR_ERR(fl); |
1da177e4c Linux-2.6.12-rc2 |
1804 |
|
f7347ce4e fasync: re-organi... |
1805 1806 1807 1808 1809 |
new = fasync_alloc(); if (!new) { locks_free_lock(fl); return -ENOMEM; } |
1c7dd2ff4 locks: define a l... |
1810 |
new->fa_fd = fd; |
f7347ce4e fasync: re-organi... |
1811 |
|
1c7dd2ff4 locks: define a l... |
1812 |
error = vfs_setlease(filp, arg, &fl, (void **)&new); |
2dfb928f7 locks: move locks... |
1813 1814 |
if (fl) locks_free_lock(fl); |
f7347ce4e fasync: re-organi... |
1815 1816 |
if (new) fasync_free(new); |
1da177e4c Linux-2.6.12-rc2 |
1817 1818 1819 1820 |
return error; } /** |
0ceaf6c70 locks: prevent EN... |
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 |
* fcntl_setlease - sets a lease on an open file * @fd: open file descriptor * @filp: file pointer * @arg: type of lease to obtain * * Call this fcntl to establish a lease on the file. * Note that you also need to call %F_SETSIG to * receive a signal when the lease is broken. */ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) { if (arg == F_UNLCK) |
2ab99ee12 fs: track fl_owne... |
1833 |
return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); |
0ceaf6c70 locks: prevent EN... |
1834 1835 1836 1837 |
return do_fcntl_add_lease(fd, filp, arg); } /** |
29d01b22e locks: new helper... |
1838 1839 |
* flock_lock_inode_wait - Apply a FLOCK-style lock to a file * @inode: inode of the file to apply to |
1da177e4c Linux-2.6.12-rc2 |
1840 1841 |
* @fl: The lock to be applied * |
29d01b22e locks: new helper... |
1842 |
* Apply a FLOCK style lock request to an inode. |
1da177e4c Linux-2.6.12-rc2 |
1843 |
*/ |
616fb38fa locks: cleanup po... |
1844 |
static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
1845 1846 1847 1848 |
{ int error; might_sleep(); for (;;) { |
29d01b22e locks: new helper... |
1849 |
error = flock_lock_inode(inode, fl); |
bde74e4bc locks: add specia... |
1850 |
if (error != FILE_LOCK_DEFERRED) |
1da177e4c Linux-2.6.12-rc2 |
1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 |
break; error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); if (!error) continue; locks_delete_block(fl); break; } return error; } |
29d01b22e locks: new helper... |
1861 |
/** |
e55c34a66 locks: introduce ... |
1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 |
* locks_lock_inode_wait - Apply a lock to an inode * @inode: inode of the file to apply to * @fl: The lock to be applied * * Apply a POSIX or FLOCK style lock request to an inode. */ int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl) { int res = 0; switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) { case FL_POSIX: res = posix_lock_inode_wait(inode, fl); break; case FL_FLOCK: res = flock_lock_inode_wait(inode, fl); break; default: BUG(); } return res; } EXPORT_SYMBOL(locks_lock_inode_wait); /** |
1da177e4c Linux-2.6.12-rc2 |
1886 1887 1888 1889 1890 |
* sys_flock: - flock() system call. * @fd: the file descriptor to lock. * @cmd: the type of lock to apply. * * Apply a %FL_FLOCK style lock to an open file descriptor. |
80b79dd0e fs: locks: Fix so... |
1891 |
* The @cmd can be one of: |
1da177e4c Linux-2.6.12-rc2 |
1892 |
* |
80b79dd0e fs: locks: Fix so... |
1893 1894 1895 1896 1897 |
* - %LOCK_SH -- a shared lock. * - %LOCK_EX -- an exclusive lock. * - %LOCK_UN -- remove an existing lock. * - %LOCK_MAND -- a 'mandatory' flock. * This exists to emulate Windows Share Modes. |
1da177e4c Linux-2.6.12-rc2 |
1898 1899 1900 1901 |
* * %LOCK_MAND can be combined with %LOCK_READ or %LOCK_WRITE to allow other * processes read and write access respectively. */ |
002c8976e [CVE-2009-0029] S... |
1902 |
SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) |
1da177e4c Linux-2.6.12-rc2 |
1903 |
{ |
2903ff019 switch simple cas... |
1904 |
struct fd f = fdget(fd); |
1da177e4c Linux-2.6.12-rc2 |
1905 1906 1907 1908 1909 |
struct file_lock *lock; int can_sleep, unlock; int error; error = -EBADF; |
2903ff019 switch simple cas... |
1910 |
if (!f.file) |
1da177e4c Linux-2.6.12-rc2 |
1911 1912 1913 1914 1915 |
goto out; can_sleep = !(cmd & LOCK_NB); cmd &= ~LOCK_NB; unlock = (cmd == LOCK_UN); |
aeb5d7270 [PATCH] introduce... |
1916 |
if (!unlock && !(cmd & LOCK_MAND) && |
2903ff019 switch simple cas... |
1917 |
!(f.file->f_mode & (FMODE_READ|FMODE_WRITE))) |
1da177e4c Linux-2.6.12-rc2 |
1918 |
goto out_putf; |
6e129d006 locks: flock_make... |
1919 1920 1921 |
lock = flock_make_lock(f.file, cmd); if (IS_ERR(lock)) { error = PTR_ERR(lock); |
1da177e4c Linux-2.6.12-rc2 |
1922 |
goto out_putf; |
6e129d006 locks: flock_make... |
1923 |
} |
1da177e4c Linux-2.6.12-rc2 |
1924 1925 |
if (can_sleep) lock->fl_flags |= FL_SLEEP; |
2903ff019 switch simple cas... |
1926 |
error = security_file_lock(f.file, lock->fl_type); |
1da177e4c Linux-2.6.12-rc2 |
1927 1928 |
if (error) goto out_free; |
de2a4a501 Partially revert ... |
1929 |
if (f.file->f_op->flock) |
2903ff019 switch simple cas... |
1930 |
error = f.file->f_op->flock(f.file, |
1da177e4c Linux-2.6.12-rc2 |
1931 1932 1933 |
(can_sleep) ? F_SETLKW : F_SETLK, lock); else |
4f6563677 Move locks API us... |
1934 |
error = locks_lock_file_wait(f.file, lock); |
1da177e4c Linux-2.6.12-rc2 |
1935 1936 |
out_free: |
993dfa877 [PATCH] fs/locks.... |
1937 |
locks_free_lock(lock); |
1da177e4c Linux-2.6.12-rc2 |
1938 1939 |
out_putf: |
2903ff019 switch simple cas... |
1940 |
fdput(f); |
1da177e4c Linux-2.6.12-rc2 |
1941 1942 1943 |
out: return error; } |
3ee17abd1 locks: factor out... |
1944 1945 1946 |
/** * vfs_test_lock - test file byte range lock * @filp: The file to test lock for |
6924c5549 locks: fix vfs_te... |
1947 |
* @fl: The lock to test; also used to hold result |
3ee17abd1 locks: factor out... |
1948 1949 1950 1951 1952 1953 |
* * Returns -ERRNO on failure. Indicates presence of conflicting lock by * setting conf->fl_type to something other than F_UNLCK. */ int vfs_test_lock(struct file *filp, struct file_lock *fl) { |
de2a4a501 Partially revert ... |
1954 |
if (filp->f_op->lock) |
3ee17abd1 locks: factor out... |
1955 1956 1957 1958 1959 |
return filp->f_op->lock(filp, F_GETLK, fl); posix_test_lock(filp, fl); return 0; } EXPORT_SYMBOL_GPL(vfs_test_lock); |
9d5b86ac1 fs/locks: Remove ... |
1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 |
/** * locks_translate_pid - translate a file_lock's fl_pid number into a namespace * @fl: The file_lock who's fl_pid should be translated * @ns: The namespace into which the pid should be translated * * Used to tranlate a fl_pid into a namespace virtual pid number */ static pid_t locks_translate_pid(struct file_lock *fl, struct pid_namespace *ns) { pid_t vnr; struct pid *pid; if (IS_OFDLCK(fl)) return -1; if (IS_REMOTELCK(fl)) return fl->fl_pid; |
826d7bc9f fs/lock: skip loc... |
1976 1977 1978 1979 1980 1981 1982 |
/* * If the flock owner process is dead and its pid has been already * freed, the translation below won't work, but we still want to show * flock owner pid number in init pidns. */ if (ns == &init_pid_ns) return (pid_t)fl->fl_pid; |
9d5b86ac1 fs/locks: Remove ... |
1983 1984 1985 1986 1987 1988 1989 |
rcu_read_lock(); pid = find_pid_ns(fl->fl_pid, &init_pid_ns); vnr = pid_nr_ns(pid, ns); rcu_read_unlock(); return vnr; } |
c2fa1b8a6 locks: create pos... |
1990 1991 |
static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) { |
9d5b86ac1 fs/locks: Remove ... |
1992 |
flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current)); |
c2fa1b8a6 locks: create pos... |
1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 |
#if BITS_PER_LONG == 32 /* * Make sure we can represent the posix lock via * legacy 32bit flock. */ if (fl->fl_start > OFFT_OFFSET_MAX) return -EOVERFLOW; if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX) return -EOVERFLOW; #endif flock->l_start = fl->fl_start; flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1; flock->l_whence = 0; |
129a84de2 locks: fix F_GETL... |
2007 |
flock->l_type = fl->fl_type; |
c2fa1b8a6 locks: create pos... |
2008 2009 2010 2011 2012 2013 |
return 0; } #if BITS_PER_LONG == 32 static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) { |
9d5b86ac1 fs/locks: Remove ... |
2014 |
flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current)); |
c2fa1b8a6 locks: create pos... |
2015 2016 2017 2018 2019 2020 2021 |
flock->l_start = fl->fl_start; flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1; flock->l_whence = 0; flock->l_type = fl->fl_type; } #endif |
1da177e4c Linux-2.6.12-rc2 |
2022 2023 2024 |
/* Report the first existing lock that would conflict with l. * This implements the F_GETLK command of fcntl(). */ |
a75d30c77 fs/locks: pass ke... |
2025 |
int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock) |
1da177e4c Linux-2.6.12-rc2 |
2026 |
{ |
52306e882 fs/locks: Use all... |
2027 |
struct file_lock *fl; |
1da177e4c Linux-2.6.12-rc2 |
2028 |
int error; |
52306e882 fs/locks: Use all... |
2029 2030 2031 |
fl = locks_alloc_lock(); if (fl == NULL) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
2032 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2033 |
if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK) |
1da177e4c Linux-2.6.12-rc2 |
2034 |
goto out; |
52306e882 fs/locks: Use all... |
2035 |
error = flock_to_posix_lock(filp, fl, flock); |
1da177e4c Linux-2.6.12-rc2 |
2036 2037 |
if (error) goto out; |
0d3f7a2dd locks: rename fil... |
2038 |
if (cmd == F_OFD_GETLK) { |
90478939d locks: require th... |
2039 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2040 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2041 |
goto out; |
5d50ffd7c locks: add new fc... |
2042 |
cmd = F_GETLK; |
52306e882 fs/locks: Use all... |
2043 2044 |
fl->fl_flags |= FL_OFDLCK; fl->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2045 |
} |
52306e882 fs/locks: Use all... |
2046 |
error = vfs_test_lock(filp, fl); |
3ee17abd1 locks: factor out... |
2047 2048 |
if (error) goto out; |
1da177e4c Linux-2.6.12-rc2 |
2049 |
|
52306e882 fs/locks: Use all... |
2050 2051 2052 |
flock->l_type = fl->fl_type; if (fl->fl_type != F_UNLCK) { error = posix_lock_to_flock(flock, fl); |
c2fa1b8a6 locks: create pos... |
2053 |
if (error) |
52306e882 fs/locks: Use all... |
2054 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2055 |
} |
1da177e4c Linux-2.6.12-rc2 |
2056 |
out: |
52306e882 fs/locks: Use all... |
2057 |
locks_free_lock(fl); |
1da177e4c Linux-2.6.12-rc2 |
2058 2059 |
return error; } |
7723ec977 locks: factor out... |
2060 2061 2062 2063 2064 |
/** * vfs_lock_file - file byte range lock * @filp: The file to apply the lock to * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.) * @fl: The lock to be applied |
150b39345 locks: allow {vfs... |
2065 2066 2067 2068 2069 2070 2071 2072 |
* @conf: Place to return a copy of the conflicting lock, if found. * * A caller that doesn't care about the conflicting lock may pass NULL * as the final argument. * * If the filesystem defines a private ->lock() method, then @conf will * be left unchanged; so a caller that cares should initialize it to * some acceptable default. |
2beb6614f locks: add fl_gra... |
2073 2074 2075 2076 |
* * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX * locks, the ->lock() interface may return asynchronously, before the lock has * been granted or denied by the underlying filesystem, if (and only if) |
8fb47a4fb locks: rename loc... |
2077 |
* lm_grant is set. Callers expecting ->lock() to return asynchronously |
2beb6614f locks: add fl_gra... |
2078 2079 |
* will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) * the request is for a blocking lock. When ->lock() does return asynchronously, |
8fb47a4fb locks: rename loc... |
2080 |
* it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock |
2beb6614f locks: add fl_gra... |
2081 2082 |
* request completes. * If the request is for non-blocking lock the file system should return |
bde74e4bc locks: add specia... |
2083 2084 |
* FILE_LOCK_DEFERRED then try to get the lock and call the callback routine * with the result. If the request timed out the callback routine will return a |
2beb6614f locks: add fl_gra... |
2085 2086 2087 2088 2089 |
* nonzero return code and the file system should release the lock. The file * system is also responsible to keep a corresponding posix lock when it * grants a lock so the VFS can find out which locks are locally held and do * the correct lock cleanup when required. * The underlying filesystem must not drop the kernel lock or call |
8fb47a4fb locks: rename loc... |
2090 |
* ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED |
2beb6614f locks: add fl_gra... |
2091 |
* return code. |
7723ec977 locks: factor out... |
2092 |
*/ |
150b39345 locks: allow {vfs... |
2093 |
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) |
7723ec977 locks: factor out... |
2094 |
{ |
de2a4a501 Partially revert ... |
2095 |
if (filp->f_op->lock) |
7723ec977 locks: factor out... |
2096 2097 |
return filp->f_op->lock(filp, cmd, fl); else |
150b39345 locks: allow {vfs... |
2098 |
return posix_lock_file(filp, fl, conf); |
7723ec977 locks: factor out... |
2099 2100 |
} EXPORT_SYMBOL_GPL(vfs_lock_file); |
b648a6de0 locks: cleanup co... |
2101 2102 2103 2104 2105 2106 2107 2108 |
static int do_lock_file_wait(struct file *filp, unsigned int cmd, struct file_lock *fl) { int error; error = security_file_lock(filp, fl->fl_type); if (error) return error; |
764c76b37 locks: allow ->lo... |
2109 2110 2111 |
for (;;) { error = vfs_lock_file(filp, cmd, fl, NULL); if (error != FILE_LOCK_DEFERRED) |
b648a6de0 locks: cleanup co... |
2112 |
break; |
764c76b37 locks: allow ->lo... |
2113 2114 2115 2116 2117 2118 |
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); if (!error) continue; locks_delete_block(fl); break; |
b648a6de0 locks: cleanup co... |
2119 2120 2121 2122 |
} return error; } |
6ca7d9101 locks: Use more f... |
2123 |
/* Ensure that fl->fl_file has compatible f_mode for F_SETLK calls */ |
cf01f4eef locks: only valid... |
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 |
static int check_fmode_for_setlk(struct file_lock *fl) { switch (fl->fl_type) { case F_RDLCK: if (!(fl->fl_file->f_mode & FMODE_READ)) return -EBADF; break; case F_WRLCK: if (!(fl->fl_file->f_mode & FMODE_WRITE)) return -EBADF; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
2138 2139 2140 |
/* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ |
c293621bb [PATCH] stale POS... |
2141 |
int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, |
a75d30c77 fs/locks: pass ke... |
2142 |
struct flock *flock) |
1da177e4c Linux-2.6.12-rc2 |
2143 2144 |
{ struct file_lock *file_lock = locks_alloc_lock(); |
a75d30c77 fs/locks: pass ke... |
2145 |
struct inode *inode = locks_inode(filp); |
0b2bac2f1 [PATCH] fix SMP o... |
2146 |
struct file *f; |
1da177e4c Linux-2.6.12-rc2 |
2147 2148 2149 2150 |
int error; if (file_lock == NULL) return -ENOLCK; |
1da177e4c Linux-2.6.12-rc2 |
2151 2152 2153 |
/* Don't allow mandatory locks on files that may be memory mapped * and shared. */ |
a16877ca9 Cleanup macros fo... |
2154 |
if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) { |
1da177e4c Linux-2.6.12-rc2 |
2155 2156 2157 |
error = -EAGAIN; goto out; } |
a75d30c77 fs/locks: pass ke... |
2158 |
error = flock_to_posix_lock(filp, file_lock, flock); |
1da177e4c Linux-2.6.12-rc2 |
2159 2160 |
if (error) goto out; |
5d50ffd7c locks: add new fc... |
2161 |
|
cf01f4eef locks: only valid... |
2162 2163 2164 |
error = check_fmode_for_setlk(file_lock); if (error) goto out; |
5d50ffd7c locks: add new fc... |
2165 2166 |
/* * If the cmd is requesting file-private locks, then set the |
cff2fce58 locks: rename FL_... |
2167 |
* FL_OFDLCK flag and override the owner. |
5d50ffd7c locks: add new fc... |
2168 2169 |
*/ switch (cmd) { |
0d3f7a2dd locks: rename fil... |
2170 |
case F_OFD_SETLK: |
90478939d locks: require th... |
2171 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2172 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2173 |
goto out; |
5d50ffd7c locks: add new fc... |
2174 |
cmd = F_SETLK; |
cff2fce58 locks: rename FL_... |
2175 |
file_lock->fl_flags |= FL_OFDLCK; |
73a8f5f7e locks: purge fl_o... |
2176 |
file_lock->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2177 |
break; |
0d3f7a2dd locks: rename fil... |
2178 |
case F_OFD_SETLKW: |
90478939d locks: require th... |
2179 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2180 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2181 |
goto out; |
5d50ffd7c locks: add new fc... |
2182 |
cmd = F_SETLKW; |
cff2fce58 locks: rename FL_... |
2183 |
file_lock->fl_flags |= FL_OFDLCK; |
73a8f5f7e locks: purge fl_o... |
2184 |
file_lock->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2185 2186 |
/* Fallthrough */ case F_SETLKW: |
1da177e4c Linux-2.6.12-rc2 |
2187 2188 |
file_lock->fl_flags |= FL_SLEEP; } |
5d50ffd7c locks: add new fc... |
2189 |
|
b648a6de0 locks: cleanup co... |
2190 |
error = do_lock_file_wait(filp, cmd, file_lock); |
1da177e4c Linux-2.6.12-rc2 |
2191 |
|
c293621bb [PATCH] stale POS... |
2192 |
/* |
0752ba807 locks: don't chec... |
2193 2194 2195 |
* Attempt to detect a close/fcntl race and recover by releasing the * lock that was just acquired. There is no need to do that when we're * unlocking though, or for OFD locks. |
c293621bb [PATCH] stale POS... |
2196 |
*/ |
0752ba807 locks: don't chec... |
2197 2198 |
if (!error && file_lock->fl_type != F_UNLCK && !(file_lock->fl_flags & FL_OFDLCK)) { |
7f3697e24 locks: fix unlock... |
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 |
/* * We need that spin_lock here - it prevents reordering between * update of i_flctx->flc_posix and check for it done in * close(). rcu_read_lock() wouldn't do. */ spin_lock(¤t->files->file_lock); f = fcheck(fd); spin_unlock(¤t->files->file_lock); if (f != filp) { file_lock->fl_type = F_UNLCK; error = do_lock_file_wait(filp, cmd, file_lock); WARN_ON_ONCE(error); error = -EBADF; } |
1da177e4c Linux-2.6.12-rc2 |
2213 |
} |
c293621bb [PATCH] stale POS... |
2214 |
out: |
1890910fd locks: sprinkle s... |
2215 |
trace_fcntl_setlk(inode, file_lock, error); |
1da177e4c Linux-2.6.12-rc2 |
2216 2217 2218 2219 2220 2221 2222 2223 |
locks_free_lock(file_lock); return error; } #if BITS_PER_LONG == 32 /* Report the first existing lock that would conflict with l. * This implements the F_GETLK command of fcntl(). */ |
a75d30c77 fs/locks: pass ke... |
2224 |
int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock) |
1da177e4c Linux-2.6.12-rc2 |
2225 |
{ |
52306e882 fs/locks: Use all... |
2226 |
struct file_lock *fl; |
1da177e4c Linux-2.6.12-rc2 |
2227 |
int error; |
52306e882 fs/locks: Use all... |
2228 2229 2230 |
fl = locks_alloc_lock(); if (fl == NULL) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
2231 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2232 |
if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK) |
1da177e4c Linux-2.6.12-rc2 |
2233 |
goto out; |
52306e882 fs/locks: Use all... |
2234 |
error = flock64_to_posix_lock(filp, fl, flock); |
1da177e4c Linux-2.6.12-rc2 |
2235 2236 |
if (error) goto out; |
0d3f7a2dd locks: rename fil... |
2237 |
if (cmd == F_OFD_GETLK) { |
90478939d locks: require th... |
2238 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2239 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2240 |
goto out; |
5d50ffd7c locks: add new fc... |
2241 |
cmd = F_GETLK64; |
52306e882 fs/locks: Use all... |
2242 2243 |
fl->fl_flags |= FL_OFDLCK; fl->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2244 |
} |
52306e882 fs/locks: Use all... |
2245 |
error = vfs_test_lock(filp, fl); |
3ee17abd1 locks: factor out... |
2246 2247 |
if (error) goto out; |
52306e882 fs/locks: Use all... |
2248 2249 2250 |
flock->l_type = fl->fl_type; if (fl->fl_type != F_UNLCK) posix_lock_to_flock64(flock, fl); |
f328296e2 locks: Copy fl_lm... |
2251 |
|
1da177e4c Linux-2.6.12-rc2 |
2252 |
out: |
52306e882 fs/locks: Use all... |
2253 |
locks_free_lock(fl); |
1da177e4c Linux-2.6.12-rc2 |
2254 2255 2256 2257 2258 2259 |
return error; } /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ |
c293621bb [PATCH] stale POS... |
2260 |
int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, |
a75d30c77 fs/locks: pass ke... |
2261 |
struct flock64 *flock) |
1da177e4c Linux-2.6.12-rc2 |
2262 2263 |
{ struct file_lock *file_lock = locks_alloc_lock(); |
a75d30c77 fs/locks: pass ke... |
2264 |
struct inode *inode = locks_inode(filp); |
0b2bac2f1 [PATCH] fix SMP o... |
2265 |
struct file *f; |
1da177e4c Linux-2.6.12-rc2 |
2266 2267 2268 2269 |
int error; if (file_lock == NULL) return -ENOLCK; |
1da177e4c Linux-2.6.12-rc2 |
2270 2271 2272 |
/* Don't allow mandatory locks on files that may be memory mapped * and shared. */ |
a16877ca9 Cleanup macros fo... |
2273 |
if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) { |
1da177e4c Linux-2.6.12-rc2 |
2274 2275 2276 |
error = -EAGAIN; goto out; } |
a75d30c77 fs/locks: pass ke... |
2277 |
error = flock64_to_posix_lock(filp, file_lock, flock); |
1da177e4c Linux-2.6.12-rc2 |
2278 2279 |
if (error) goto out; |
5d50ffd7c locks: add new fc... |
2280 |
|
cf01f4eef locks: only valid... |
2281 2282 2283 |
error = check_fmode_for_setlk(file_lock); if (error) goto out; |
5d50ffd7c locks: add new fc... |
2284 2285 |
/* * If the cmd is requesting file-private locks, then set the |
cff2fce58 locks: rename FL_... |
2286 |
* FL_OFDLCK flag and override the owner. |
5d50ffd7c locks: add new fc... |
2287 2288 |
*/ switch (cmd) { |
0d3f7a2dd locks: rename fil... |
2289 |
case F_OFD_SETLK: |
90478939d locks: require th... |
2290 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2291 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2292 |
goto out; |
5d50ffd7c locks: add new fc... |
2293 |
cmd = F_SETLK64; |
cff2fce58 locks: rename FL_... |
2294 |
file_lock->fl_flags |= FL_OFDLCK; |
73a8f5f7e locks: purge fl_o... |
2295 |
file_lock->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2296 |
break; |
0d3f7a2dd locks: rename fil... |
2297 |
case F_OFD_SETLKW: |
90478939d locks: require th... |
2298 |
error = -EINVAL; |
a75d30c77 fs/locks: pass ke... |
2299 |
if (flock->l_pid != 0) |
90478939d locks: require th... |
2300 |
goto out; |
5d50ffd7c locks: add new fc... |
2301 |
cmd = F_SETLKW64; |
cff2fce58 locks: rename FL_... |
2302 |
file_lock->fl_flags |= FL_OFDLCK; |
73a8f5f7e locks: purge fl_o... |
2303 |
file_lock->fl_owner = filp; |
5d50ffd7c locks: add new fc... |
2304 2305 |
/* Fallthrough */ case F_SETLKW64: |
1da177e4c Linux-2.6.12-rc2 |
2306 2307 |
file_lock->fl_flags |= FL_SLEEP; } |
5d50ffd7c locks: add new fc... |
2308 |
|
b648a6de0 locks: cleanup co... |
2309 |
error = do_lock_file_wait(filp, cmd, file_lock); |
1da177e4c Linux-2.6.12-rc2 |
2310 |
|
c293621bb [PATCH] stale POS... |
2311 |
/* |
0752ba807 locks: don't chec... |
2312 2313 2314 |
* Attempt to detect a close/fcntl race and recover by releasing the * lock that was just acquired. There is no need to do that when we're * unlocking though, or for OFD locks. |
c293621bb [PATCH] stale POS... |
2315 |
*/ |
0752ba807 locks: don't chec... |
2316 2317 |
if (!error && file_lock->fl_type != F_UNLCK && !(file_lock->fl_flags & FL_OFDLCK)) { |
7f3697e24 locks: fix unlock... |
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 |
/* * We need that spin_lock here - it prevents reordering between * update of i_flctx->flc_posix and check for it done in * close(). rcu_read_lock() wouldn't do. */ spin_lock(¤t->files->file_lock); f = fcheck(fd); spin_unlock(¤t->files->file_lock); if (f != filp) { file_lock->fl_type = F_UNLCK; error = do_lock_file_wait(filp, cmd, file_lock); WARN_ON_ONCE(error); error = -EBADF; } |
1da177e4c Linux-2.6.12-rc2 |
2332 |
} |
1da177e4c Linux-2.6.12-rc2 |
2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 |
out: locks_free_lock(file_lock); return error; } #endif /* BITS_PER_LONG == 32 */ /* * This function is called when the file is being removed * from the task's fd array. POSIX locks belonging to this task * are deleted at this time. */ void locks_remove_posix(struct file *filp, fl_owner_t owner) { |
1890910fd locks: sprinkle s... |
2346 |
int error; |
c568d6834 locks: fix file l... |
2347 |
struct inode *inode = locks_inode(filp); |
ff7b86b82 [PATCH] locks: cl... |
2348 |
struct file_lock lock; |
128a37852 fs: fix data race... |
2349 |
struct file_lock_context *ctx; |
1da177e4c Linux-2.6.12-rc2 |
2350 2351 2352 2353 2354 2355 |
/* * If there are no locks held on this file, we don't need to call * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ |
c568d6834 locks: fix file l... |
2356 |
ctx = smp_load_acquire(&inode->i_flctx); |
bd61e0a9c locks: convert po... |
2357 |
if (!ctx || list_empty(&ctx->flc_posix)) |
1da177e4c Linux-2.6.12-rc2 |
2358 2359 2360 |
return; lock.fl_type = F_UNLCK; |
75e1fcc0b [PATCH] vfs: add ... |
2361 |
lock.fl_flags = FL_POSIX | FL_CLOSE; |
1da177e4c Linux-2.6.12-rc2 |
2362 2363 2364 2365 2366 2367 2368 |
lock.fl_start = 0; lock.fl_end = OFFSET_MAX; lock.fl_owner = owner; lock.fl_pid = current->tgid; lock.fl_file = filp; lock.fl_ops = NULL; lock.fl_lmops = NULL; |
1890910fd locks: sprinkle s... |
2369 |
error = vfs_lock_file(filp, F_SETLK, &lock, NULL); |
1da177e4c Linux-2.6.12-rc2 |
2370 |
|
1da177e4c Linux-2.6.12-rc2 |
2371 2372 |
if (lock.fl_ops && lock.fl_ops->fl_release_private) lock.fl_ops->fl_release_private(&lock); |
c568d6834 locks: fix file l... |
2373 |
trace_locks_remove_posix(inode, &lock, error); |
1da177e4c Linux-2.6.12-rc2 |
2374 2375 2376 |
} EXPORT_SYMBOL(locks_remove_posix); |
3d8e560de locks: consolidat... |
2377 |
/* The i_flctx must be valid when calling into here */ |
dd459bb19 locks: have locks... |
2378 |
static void |
128a37852 fs: fix data race... |
2379 |
locks_remove_flock(struct file *filp, struct file_lock_context *flctx) |
dd459bb19 locks: have locks... |
2380 2381 2382 2383 2384 |
{ struct file_lock fl = { .fl_owner = filp, .fl_pid = current->tgid, .fl_file = filp, |
50f2112cf locks: Set FL_CLO... |
2385 |
.fl_flags = FL_FLOCK | FL_CLOSE, |
dd459bb19 locks: have locks... |
2386 2387 2388 |
.fl_type = F_UNLCK, .fl_end = OFFSET_MAX, }; |
c568d6834 locks: fix file l... |
2389 |
struct inode *inode = locks_inode(filp); |
dd459bb19 locks: have locks... |
2390 |
|
3d8e560de locks: consolidat... |
2391 |
if (list_empty(&flctx->flc_flock)) |
dd459bb19 locks: have locks... |
2392 |
return; |
de2a4a501 Partially revert ... |
2393 |
if (filp->f_op->flock) |
dd459bb19 locks: have locks... |
2394 2395 |
filp->f_op->flock(filp, F_SETLKW, &fl); else |
bcd7f78d0 locks: have flock... |
2396 |
flock_lock_inode(inode, &fl); |
dd459bb19 locks: have locks... |
2397 2398 2399 2400 |
if (fl.fl_ops && fl.fl_ops->fl_release_private) fl.fl_ops->fl_release_private(&fl); } |
3d8e560de locks: consolidat... |
2401 |
/* The i_flctx must be valid when calling into here */ |
8634b51f6 locks: convert le... |
2402 |
static void |
128a37852 fs: fix data race... |
2403 |
locks_remove_lease(struct file *filp, struct file_lock_context *ctx) |
8634b51f6 locks: convert le... |
2404 |
{ |
8634b51f6 locks: convert le... |
2405 2406 |
struct file_lock *fl, *tmp; LIST_HEAD(dispose); |
3d8e560de locks: consolidat... |
2407 |
if (list_empty(&ctx->flc_lease)) |
8634b51f6 locks: convert le... |
2408 |
return; |
5f43086bb locking, fs/locks... |
2409 |
percpu_down_read_preempt_disable(&file_rwsem); |
6109c8503 locks: add a dedi... |
2410 |
spin_lock(&ctx->flc_lock); |
8634b51f6 locks: convert le... |
2411 |
list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) |
c4e136cda locks: only remov... |
2412 2413 |
if (filp == fl->fl_file) lease_modify(fl, F_UNLCK, &dispose); |
6109c8503 locks: add a dedi... |
2414 |
spin_unlock(&ctx->flc_lock); |
5f43086bb locking, fs/locks... |
2415 |
percpu_up_read_preempt_enable(&file_rwsem); |
8634b51f6 locks: convert le... |
2416 2417 |
locks_dispose_list(&dispose); } |
1da177e4c Linux-2.6.12-rc2 |
2418 2419 2420 |
/* * This function is called on the last close of an open file. */ |
78ed8a133 locks: rename loc... |
2421 |
void locks_remove_file(struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
2422 |
{ |
128a37852 fs: fix data race... |
2423 |
struct file_lock_context *ctx; |
c568d6834 locks: fix file l... |
2424 |
ctx = smp_load_acquire(&locks_inode(filp)->i_flctx); |
128a37852 fs: fix data race... |
2425 |
if (!ctx) |
3d8e560de locks: consolidat... |
2426 |
return; |
dd459bb19 locks: have locks... |
2427 |
/* remove any OFD locks */ |
73a8f5f7e locks: purge fl_o... |
2428 |
locks_remove_posix(filp, filp); |
5d50ffd7c locks: add new fc... |
2429 |
|
dd459bb19 locks: have locks... |
2430 |
/* remove flock locks */ |
128a37852 fs: fix data race... |
2431 |
locks_remove_flock(filp, ctx); |
dd459bb19 locks: have locks... |
2432 |
|
8634b51f6 locks: convert le... |
2433 |
/* remove any leases */ |
128a37852 fs: fix data race... |
2434 |
locks_remove_lease(filp, ctx); |
3953704fd locks: restore a ... |
2435 2436 2437 2438 2439 2440 |
spin_lock(&ctx->flc_lock); locks_check_ctx_file_list(filp, &ctx->flc_posix, "POSIX"); locks_check_ctx_file_list(filp, &ctx->flc_flock, "FLOCK"); locks_check_ctx_file_list(filp, &ctx->flc_lease, "LEASE"); spin_unlock(&ctx->flc_lock); |
1da177e4c Linux-2.6.12-rc2 |
2441 2442 2443 |
} /** |
1da177e4c Linux-2.6.12-rc2 |
2444 |
* posix_unblock_lock - stop waiting for a file lock |
1da177e4c Linux-2.6.12-rc2 |
2445 2446 2447 2448 |
* @waiter: the lock which was waiting * * lockd needs to block waiting for locks. */ |
64a318ee2 NLM: Further canc... |
2449 |
int |
f891a29f4 locks: drop the u... |
2450 |
posix_unblock_lock(struct file_lock *waiter) |
1da177e4c Linux-2.6.12-rc2 |
2451 |
{ |
64a318ee2 NLM: Further canc... |
2452 |
int status = 0; |
7b2296afb locks: give the b... |
2453 |
spin_lock(&blocked_lock_lock); |
5996a298d NLM: don't unlock... |
2454 |
if (waiter->fl_next) |
1da177e4c Linux-2.6.12-rc2 |
2455 |
__locks_delete_block(waiter); |
64a318ee2 NLM: Further canc... |
2456 2457 |
else status = -ENOENT; |
7b2296afb locks: give the b... |
2458 |
spin_unlock(&blocked_lock_lock); |
64a318ee2 NLM: Further canc... |
2459 |
return status; |
1da177e4c Linux-2.6.12-rc2 |
2460 |
} |
1da177e4c Linux-2.6.12-rc2 |
2461 |
EXPORT_SYMBOL(posix_unblock_lock); |
9b9d2ab41 locks: add lock c... |
2462 2463 2464 2465 2466 2467 2468 2469 2470 |
/** * vfs_cancel_lock - file byte range unblock lock * @filp: The file to apply the unblock to * @fl: The lock to be unblocked * * Used by lock managers to cancel blocked requests */ int vfs_cancel_lock(struct file *filp, struct file_lock *fl) { |
de2a4a501 Partially revert ... |
2471 |
if (filp->f_op->lock) |
9b9d2ab41 locks: add lock c... |
2472 2473 2474 2475 2476 |
return filp->f_op->lock(filp, F_CANCELLK, fl); return 0; } EXPORT_SYMBOL_GPL(vfs_cancel_lock); |
7f8ada98d Rework /proc/lock... |
2477 |
#ifdef CONFIG_PROC_FS |
d8ba7a363 proc: move rest o... |
2478 |
#include <linux/proc_fs.h> |
7f8ada98d Rework /proc/lock... |
2479 |
#include <linux/seq_file.h> |
7012b02a2 locks: move file_... |
2480 2481 2482 2483 |
struct locks_iterator { int li_cpu; loff_t li_pos; }; |
7f8ada98d Rework /proc/lock... |
2484 |
static void lock_get_status(struct seq_file *f, struct file_lock *fl, |
99dc82925 procfs: fix numbe... |
2485 |
loff_t id, char *pfx) |
1da177e4c Linux-2.6.12-rc2 |
2486 2487 |
{ struct inode *inode = NULL; |
ab1f16116 pid-namespaces-vs... |
2488 |
unsigned int fl_pid; |
9d5b86ac1 fs/locks: Remove ... |
2489 |
struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info; |
ab1f16116 pid-namespaces-vs... |
2490 |
|
9d5b86ac1 fs/locks: Remove ... |
2491 2492 |
fl_pid = locks_translate_pid(fl, proc_pidns); /* |
1cf8e5de4 fs/lock: show loc... |
2493 2494 2495 |
* If lock owner is dead (and pid is freed) or not visible in current * pidns, zero is shown as a pid value. Check lock info from * init_pid_ns to get saved lock pid value. |
9d5b86ac1 fs/locks: Remove ... |
2496 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
2497 2498 |
if (fl->fl_file != NULL) |
c568d6834 locks: fix file l... |
2499 |
inode = locks_inode(fl->fl_file); |
1da177e4c Linux-2.6.12-rc2 |
2500 |
|
99dc82925 procfs: fix numbe... |
2501 |
seq_printf(f, "%lld:%s ", id, pfx); |
1da177e4c Linux-2.6.12-rc2 |
2502 |
if (IS_POSIX(fl)) { |
c918d42a2 locks: make /proc... |
2503 |
if (fl->fl_flags & FL_ACCESS) |
5315c26a6 fs/locks.c: repla... |
2504 |
seq_puts(f, "ACCESS"); |
cff2fce58 locks: rename FL_... |
2505 |
else if (IS_OFDLCK(fl)) |
5315c26a6 fs/locks.c: repla... |
2506 |
seq_puts(f, "OFDLCK"); |
c918d42a2 locks: make /proc... |
2507 |
else |
5315c26a6 fs/locks.c: repla... |
2508 |
seq_puts(f, "POSIX "); |
c918d42a2 locks: make /proc... |
2509 2510 |
seq_printf(f, " %s ", |
1da177e4c Linux-2.6.12-rc2 |
2511 |
(inode == NULL) ? "*NOINODE*" : |
a16877ca9 Cleanup macros fo... |
2512 |
mandatory_lock(inode) ? "MANDATORY" : "ADVISORY "); |
1da177e4c Linux-2.6.12-rc2 |
2513 2514 |
} else if (IS_FLOCK(fl)) { if (fl->fl_type & LOCK_MAND) { |
5315c26a6 fs/locks.c: repla... |
2515 |
seq_puts(f, "FLOCK MSNFS "); |
1da177e4c Linux-2.6.12-rc2 |
2516 |
} else { |
5315c26a6 fs/locks.c: repla... |
2517 |
seq_puts(f, "FLOCK ADVISORY "); |
1da177e4c Linux-2.6.12-rc2 |
2518 2519 |
} } else if (IS_LEASE(fl)) { |
8144f1f69 locks: show deleg... |
2520 2521 2522 2523 |
if (fl->fl_flags & FL_DELEG) seq_puts(f, "DELEG "); else seq_puts(f, "LEASE "); |
ab83fa4b4 locks: minor leas... |
2524 |
if (lease_breaking(fl)) |
5315c26a6 fs/locks.c: repla... |
2525 |
seq_puts(f, "BREAKING "); |
1da177e4c Linux-2.6.12-rc2 |
2526 |
else if (fl->fl_file) |
5315c26a6 fs/locks.c: repla... |
2527 |
seq_puts(f, "ACTIVE "); |
1da177e4c Linux-2.6.12-rc2 |
2528 |
else |
5315c26a6 fs/locks.c: repla... |
2529 |
seq_puts(f, "BREAKER "); |
1da177e4c Linux-2.6.12-rc2 |
2530 |
} else { |
5315c26a6 fs/locks.c: repla... |
2531 |
seq_puts(f, "UNKNOWN UNKNOWN "); |
1da177e4c Linux-2.6.12-rc2 |
2532 2533 |
} if (fl->fl_type & LOCK_MAND) { |
7f8ada98d Rework /proc/lock... |
2534 |
seq_printf(f, "%s ", |
1da177e4c Linux-2.6.12-rc2 |
2535 2536 2537 2538 |
(fl->fl_type & LOCK_READ) ? (fl->fl_type & LOCK_WRITE) ? "RW " : "READ " : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE "); } else { |
7f8ada98d Rework /proc/lock... |
2539 |
seq_printf(f, "%s ", |
ab83fa4b4 locks: minor leas... |
2540 |
(lease_breaking(fl)) |
0ee5c6d63 vfs: don't treat ... |
2541 2542 |
? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ " : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ "); |
1da177e4c Linux-2.6.12-rc2 |
2543 2544 |
} if (inode) { |
3648888e9 locks: get rid of... |
2545 |
/* userspace relies on this representation of dev_t */ |
ab1f16116 pid-namespaces-vs... |
2546 |
seq_printf(f, "%d %02x:%02x:%ld ", fl_pid, |
1da177e4c Linux-2.6.12-rc2 |
2547 2548 |
MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), inode->i_ino); |
1da177e4c Linux-2.6.12-rc2 |
2549 |
} else { |
ab1f16116 pid-namespaces-vs... |
2550 |
seq_printf(f, "%d <none>:0 ", fl_pid); |
1da177e4c Linux-2.6.12-rc2 |
2551 2552 2553 |
} if (IS_POSIX(fl)) { if (fl->fl_end == OFFSET_MAX) |
7f8ada98d Rework /proc/lock... |
2554 2555 |
seq_printf(f, "%Ld EOF ", fl->fl_start); |
1da177e4c Linux-2.6.12-rc2 |
2556 |
else |
7f8ada98d Rework /proc/lock... |
2557 2558 |
seq_printf(f, "%Ld %Ld ", fl->fl_start, fl->fl_end); |
1da177e4c Linux-2.6.12-rc2 |
2559 |
} else { |
5315c26a6 fs/locks.c: repla... |
2560 2561 |
seq_puts(f, "0 EOF "); |
1da177e4c Linux-2.6.12-rc2 |
2562 2563 |
} } |
7f8ada98d Rework /proc/lock... |
2564 |
static int locks_show(struct seq_file *f, void *v) |
1da177e4c Linux-2.6.12-rc2 |
2565 |
{ |
7012b02a2 locks: move file_... |
2566 |
struct locks_iterator *iter = f->private; |
7f8ada98d Rework /proc/lock... |
2567 |
struct file_lock *fl, *bfl; |
d67fd44f6 locks: Filter /pr... |
2568 |
struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info; |
1da177e4c Linux-2.6.12-rc2 |
2569 |
|
139ca04ee locks: convert fl... |
2570 |
fl = hlist_entry(v, struct file_lock, fl_link); |
1da177e4c Linux-2.6.12-rc2 |
2571 |
|
9d5b86ac1 fs/locks: Remove ... |
2572 |
if (locks_translate_pid(fl, proc_pidns) == 0) |
d67fd44f6 locks: Filter /pr... |
2573 |
return 0; |
7012b02a2 locks: move file_... |
2574 |
lock_get_status(f, fl, iter->li_pos, ""); |
1da177e4c Linux-2.6.12-rc2 |
2575 |
|
7f8ada98d Rework /proc/lock... |
2576 |
list_for_each_entry(bfl, &fl->fl_block, fl_block) |
7012b02a2 locks: move file_... |
2577 |
lock_get_status(f, bfl, iter->li_pos, " ->"); |
094f28252 fs/locks.c: use l... |
2578 |
|
7f8ada98d Rework /proc/lock... |
2579 2580 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
2581 |
|
6c8c90319 proc: show locks ... |
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 |
static void __show_fd_locks(struct seq_file *f, struct list_head *head, int *id, struct file *filp, struct files_struct *files) { struct file_lock *fl; list_for_each_entry(fl, head, fl_list) { if (filp != fl->fl_file) continue; if (fl->fl_owner != files && fl->fl_owner != filp) continue; (*id)++; seq_puts(f, "lock:\t"); lock_get_status(f, fl, *id, ""); } } void show_fd_locks(struct seq_file *f, struct file *filp, struct files_struct *files) { |
c568d6834 locks: fix file l... |
2605 |
struct inode *inode = locks_inode(filp); |
6c8c90319 proc: show locks ... |
2606 2607 |
struct file_lock_context *ctx; int id = 0; |
128a37852 fs: fix data race... |
2608 |
ctx = smp_load_acquire(&inode->i_flctx); |
6c8c90319 proc: show locks ... |
2609 2610 2611 2612 2613 2614 2615 2616 2617 |
if (!ctx) return; spin_lock(&ctx->flc_lock); __show_fd_locks(f, &ctx->flc_flock, &id, filp, files); __show_fd_locks(f, &ctx->flc_posix, &id, filp, files); __show_fd_locks(f, &ctx->flc_lease, &id, filp, files); spin_unlock(&ctx->flc_lock); } |
7f8ada98d Rework /proc/lock... |
2618 |
static void *locks_start(struct seq_file *f, loff_t *pos) |
b03dfdec0 locks: add __acqu... |
2619 |
__acquires(&blocked_lock_lock) |
7f8ada98d Rework /proc/lock... |
2620 |
{ |
7012b02a2 locks: move file_... |
2621 |
struct locks_iterator *iter = f->private; |
99dc82925 procfs: fix numbe... |
2622 |
|
7012b02a2 locks: move file_... |
2623 |
iter->li_pos = *pos + 1; |
aba376607 fs/locks: Replace... |
2624 |
percpu_down_write(&file_rwsem); |
7b2296afb locks: give the b... |
2625 |
spin_lock(&blocked_lock_lock); |
7c3f654d8 fs/locks: Replace... |
2626 |
return seq_hlist_start_percpu(&file_lock_list.hlist, &iter->li_cpu, *pos); |
7f8ada98d Rework /proc/lock... |
2627 |
} |
1da177e4c Linux-2.6.12-rc2 |
2628 |
|
7f8ada98d Rework /proc/lock... |
2629 2630 |
static void *locks_next(struct seq_file *f, void *v, loff_t *pos) { |
7012b02a2 locks: move file_... |
2631 2632 2633 |
struct locks_iterator *iter = f->private; ++iter->li_pos; |
7c3f654d8 fs/locks: Replace... |
2634 |
return seq_hlist_next_percpu(v, &file_lock_list.hlist, &iter->li_cpu, pos); |
7f8ada98d Rework /proc/lock... |
2635 |
} |
1da177e4c Linux-2.6.12-rc2 |
2636 |
|
7f8ada98d Rework /proc/lock... |
2637 |
static void locks_stop(struct seq_file *f, void *v) |
b03dfdec0 locks: add __acqu... |
2638 |
__releases(&blocked_lock_lock) |
7f8ada98d Rework /proc/lock... |
2639 |
{ |
7b2296afb locks: give the b... |
2640 |
spin_unlock(&blocked_lock_lock); |
aba376607 fs/locks: Replace... |
2641 |
percpu_up_write(&file_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
2642 |
} |
d8ba7a363 proc: move rest o... |
2643 |
static const struct seq_operations locks_seq_operations = { |
7f8ada98d Rework /proc/lock... |
2644 2645 2646 2647 2648 |
.start = locks_start, .next = locks_next, .stop = locks_stop, .show = locks_show, }; |
d8ba7a363 proc: move rest o... |
2649 |
|
d8ba7a363 proc: move rest o... |
2650 2651 |
static int __init proc_locks_init(void) { |
44414d82c proc: introduce p... |
2652 2653 |
proc_create_seq_private("locks", 0, NULL, &locks_seq_operations, sizeof(struct locks_iterator), NULL); |
d8ba7a363 proc: move rest o... |
2654 2655 |
return 0; } |
918992267 fs: make locks.c ... |
2656 |
fs_initcall(proc_locks_init); |
7f8ada98d Rework /proc/lock... |
2657 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
2658 2659 |
static int __init filelock_init(void) { |
7012b02a2 locks: move file_... |
2660 |
int i; |
4a075e39c locks: add a new ... |
2661 2662 |
flctx_cache = kmem_cache_create("file_lock_ctx", sizeof(struct file_lock_context), 0, SLAB_PANIC, NULL); |
1da177e4c Linux-2.6.12-rc2 |
2663 |
filelock_cache = kmem_cache_create("file_lock_cache", |
ee19cc406 fs: locks: remove... |
2664 |
sizeof(struct file_lock), 0, SLAB_PANIC, NULL); |
7012b02a2 locks: move file_... |
2665 |
|
7c3f654d8 fs/locks: Replace... |
2666 2667 2668 2669 2670 2671 |
for_each_possible_cpu(i) { struct file_lock_list_struct *fll = per_cpu_ptr(&file_lock_list, i); spin_lock_init(&fll->lock); INIT_HLIST_HEAD(&fll->hlist); } |
7012b02a2 locks: move file_... |
2672 |
|
1da177e4c Linux-2.6.12-rc2 |
2673 2674 2675 2676 |
return 0; } core_initcall(filelock_init); |