Blame view

fs/locks.c 79.9 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   *  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
7bbd1fc0e   NeilBrown   fs/locks: remove ...
15
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
   *  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
7bbd1fc0e   NeilBrown   fs/locks: remove ...
19
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
   *  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
7bbd1fc0e   NeilBrown   fs/locks: remove ...
45
   *  unlocked).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
   *
   *  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
7bbd1fc0e   NeilBrown   fs/locks: remove ...
54
   *  races. Just grep for FIXME to see them.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
60
61
62
63
   *  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.
a02dcdf65   Mauro Carvalho Chehab   docs: filesystems...
64
   *  See 'Documentation/filesystems/mandatory-locking.rst' for details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
   *  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.
fd7732e03   NeilBrown   fs/locks: create ...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
   *
   * Locking conflicts and dependencies:
   * If multiple threads attempt to lock the same byte (or flock the same file)
   * only one can be granted the lock, and other must wait their turn.
   * The first lock has been "applied" or "granted", the others are "waiting"
   * and are "blocked" by the "applied" lock..
   *
   * Waiting and applied locks are all kept in trees whose properties are:
   *
   *	- the root of a tree may be an applied or waiting lock.
   *	- every other node in the tree is a waiting lock that
   *	  conflicts with every ancestor of that node.
   *
   * Every such tree begins life as a waiting singleton which obviously
   * satisfies the above properties.
   *
   * The only ways we modify trees preserve these properties:
   *
   *	1. We may add a new leaf node, but only after first verifying that it
   *	   conflicts with all of its ancestors.
   *	2. We may remove the root of a tree, creating a new singleton
   *	   tree from the root and N new trees rooted in the immediate
   *	   children.
   *	3. If the root of a tree is not currently an applied lock, we may
   *	   apply it (if possible).
   *	4. We may upgrade the root of the tree (either extend its range,
   *	   or upgrade its entire range from read to write).
   *
   * When an applied lock is modified in a way that reduces or downgrades any
   * part of its range, we remove all its children (2 above).  This particularly
   * happens when a lock is unlocked.
   *
   * For each of those child trees we "wake up" the thread which is
   * waiting for the lock so it can continue handling as follows: if the
   * root of the tree applies, we do so (3).  If it doesn't, it must
   * conflict with some applied lock.  We remove (wake up) all of its children
   * (2), and add it is a new leaf to the tree rooted in the applied
   * lock (1).  We then repeat the process recursively with those
   * children.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
   */
  
  #include <linux/capability.h>
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
160
  #include <linux/fdtable.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
  #include <linux/fs.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  #include <linux/security.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
  #include <linux/syscalls.h>
  #include <linux/time.h>
4fb3a5386   Dipankar Sarma   [PATCH] files: fi...
167
  #include <linux/rcupdate.h>
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
168
  #include <linux/pid_namespace.h>
48f741865   Jeff Layton   locks: turn the b...
169
  #include <linux/hashtable.h>
7012b02a2   Jeff Layton   locks: move file_...
170
  #include <linux/percpu.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171

62af4f1f7   Jeff Layton   locks: add some t...
172
173
  #define CREATE_TRACE_POINTS
  #include <trace/events/filelock.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
174
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  
  #define IS_POSIX(fl)	(fl->fl_flags & FL_POSIX)
  #define IS_FLOCK(fl)	(fl->fl_flags & FL_FLOCK)
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
178
  #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
cff2fce58   Jeff Layton   locks: rename FL_...
179
  #define IS_OFDLCK(fl)	(fl->fl_flags & FL_OFDLCK)
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
180
  #define IS_REMOTELCK(fl)	(fl->fl_pid <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181

ab83fa4b4   J. Bruce Fields   locks: minor leas...
182
183
  static bool lease_breaking(struct file_lock *fl)
  {
778fc546f   J. Bruce Fields   locks: fix tracki...
184
185
186
187
188
189
190
191
192
193
  	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   J. Bruce Fields   locks: minor leas...
194
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  int leases_enable = 1;
  int lease_break_time = 45;
1c8c601a8   Jeff Layton   locks: protect mo...
197
  /*
7012b02a2   Jeff Layton   locks: move file_...
198
   * The global file_lock_list is only used for displaying /proc/locks, so we
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
199
200
201
202
203
   * 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   Jeff Layton   locks: protect mo...
204
   */
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
205
206
207
208
209
  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   Peter Zijlstra   fs/locks: Replace...
210
  DEFINE_STATIC_PERCPU_RWSEM(file_rwsem);
889746917   Jeff Layton   locks: encapsulat...
211

eb82dd393   Jeff Layton   nfsd: convert fi_...
212

1c8c601a8   Jeff Layton   locks: protect mo...
213
  /*
48f741865   Jeff Layton   locks: turn the b...
214
   * The blocked_hash is used to find POSIX lock loops for deadlock detection.
7b2296afb   Jeff Layton   locks: give the b...
215
   * It is protected by blocked_lock_lock.
48f741865   Jeff Layton   locks: turn the b...
216
217
218
219
220
221
222
   *
   * 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   Jeff Layton   locks: protect mo...
223
   */
48f741865   Jeff Layton   locks: turn the b...
224
225
  #define BLOCKED_HASH_BITS	7
  static DEFINE_HASHTABLE(blocked_hash, BLOCKED_HASH_BITS);
889746917   Jeff Layton   locks: encapsulat...
226

1c8c601a8   Jeff Layton   locks: protect mo...
227
  /*
7b2296afb   Jeff Layton   locks: give the b...
228
229
   * This lock protects the blocked_hash. Generally, if you're accessing it, you
   * want to be holding this lock.
1c8c601a8   Jeff Layton   locks: protect mo...
230
   *
ada5c1da8   NeilBrown   fs/locks: rename ...
231
232
233
   * In addition, it also protects the fl->fl_blocked_requests list, and the
   * fl->fl_blocker pointer for file_lock structures that are acting as lock
   * requests (in contrast to those that are acting as records of acquired locks).
1c8c601a8   Jeff Layton   locks: protect mo...
234
235
   *
   * Note that when we acquire this lock in order to change the above fields,
6109c8503   Jeff Layton   locks: add a dedi...
236
   * we often hold the flc_lock as well. In certain cases, when reading the fields
1c8c601a8   Jeff Layton   locks: protect mo...
237
   * protected by this lock, we can skip acquiring it iff we already hold the
6109c8503   Jeff Layton   locks: add a dedi...
238
   * flc_lock.
1c8c601a8   Jeff Layton   locks: protect mo...
239
   */
7b2296afb   Jeff Layton   locks: give the b...
240
  static DEFINE_SPINLOCK(blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

4a075e39c   Jeff Layton   locks: add a new ...
242
  static struct kmem_cache *flctx_cache __read_mostly;
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
243
  static struct kmem_cache *filelock_cache __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

4a075e39c   Jeff Layton   locks: add a new ...
245
  static struct file_lock_context *
5c1c669a1   Jeff Layton   locks: don't allo...
246
  locks_get_lock_context(struct inode *inode, int type)
4a075e39c   Jeff Layton   locks: add a new ...
247
  {
128a37852   Dmitry Vyukov   fs: fix data race...
248
  	struct file_lock_context *ctx;
4a075e39c   Jeff Layton   locks: add a new ...
249

128a37852   Dmitry Vyukov   fs: fix data race...
250
251
252
  	/* paired with cmpxchg() below */
  	ctx = smp_load_acquire(&inode->i_flctx);
  	if (likely(ctx) || type == F_UNLCK)
4a075e39c   Jeff Layton   locks: add a new ...
253
  		goto out;
128a37852   Dmitry Vyukov   fs: fix data race...
254
255
  	ctx = kmem_cache_alloc(flctx_cache, GFP_KERNEL);
  	if (!ctx)
4a075e39c   Jeff Layton   locks: add a new ...
256
  		goto out;
128a37852   Dmitry Vyukov   fs: fix data race...
257
258
259
260
  	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   Jeff Layton   locks: add a new ...
261
262
263
264
265
  
  	/*
  	 * Assign the pointer if it's not already assigned. If it is, then
  	 * free the context we just allocated.
  	 */
128a37852   Dmitry Vyukov   fs: fix data race...
266
267
268
269
  	if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
  		kmem_cache_free(flctx_cache, ctx);
  		ctx = smp_load_acquire(&inode->i_flctx);
  	}
4a075e39c   Jeff Layton   locks: add a new ...
270
  out:
1890910fd   Jeff Layton   locks: sprinkle s...
271
  	trace_locks_get_lock_context(inode, type, ctx);
128a37852   Dmitry Vyukov   fs: fix data race...
272
  	return ctx;
4a075e39c   Jeff Layton   locks: add a new ...
273
  }
e24dadab0   Jeff Layton   locks: prink more...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  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   Benjamin Coddington   locks: restore a ...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  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   Jeff Layton   locks: add a new ...
318
  void
f27a0fe08   Jeff Layton   locks: pass inode...
319
  locks_free_lock_context(struct inode *inode)
4a075e39c   Jeff Layton   locks: add a new ...
320
  {
f27a0fe08   Jeff Layton   locks: pass inode...
321
  	struct file_lock_context *ctx = inode->i_flctx;
e24dadab0   Jeff Layton   locks: prink more...
322
323
  	if (unlikely(ctx)) {
  		locks_check_ctx_lists(inode);
4a075e39c   Jeff Layton   locks: add a new ...
324
325
326
  		kmem_cache_free(flctx_cache, ctx);
  	}
  }
ee19cc406   Miklos Szeredi   fs: locks: remove...
327
  static void locks_init_lock_heads(struct file_lock *fl)
a51cb91d8   Miklos Szeredi   fs: fix lock init...
328
  {
139ca04ee   Jeff Layton   locks: convert fl...
329
  	INIT_HLIST_NODE(&fl->fl_link);
6dee60f69   Jeff Layton   locks: add new st...
330
  	INIT_LIST_HEAD(&fl->fl_list);
ada5c1da8   NeilBrown   fs/locks: rename ...
331
332
  	INIT_LIST_HEAD(&fl->fl_blocked_requests);
  	INIT_LIST_HEAD(&fl->fl_blocked_member);
ee19cc406   Miklos Szeredi   fs: locks: remove...
333
  	init_waitqueue_head(&fl->fl_wait);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
334
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  /* Allocate an empty lock structure. */
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
336
  struct file_lock *locks_alloc_lock(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  {
ee19cc406   Miklos Szeredi   fs: locks: remove...
338
  	struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
339
340
  
  	if (fl)
ee19cc406   Miklos Szeredi   fs: locks: remove...
341
  		locks_init_lock_heads(fl);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
342
343
  
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  }
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
345
  EXPORT_SYMBOL_GPL(locks_alloc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

a9e61e25f   Felix Blyakher   lockd: call locks...
347
  void locks_release_private(struct file_lock *fl)
47831f35b   Trond Myklebust   VFS: Fix __posix_...
348
  {
5926459e7   NeilBrown   locks: move check...
349
350
351
352
353
  	BUG_ON(waitqueue_active(&fl->fl_wait));
  	BUG_ON(!list_empty(&fl->fl_list));
  	BUG_ON(!list_empty(&fl->fl_blocked_requests));
  	BUG_ON(!list_empty(&fl->fl_blocked_member));
  	BUG_ON(!hlist_unhashed(&fl->fl_link));
47831f35b   Trond Myklebust   VFS: Fix __posix_...
354
355
356
357
358
  	if (fl->fl_ops) {
  		if (fl->fl_ops->fl_release_private)
  			fl->fl_ops->fl_release_private(fl);
  		fl->fl_ops = NULL;
  	}
47831f35b   Trond Myklebust   VFS: Fix __posix_...
359

5c97d7b14   Kinglong Mee   locks: New ops in...
360
  	if (fl->fl_lmops) {
cae80b305   Jeff Layton   locks: change lm_...
361
362
363
364
  		if (fl->fl_lmops->lm_put_owner) {
  			fl->fl_lmops->lm_put_owner(fl->fl_owner);
  			fl->fl_owner = NULL;
  		}
5c97d7b14   Kinglong Mee   locks: New ops in...
365
366
  		fl->fl_lmops = NULL;
  	}
47831f35b   Trond Myklebust   VFS: Fix __posix_...
367
  }
a9e61e25f   Felix Blyakher   lockd: call locks...
368
  EXPORT_SYMBOL_GPL(locks_release_private);
47831f35b   Trond Myklebust   VFS: Fix __posix_...
369

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  /* Free a lock which is not in use. */
05fa3135f   J. Bruce Fields   locks: fix setlea...
371
  void locks_free_lock(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
  {
47831f35b   Trond Myklebust   VFS: Fix __posix_...
373
  	locks_release_private(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
  	kmem_cache_free(filelock_cache, fl);
  }
05fa3135f   J. Bruce Fields   locks: fix setlea...
376
  EXPORT_SYMBOL(locks_free_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377

ed9814d85   Jeff Layton   locks: defer free...
378
379
380
381
382
383
  static void
  locks_dispose_list(struct list_head *dispose)
  {
  	struct file_lock *fl;
  
  	while (!list_empty(dispose)) {
6dee60f69   Jeff Layton   locks: add new st...
384
385
  		fl = list_first_entry(dispose, struct file_lock, fl_list);
  		list_del_init(&fl->fl_list);
ed9814d85   Jeff Layton   locks: defer free...
386
387
388
  		locks_free_lock(fl);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
  void locks_init_lock(struct file_lock *fl)
  {
ee19cc406   Miklos Szeredi   fs: locks: remove...
391
392
  	memset(fl, 0, sizeof(struct file_lock));
  	locks_init_lock_heads(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  EXPORT_SYMBOL(locks_init_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
  /*
   * Initialize a new lock from an existing file_lock structure.
   */
3fe0fff18   Kinglong Mee   locks: Rename __l...
398
  void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  {
  	new->fl_owner = fl->fl_owner;
  	new->fl_pid = fl->fl_pid;
0996905f9   Trond Myklebust   lockd: posix_test...
402
  	new->fl_file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
  	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   Kinglong Mee   locks: Copy fl_lm...
407
  	new->fl_lmops = fl->fl_lmops;
0996905f9   Trond Myklebust   lockd: posix_test...
408
  	new->fl_ops = NULL;
f328296e2   Kinglong Mee   locks: Copy fl_lm...
409
410
411
  
  	if (fl->fl_lmops) {
  		if (fl->fl_lmops->lm_get_owner)
cae80b305   Jeff Layton   locks: change lm_...
412
  			fl->fl_lmops->lm_get_owner(fl->fl_owner);
f328296e2   Kinglong Mee   locks: Copy fl_lm...
413
  	}
0996905f9   Trond Myklebust   lockd: posix_test...
414
  }
3fe0fff18   Kinglong Mee   locks: Rename __l...
415
  EXPORT_SYMBOL(locks_copy_conflock);
0996905f9   Trond Myklebust   lockd: posix_test...
416
417
418
  
  void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
  {
566709bd6   Jeff Layton   locks: don't call...
419
420
  	/* "new" must be a freshly-initialized lock */
  	WARN_ON_ONCE(new->fl_ops);
0996905f9   Trond Myklebust   lockd: posix_test...
421

3fe0fff18   Kinglong Mee   locks: Rename __l...
422
  	locks_copy_conflock(new, fl);
f328296e2   Kinglong Mee   locks: Copy fl_lm...
423

0996905f9   Trond Myklebust   lockd: posix_test...
424
  	new->fl_file = fl->fl_file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  	new->fl_ops = fl->fl_ops;
47831f35b   Trond Myklebust   VFS: Fix __posix_...
426

f328296e2   Kinglong Mee   locks: Copy fl_lm...
427
428
429
430
  	if (fl->fl_ops) {
  		if (fl->fl_ops->fl_copy_lock)
  			fl->fl_ops->fl_copy_lock(new, fl);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  EXPORT_SYMBOL(locks_copy_lock);
5946c4319   NeilBrown   fs/locks: allow a...
433
434
435
436
437
438
439
440
441
442
443
444
445
  static void locks_move_blocks(struct file_lock *new, struct file_lock *fl)
  {
  	struct file_lock *f;
  
  	/*
  	 * As ctx->flc_lock is held, new requests cannot be added to
  	 * ->fl_blocked_requests, so we don't need a lock to check if it
  	 * is empty.
  	 */
  	if (list_empty(&fl->fl_blocked_requests))
  		return;
  	spin_lock(&blocked_lock_lock);
  	list_splice_init(&fl->fl_blocked_requests, &new->fl_blocked_requests);
bf77ae4c9   NeilBrown   locks: fix error ...
446
  	list_for_each_entry(f, &new->fl_blocked_requests, fl_blocked_member)
5946c4319   NeilBrown   fs/locks: allow a...
447
448
449
  		f->fl_blocker = new;
  	spin_unlock(&blocked_lock_lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  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   Jeff Layton   locks: flock_make...
465
  static struct file_lock *
d6367d624   NeilBrown   fs/locks: use pro...
466
  flock_make_lock(struct file *filp, unsigned int cmd, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  	int type = flock_translate_cmd(cmd);
6e129d006   Jeff Layton   locks: flock_make...
469

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  	if (type < 0)
6e129d006   Jeff Layton   locks: flock_make...
471
  		return ERR_PTR(type);
7bbd1fc0e   NeilBrown   fs/locks: remove ...
472

d6367d624   NeilBrown   fs/locks: use pro...
473
474
475
476
477
478
479
  	if (fl == NULL) {
  		fl = locks_alloc_lock();
  		if (fl == NULL)
  			return ERR_PTR(-ENOMEM);
  	} else {
  		locks_init_lock(fl);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  
  	fl->fl_file = filp;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
482
  	fl->fl_owner = filp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
  	fl->fl_pid = current->tgid;
  	fl->fl_flags = FL_FLOCK;
  	fl->fl_type = type;
  	fl->fl_end = OFFSET_MAX;
7bbd1fc0e   NeilBrown   fs/locks: remove ...
487

6e129d006   Jeff Layton   locks: flock_make...
488
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  }
0ec4f431e   J. Bruce Fields   locks: fix checki...
490
  static int assign_type(struct file_lock *fl, long type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
497
498
499
500
501
502
  {
  	switch (type) {
  	case F_RDLCK:
  	case F_WRLCK:
  	case F_UNLCK:
  		fl->fl_type = type;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
ef12e72a0   J. Bruce Fields   locks: fix posix ...
503
504
  static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
  				 struct flock64 *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  	switch (l->l_whence) {
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
507
  	case SEEK_SET:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
508
  		fl->fl_start = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  		break;
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
510
  	case SEEK_CUR:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
511
  		fl->fl_start = filp->f_pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  		break;
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
513
  	case SEEK_END:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
514
  		fl->fl_start = i_size_read(file_inode(filp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
  		break;
  	default:
  		return -EINVAL;
  	}
ef12e72a0   J. Bruce Fields   locks: fix posix ...
519
520
521
522
523
  	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   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
  
  	/* POSIX-1996 leaves the case l->l_len < 0 undefined;
  	   POSIX-2001 defines it. */
4c780a468   Trond Myklebust   Fix Connectathon ...
527
  	if (l->l_len > 0) {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
528
529
530
  		if (l->l_len - 1 > OFFSET_MAX - fl->fl_start)
  			return -EOVERFLOW;
  		fl->fl_end = fl->fl_start + l->l_len - 1;
4c780a468   Trond Myklebust   Fix Connectathon ...
531
  	} else if (l->l_len < 0) {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
532
  		if (fl->fl_start + l->l_len < 0)
4c780a468   Trond Myklebust   Fix Connectathon ...
533
  			return -EINVAL;
ef12e72a0   J. Bruce Fields   locks: fix posix ...
534
535
536
537
  		fl->fl_end = fl->fl_start - 1;
  		fl->fl_start += l->l_len;
  	} else
  		fl->fl_end = OFFSET_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
540
541
542
543
544
545
546
  	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   J. Bruce Fields   locks: fix posix ...
547
548
549
550
551
  /* 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   Linus Torvalds   Linux-2.6.12-rc2
552
  {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
553
554
555
556
557
558
559
560
  	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   Linus Torvalds   Linux-2.6.12-rc2
561
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  
  /* default lease lock manager operations */
4d01b7f5e   Jeff Layton   locks: give lm_br...
564
565
  static bool
  lease_break_callback(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
  {
  	kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
4d01b7f5e   Jeff Layton   locks: give lm_br...
568
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  }
1c7dd2ff4   Jeff Layton   locks: define a l...
570
571
572
573
574
575
576
577
578
579
580
581
582
  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   Eric W. Biederman   signal: Use PIDTY...
583
  	__f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
1c7dd2ff4   Jeff Layton   locks: define a l...
584
  }
7b021967c   Alexey Dobriyan   const: make lock_...
585
  static const struct lock_manager_operations lease_manager_ops = {
8fb47a4fb   J. Bruce Fields   locks: rename loc...
586
  	.lm_break = lease_break_callback,
8fb47a4fb   J. Bruce Fields   locks: rename loc...
587
  	.lm_change = lease_modify,
1c7dd2ff4   Jeff Layton   locks: define a l...
588
  	.lm_setup = lease_setup,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
592
593
  };
  
  /*
   * Initialize a lease, use the default lock manager operations
   */
0ec4f431e   J. Bruce Fields   locks: fix checki...
594
  static int lease_init(struct file *filp, long type, struct file_lock *fl)
447a5647c   Joe Perches   treewide: Align f...
595
  {
75dff55af   Trond Myklebust   [PATCH] fs/locks....
596
597
  	if (assign_type(fl, type) != 0)
  		return -EINVAL;
7ca76311f   Jeff Layton   locks: set fl_own...
598
  	fl->fl_owner = filp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
602
  	fl->fl_pid = current->tgid;
  
  	fl->fl_file = filp;
  	fl->fl_flags = FL_LEASE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
609
610
  	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   J. Bruce Fields   locks: fix checki...
611
  static struct file_lock *lease_alloc(struct file *filp, long type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  {
  	struct file_lock *fl = locks_alloc_lock();
75dff55af   Trond Myklebust   [PATCH] fs/locks....
614
  	int error = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
  
  	if (fl == NULL)
e32b8ee27   J. Bruce Fields   locks: clean up l...
617
  		return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
  
  	error = lease_init(filp, type, fl);
75dff55af   Trond Myklebust   [PATCH] fs/locks....
620
621
  	if (error) {
  		locks_free_lock(fl);
e32b8ee27   J. Bruce Fields   locks: clean up l...
622
  		return ERR_PTR(error);
75dff55af   Trond Myklebust   [PATCH] fs/locks....
623
  	}
e32b8ee27   J. Bruce Fields   locks: clean up l...
624
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
628
629
630
631
632
633
634
635
636
637
  }
  
  /* 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   Matt Mackall   [PATCH] tiny: Uni...
638
  static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
  	return fl1->fl_owner == fl2->fl_owner;
  }
6109c8503   Jeff Layton   locks: add a dedi...
642
  /* Must be called with the flc_lock held! */
6ca10ed8e   Jeff Layton   locks: remove "in...
643
  static void locks_insert_global_locks(struct file_lock *fl)
889746917   Jeff Layton   locks: encapsulat...
644
  {
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
645
  	struct file_lock_list_struct *fll = this_cpu_ptr(&file_lock_list);
aba376607   Peter Zijlstra   fs/locks: Replace...
646
  	percpu_rwsem_assert_held(&file_rwsem);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
647
  	spin_lock(&fll->lock);
7012b02a2   Jeff Layton   locks: move file_...
648
  	fl->fl_link_cpu = smp_processor_id();
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
649
650
  	hlist_add_head(&fl->fl_link, &fll->hlist);
  	spin_unlock(&fll->lock);
889746917   Jeff Layton   locks: encapsulat...
651
  }
6109c8503   Jeff Layton   locks: add a dedi...
652
  /* Must be called with the flc_lock held! */
6ca10ed8e   Jeff Layton   locks: remove "in...
653
  static void locks_delete_global_locks(struct file_lock *fl)
889746917   Jeff Layton   locks: encapsulat...
654
  {
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
655
  	struct file_lock_list_struct *fll;
aba376607   Peter Zijlstra   fs/locks: Replace...
656
  	percpu_rwsem_assert_held(&file_rwsem);
7012b02a2   Jeff Layton   locks: move file_...
657
658
  	/*
  	 * Avoid taking lock if already unhashed. This is safe since this check
6109c8503   Jeff Layton   locks: add a dedi...
659
  	 * is done while holding the flc_lock, and new insertions into the list
7012b02a2   Jeff Layton   locks: move file_...
660
661
662
663
  	 * also require that it be held.
  	 */
  	if (hlist_unhashed(&fl->fl_link))
  		return;
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
664
665
666
  
  	fll = per_cpu_ptr(&file_lock_list, fl->fl_link_cpu);
  	spin_lock(&fll->lock);
139ca04ee   Jeff Layton   locks: convert fl...
667
  	hlist_del_init(&fl->fl_link);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
668
  	spin_unlock(&fll->lock);
889746917   Jeff Layton   locks: encapsulat...
669
  }
3999e4936   Jeff Layton   locks: add a new ...
670
671
672
  static unsigned long
  posix_owner_key(struct file_lock *fl)
  {
3999e4936   Jeff Layton   locks: add a new ...
673
674
  	return (unsigned long)fl->fl_owner;
  }
6ca10ed8e   Jeff Layton   locks: remove "in...
675
  static void locks_insert_global_blocked(struct file_lock *waiter)
889746917   Jeff Layton   locks: encapsulat...
676
  {
663d5af75   Daniel Wagner   locks: Add lockde...
677
  	lockdep_assert_held(&blocked_lock_lock);
3999e4936   Jeff Layton   locks: add a new ...
678
  	hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter));
889746917   Jeff Layton   locks: encapsulat...
679
  }
6ca10ed8e   Jeff Layton   locks: remove "in...
680
  static void locks_delete_global_blocked(struct file_lock *waiter)
889746917   Jeff Layton   locks: encapsulat...
681
  {
663d5af75   Daniel Wagner   locks: Add lockde...
682
  	lockdep_assert_held(&blocked_lock_lock);
48f741865   Jeff Layton   locks: turn the b...
683
  	hash_del(&waiter->fl_link);
889746917   Jeff Layton   locks: encapsulat...
684
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
  /* Remove waiter from blocker's block list.
   * When blocker ends up pointing to itself then the list is empty.
1c8c601a8   Jeff Layton   locks: protect mo...
687
   *
7b2296afb   Jeff Layton   locks: give the b...
688
   * Must be called with blocked_lock_lock held.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
   */
33443c42f   Matt Mackall   [PATCH] tiny: Uni...
690
  static void __locks_delete_block(struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  {
889746917   Jeff Layton   locks: encapsulat...
692
  	locks_delete_global_blocked(waiter);
ada5c1da8   NeilBrown   fs/locks: rename ...
693
  	list_del_init(&waiter->fl_blocked_member);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  }
ad6bbd8b1   NeilBrown   fs/locks: split o...
695
696
697
698
699
700
701
702
703
704
705
706
  static void __locks_wake_up_blocks(struct file_lock *blocker)
  {
  	while (!list_empty(&blocker->fl_blocked_requests)) {
  		struct file_lock *waiter;
  
  		waiter = list_first_entry(&blocker->fl_blocked_requests,
  					  struct file_lock, fl_blocked_member);
  		__locks_delete_block(waiter);
  		if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
  			waiter->fl_lmops->lm_notify(waiter);
  		else
  			wake_up(&waiter->fl_wait);
dcf23ac3e   Linus Torvalds   locks: reinstate ...
707
708
709
710
711
712
713
  
  		/*
  		 * The setting of fl_blocker to NULL marks the "done"
  		 * point in deleting a block. Paired with acquire at the top
  		 * of locks_delete_block().
  		 */
  		smp_store_release(&waiter->fl_blocker, NULL);
ad6bbd8b1   NeilBrown   fs/locks: split o...
714
715
  	}
  }
cb03f94ff   NeilBrown   fs/locks: merge p...
716
717
718
719
720
721
722
  /**
   *	locks_delete_lock - stop waiting for a file lock
   *	@waiter: the lock which was waiting
   *
   *	lockd/nfsd need to disconnect the lock while working on it.
   */
  int locks_delete_block(struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
  {
cb03f94ff   NeilBrown   fs/locks: merge p...
724
  	int status = -ENOENT;
dcf23ac3e   Linus Torvalds   locks: reinstate ...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  	/*
  	 * If fl_blocker is NULL, it won't be set again as this thread "owns"
  	 * the lock and is the only one that might try to claim the lock.
  	 *
  	 * We use acquire/release to manage fl_blocker so that we can
  	 * optimize away taking the blocked_lock_lock in many cases.
  	 *
  	 * The smp_load_acquire guarantees two things:
  	 *
  	 * 1/ that fl_blocked_requests can be tested locklessly. If something
  	 * was recently added to that list it must have been in a locked region
  	 * *before* the locked region when fl_blocker was set to NULL.
  	 *
  	 * 2/ that no other thread is accessing 'waiter', so it is safe to free
  	 * it.  __locks_wake_up_blocks is careful not to touch waiter after
  	 * fl_blocker is released.
  	 *
  	 * If a lockless check of fl_blocker shows it to be NULL, we know that
  	 * no new locks can be inserted into its fl_blocked_requests list, and
  	 * can avoid doing anything further if the list is empty.
  	 */
  	if (!smp_load_acquire(&waiter->fl_blocker) &&
  	    list_empty(&waiter->fl_blocked_requests))
  		return status;
7b2296afb   Jeff Layton   locks: give the b...
749
  	spin_lock(&blocked_lock_lock);
cb03f94ff   NeilBrown   fs/locks: merge p...
750
751
  	if (waiter->fl_blocker)
  		status = 0;
5946c4319   NeilBrown   fs/locks: allow a...
752
  	__locks_wake_up_blocks(waiter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  	__locks_delete_block(waiter);
dcf23ac3e   Linus Torvalds   locks: reinstate ...
754
755
756
757
758
759
  
  	/*
  	 * The setting of fl_blocker to NULL marks the "done" point in deleting
  	 * a block. Paired with acquire at the top of this function.
  	 */
  	smp_store_release(&waiter->fl_blocker, NULL);
7b2296afb   Jeff Layton   locks: give the b...
760
  	spin_unlock(&blocked_lock_lock);
cb03f94ff   NeilBrown   fs/locks: merge p...
761
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  }
cb03f94ff   NeilBrown   fs/locks: merge p...
763
  EXPORT_SYMBOL(locks_delete_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
  
  /* 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   Jeff Layton   locks: protect mo...
769
   *
6109c8503   Jeff Layton   locks: add a dedi...
770
   * Must be called with both the flc_lock and blocked_lock_lock held. The
ada5c1da8   NeilBrown   fs/locks: rename ...
771
772
773
774
   * fl_blocked_requests 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_blocked_requests list is empty.
fd7732e03   NeilBrown   fs/locks: create ...
775
776
777
778
   *
   * Rather than just adding to the list, we check for conflicts with any existing
   * waiters, and add beneath any waiter that blocks the new waiter.
   * Thus wakeups don't happen until needed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
   */
1c8c601a8   Jeff Layton   locks: protect mo...
780
  static void __locks_insert_block(struct file_lock *blocker,
fd7732e03   NeilBrown   fs/locks: create ...
781
782
783
  				 struct file_lock *waiter,
  				 bool conflict(struct file_lock *,
  					       struct file_lock *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  {
fd7732e03   NeilBrown   fs/locks: create ...
785
  	struct file_lock *fl;
ada5c1da8   NeilBrown   fs/locks: rename ...
786
  	BUG_ON(!list_empty(&waiter->fl_blocked_member));
fd7732e03   NeilBrown   fs/locks: create ...
787
788
789
790
791
792
793
  
  new_blocker:
  	list_for_each_entry(fl, &blocker->fl_blocked_requests, fl_blocked_member)
  		if (conflict(fl, waiter)) {
  			blocker =  fl;
  			goto new_blocker;
  		}
ada5c1da8   NeilBrown   fs/locks: rename ...
794
795
  	waiter->fl_blocker = blocker;
  	list_add_tail(&waiter->fl_blocked_member, &blocker->fl_blocked_requests);
cff2fce58   Jeff Layton   locks: rename FL_...
796
  	if (IS_POSIX(blocker) && !IS_OFDLCK(blocker))
1c8c601a8   Jeff Layton   locks: protect mo...
797
  		locks_insert_global_blocked(waiter);
5946c4319   NeilBrown   fs/locks: allow a...
798
799
800
801
802
803
  
  	/* The requests in waiter->fl_blocked are known to conflict with
  	 * waiter, but might not conflict with blocker, or the requests
  	 * and lock which block it.  So they all need to be woken.
  	 */
  	__locks_wake_up_blocks(waiter);
1c8c601a8   Jeff Layton   locks: protect mo...
804
  }
6109c8503   Jeff Layton   locks: add a dedi...
805
  /* Must be called with flc_lock held. */
1c8c601a8   Jeff Layton   locks: protect mo...
806
  static void locks_insert_block(struct file_lock *blocker,
fd7732e03   NeilBrown   fs/locks: create ...
807
808
809
  			       struct file_lock *waiter,
  			       bool conflict(struct file_lock *,
  					     struct file_lock *))
1c8c601a8   Jeff Layton   locks: protect mo...
810
  {
7b2296afb   Jeff Layton   locks: give the b...
811
  	spin_lock(&blocked_lock_lock);
fd7732e03   NeilBrown   fs/locks: create ...
812
  	__locks_insert_block(blocker, waiter, conflict);
7b2296afb   Jeff Layton   locks: give the b...
813
  	spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  }
1cb360125   Jeff Layton   locks: comment cl...
815
816
817
  /*
   * Wake up processes blocked waiting for blocker.
   *
6109c8503   Jeff Layton   locks: add a dedi...
818
   * Must be called with the inode->flc_lock held!
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
821
   */
  static void locks_wake_up_blocks(struct file_lock *blocker)
  {
4e8c765d3   Jeff Layton   locks: avoid taki...
822
823
  	/*
  	 * Avoid taking global lock if list is empty. This is safe since new
6109c8503   Jeff Layton   locks: add a dedi...
824
  	 * blocked requests are only added to the list under the flc_lock, and
ada5c1da8   NeilBrown   fs/locks: rename ...
825
826
827
  	 * the flc_lock is always held here. Note that removal from the
  	 * fl_blocked_requests list does not require the flc_lock, so we must
  	 * recheck list_empty() after acquiring the blocked_lock_lock.
4e8c765d3   Jeff Layton   locks: avoid taki...
828
  	 */
ada5c1da8   NeilBrown   fs/locks: rename ...
829
  	if (list_empty(&blocker->fl_blocked_requests))
4e8c765d3   Jeff Layton   locks: avoid taki...
830
  		return;
7b2296afb   Jeff Layton   locks: give the b...
831
  	spin_lock(&blocked_lock_lock);
ad6bbd8b1   NeilBrown   fs/locks: split o...
832
  	__locks_wake_up_blocks(blocker);
7b2296afb   Jeff Layton   locks: give the b...
833
  	spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  }
5263e31e4   Jeff Layton   locks: move flock...
835
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
836
  locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
5263e31e4   Jeff Layton   locks: move flock...
837
  {
5263e31e4   Jeff Layton   locks: move flock...
838
839
840
  	list_add_tail(&fl->fl_list, before);
  	locks_insert_global_locks(fl);
  }
8634b51f6   Jeff Layton   locks: convert le...
841
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
842
  locks_unlink_lock_ctx(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  {
889746917   Jeff Layton   locks: encapsulat...
844
  	locks_delete_global_locks(fl);
8634b51f6   Jeff Layton   locks: convert le...
845
  	list_del_init(&fl->fl_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  	locks_wake_up_blocks(fl);
24cbe7845   Jeff Layton   locks: close pote...
847
  }
8634b51f6   Jeff Layton   locks: convert le...
848
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
849
  locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
24cbe7845   Jeff Layton   locks: close pote...
850
  {
e084c1bd4   Jeff Layton   Revert "locks: ke...
851
  	locks_unlink_lock_ctx(fl);
ed9814d85   Jeff Layton   locks: defer free...
852
  	if (dispose)
6dee60f69   Jeff Layton   locks: add new st...
853
  		list_add(&fl->fl_list, dispose);
ed9814d85   Jeff Layton   locks: defer free...
854
855
  	else
  		locks_free_lock(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
860
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. Common functionality
   * checks for shared/exclusive status of overlapping locks.
   */
c0e159089   NeilBrown   fs/locks: change ...
861
862
  static bool locks_conflict(struct file_lock *caller_fl,
  			   struct file_lock *sys_fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
  {
  	if (sys_fl->fl_type == F_WRLCK)
c0e159089   NeilBrown   fs/locks: change ...
865
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  	if (caller_fl->fl_type == F_WRLCK)
c0e159089   NeilBrown   fs/locks: change ...
867
868
  		return true;
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
871
872
873
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific
   * checking before calling the locks_conflict().
   */
c0e159089   NeilBrown   fs/locks: change ...
874
875
  static bool posix_locks_conflict(struct file_lock *caller_fl,
  				 struct file_lock *sys_fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
878
879
  {
  	/* POSIX locks owned by the same process do not conflict with
  	 * each other.
  	 */
9b8c86956   Jeff Layton   locks: remove ext...
880
  	if (posix_same_owner(caller_fl, sys_fl))
c0e159089   NeilBrown   fs/locks: change ...
881
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
  
  	/* Check whether they overlap */
  	if (!locks_overlap(caller_fl, sys_fl))
c0e159089   NeilBrown   fs/locks: change ...
885
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886

c0e159089   NeilBrown   fs/locks: change ...
887
  	return locks_conflict(caller_fl, sys_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
891
892
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific
   * checking before calling the locks_conflict().
   */
c0e159089   NeilBrown   fs/locks: change ...
893
894
  static bool flock_locks_conflict(struct file_lock *caller_fl,
  				 struct file_lock *sys_fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
896
897
898
  {
  	/* FLOCK locks referring to the same filp do not conflict with
  	 * each other.
  	 */
9b8c86956   Jeff Layton   locks: remove ext...
899
  	if (caller_fl->fl_file == sys_fl->fl_file)
c0e159089   NeilBrown   fs/locks: change ...
900
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
  	if ((caller_fl->fl_type & LOCK_MAND) || (sys_fl->fl_type & LOCK_MAND))
c0e159089   NeilBrown   fs/locks: change ...
902
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

c0e159089   NeilBrown   fs/locks: change ...
904
  	return locks_conflict(caller_fl, sys_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  }
6d34ac199   J. Bruce Fields   locks: make posix...
906
  void
9d6a8c5c2   Marc Eshel   locks: give posix...
907
  posix_test_lock(struct file *filp, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
  {
  	struct file_lock *cfl;
bd61e0a9c   Jeff Layton   locks: convert po...
910
  	struct file_lock_context *ctx;
c568d6834   Miklos Szeredi   locks: fix file l...
911
  	struct inode *inode = locks_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912

128a37852   Dmitry Vyukov   fs: fix data race...
913
  	ctx = smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
914
915
916
917
  	if (!ctx || list_empty_careful(&ctx->flc_posix)) {
  		fl->fl_type = F_UNLCK;
  		return;
  	}
6109c8503   Jeff Layton   locks: add a dedi...
918
  	spin_lock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
919
920
921
  	list_for_each_entry(cfl, &ctx->flc_posix, fl_list) {
  		if (posix_locks_conflict(fl, cfl)) {
  			locks_copy_conflock(fl, cfl);
bd61e0a9c   Jeff Layton   locks: convert po...
922
923
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  	}
bd61e0a9c   Jeff Layton   locks: convert po...
925
926
  	fl->fl_type = F_UNLCK;
  out:
6109c8503   Jeff Layton   locks: add a dedi...
927
  	spin_unlock(&ctx->flc_lock);
6d34ac199   J. Bruce Fields   locks: make posix...
928
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  EXPORT_SYMBOL(posix_test_lock);
b533184fc   J. Bruce Fields   locks: clarify po...
931
932
933
934
935
  /*
   * Deadlock detection:
   *
   * We attempt to detect deadlocks that are due purely to posix file
   * locks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
   *
b533184fc   J. Bruce Fields   locks: clarify po...
937
938
939
940
941
942
943
   * 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   Linus Torvalds   Linux-2.6.12-rc2
944
   *
b533184fc   J. Bruce Fields   locks: clarify po...
945
946
947
   * 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   J. Bruce Fields   locks: fix possib...
948
   *
b533184fc   J. Bruce Fields   locks: clarify po...
949
950
951
   * 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   J. Bruce Fields   locks: clarify po...
952
   * To handle those cases, we just bail out after a few iterations.
57b65325f   Jeff Layton   locks: skip deadl...
953
   *
cff2fce58   Jeff Layton   locks: rename FL_...
954
   * For FL_OFDLCK locks, the owner is the filp, not the files_struct.
57b65325f   Jeff Layton   locks: skip deadl...
955
956
957
958
   * 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   Jeff Layton   locks: rename FL_...
959
   * In principle, we could do a more limited deadlock detection on FL_OFDLCK
57b65325f   Jeff Layton   locks: skip deadl...
960
961
   * locks that just checks for the case where two tasks are attempting to
   * upgrade from read to write locks on the same inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
   */
97855b49b   J. Bruce Fields   locks: fix possib...
963
964
  
  #define MAX_DEADLK_ITERATIONS 10
b533184fc   J. Bruce Fields   locks: clarify po...
965
966
967
968
  /* 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   Jeff Layton   locks: add a new ...
969
  	hash_for_each_possible(blocked_hash, fl, fl_link, posix_owner_key(block_fl)) {
5946c4319   NeilBrown   fs/locks: allow a...
970
971
972
973
974
  		if (posix_same_owner(fl, block_fl)) {
  			while (fl->fl_blocker)
  				fl = fl->fl_blocker;
  			return fl;
  		}
b533184fc   J. Bruce Fields   locks: clarify po...
975
976
977
  	}
  	return NULL;
  }
7b2296afb   Jeff Layton   locks: give the b...
978
  /* Must be called with the blocked_lock_lock held! */
b0904e147   Adrian Bunk   [PATCH] fs/locks....
979
  static int posix_locks_deadlock(struct file_lock *caller_fl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  				struct file_lock *block_fl)
  {
97855b49b   J. Bruce Fields   locks: fix possib...
982
  	int i = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983

663d5af75   Daniel Wagner   locks: Add lockde...
984
  	lockdep_assert_held(&blocked_lock_lock);
57b65325f   Jeff Layton   locks: skip deadl...
985
986
  	/*
  	 * This deadlock detector can't reasonably detect deadlocks with
cff2fce58   Jeff Layton   locks: rename FL_...
987
  	 * FL_OFDLCK locks, since they aren't owned by a process, per-se.
57b65325f   Jeff Layton   locks: skip deadl...
988
  	 */
cff2fce58   Jeff Layton   locks: rename FL_...
989
  	if (IS_OFDLCK(caller_fl))
57b65325f   Jeff Layton   locks: skip deadl...
990
  		return 0;
b533184fc   J. Bruce Fields   locks: clarify po...
991
992
993
994
995
  	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   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
  /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
02888f41e   J. Bruce Fields   locks: fix flock_...
1000
   * after any leases, but before any posix locks.
f475ae957   Trond Myklebust   VFS: Allow caller...
1001
1002
1003
1004
   *
   * 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   Linus Torvalds   Linux-2.6.12-rc2
1005
   */
bcd7f78d0   Jeff Layton   locks: have flock...
1006
  static int flock_lock_inode(struct inode *inode, struct file_lock *request)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
  {
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1008
  	struct file_lock *new_fl = NULL;
5263e31e4   Jeff Layton   locks: move flock...
1009
1010
  	struct file_lock *fl;
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
  	int error = 0;
5263e31e4   Jeff Layton   locks: move flock...
1012
  	bool found = false;
ed9814d85   Jeff Layton   locks: defer free...
1013
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014

5c1c669a1   Jeff Layton   locks: don't allo...
1015
1016
1017
1018
1019
1020
  	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   Jeff Layton   locks: move flock...
1021

b89f43213   Arnd Bergmann   fs/locks.c: prepa...
1022
  	if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
84d535ade   Pavel Emelyanov   Memory shortage c...
1023
  		new_fl = locks_alloc_lock();
b89f43213   Arnd Bergmann   fs/locks.c: prepa...
1024
1025
  		if (!new_fl)
  			return -ENOMEM;
84d535ade   Pavel Emelyanov   Memory shortage c...
1026
  	}
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1027
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1028
  	spin_lock(&ctx->flc_lock);
b89f43213   Arnd Bergmann   fs/locks.c: prepa...
1029
1030
  	if (request->fl_flags & FL_ACCESS)
  		goto find_conflict;
5263e31e4   Jeff Layton   locks: move flock...
1031
  	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
bcd7f78d0   Jeff Layton   locks: have flock...
1032
  		if (request->fl_file != fl->fl_file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
  			continue;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1034
  		if (request->fl_type == fl->fl_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  			goto out;
5263e31e4   Jeff Layton   locks: move flock...
1036
  		found = true;
e084c1bd4   Jeff Layton   Revert "locks: ke...
1037
  		locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
1039
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040

f475ae957   Trond Myklebust   VFS: Allow caller...
1041
1042
1043
  	if (request->fl_type == F_UNLCK) {
  		if ((request->fl_flags & FL_EXISTS) && !found)
  			error = -ENOENT;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1044
  		goto out;
f475ae957   Trond Myklebust   VFS: Allow caller...
1045
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046

f07f18dd6   Trond Myklebust   VFS: Add support ...
1047
  find_conflict:
5263e31e4   Jeff Layton   locks: move flock...
1048
  	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1049
  		if (!flock_locks_conflict(request, fl))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
  			continue;
  		error = -EAGAIN;
bde74e4bc   Miklos Szeredi   locks: add specia...
1052
1053
1054
  		if (!(request->fl_flags & FL_SLEEP))
  			goto out;
  		error = FILE_LOCK_DEFERRED;
fd7732e03   NeilBrown   fs/locks: create ...
1055
  		locks_insert_block(fl, request, flock_locks_conflict);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
  		goto out;
  	}
f07f18dd6   Trond Myklebust   VFS: Add support ...
1058
1059
  	if (request->fl_flags & FL_ACCESS)
  		goto out;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1060
  	locks_copy_lock(new_fl, request);
5946c4319   NeilBrown   fs/locks: allow a...
1061
  	locks_move_blocks(new_fl, request);
e084c1bd4   Jeff Layton   Revert "locks: ke...
1062
  	locks_insert_lock_ctx(new_fl, &ctx->flc_flock);
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1063
  	new_fl = NULL;
9cedc194a   Kirill Korotaev   [PATCH] Return er...
1064
  	error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
  
  out:
6109c8503   Jeff Layton   locks: add a dedi...
1067
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1068
  	percpu_up_read(&file_rwsem);
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1069
1070
  	if (new_fl)
  		locks_free_lock(new_fl);
ed9814d85   Jeff Layton   locks: defer free...
1071
  	locks_dispose_list(&dispose);
c883da313   Jeff Layton   locks: add tracep...
1072
  	trace_flock_lock_inode(inode, request, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
1074
  	return error;
  }
b4d629a39   Jeff Layton   locks: rename __p...
1075
1076
  static int posix_lock_inode(struct inode *inode, struct file_lock *request,
  			    struct file_lock *conflock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
  {
bd61e0a9c   Jeff Layton   locks: convert po...
1078
  	struct file_lock *fl, *tmp;
39005d022   Miklos Szeredi   [PATCH] locks: do...
1079
1080
  	struct file_lock *new_fl = NULL;
  	struct file_lock *new_fl2 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081
1082
  	struct file_lock *left = NULL;
  	struct file_lock *right = NULL;
bd61e0a9c   Jeff Layton   locks: convert po...
1083
  	struct file_lock_context *ctx;
b9746ef80   Jeff Layton   locks: make "adde...
1084
1085
  	int error;
  	bool added = false;
ed9814d85   Jeff Layton   locks: defer free...
1086
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087

5c1c669a1   Jeff Layton   locks: don't allo...
1088
  	ctx = locks_get_lock_context(inode, request->fl_type);
bd61e0a9c   Jeff Layton   locks: convert po...
1089
  	if (!ctx)
5c1c669a1   Jeff Layton   locks: don't allo...
1090
  		return (request->fl_type == F_UNLCK) ? 0 : -ENOMEM;
bd61e0a9c   Jeff Layton   locks: convert po...
1091

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
  	/*
  	 * We may need two file_lock structures for this operation,
  	 * so we get them in advance to avoid races.
39005d022   Miklos Szeredi   [PATCH] locks: do...
1095
1096
  	 *
  	 * In some cases we can be sure, that no new locks will be needed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  	 */
39005d022   Miklos Szeredi   [PATCH] locks: do...
1098
1099
1100
1101
1102
1103
  	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   Linus Torvalds   Linux-2.6.12-rc2
1104

02e525b2a   Peter Zijlstra   locking/percpu-rw...
1105
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1106
  	spin_lock(&ctx->flc_lock);
1cb360125   Jeff Layton   locks: comment cl...
1107
1108
1109
  	/*
  	 * 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   Jeff Layton   locks: turn the b...
1110
  	 * blocker's list of waiters and the global blocked_hash.
1cb360125   Jeff Layton   locks: comment cl...
1111
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  	if (request->fl_type != F_UNLCK) {
bd61e0a9c   Jeff Layton   locks: convert po...
1113
  		list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
  			if (!posix_locks_conflict(request, fl))
  				continue;
5842add2f   Andy Adamson   [PATCH] VFS,fs/lo...
1116
  			if (conflock)
3fe0fff18   Kinglong Mee   locks: Rename __l...
1117
  				locks_copy_conflock(conflock, fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
1119
1120
  			error = -EAGAIN;
  			if (!(request->fl_flags & FL_SLEEP))
  				goto out;
1c8c601a8   Jeff Layton   locks: protect mo...
1121
1122
1123
1124
  			/*
  			 * Deadlock detection and insertion into the blocked
  			 * locks list must be done while holding the same lock!
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
  			error = -EDEADLK;
7b2296afb   Jeff Layton   locks: give the b...
1126
  			spin_lock(&blocked_lock_lock);
945ab8f6d   Jeff Layton   locks: wake any l...
1127
1128
1129
1130
1131
  			/*
  			 * Ensure that we don't find any locks blocked on this
  			 * request during deadlock detection.
  			 */
  			__locks_wake_up_blocks(request);
1c8c601a8   Jeff Layton   locks: protect mo...
1132
1133
  			if (likely(!posix_locks_deadlock(request, fl))) {
  				error = FILE_LOCK_DEFERRED;
fd7732e03   NeilBrown   fs/locks: create ...
1134
1135
  				__locks_insert_block(fl, request,
  						     posix_locks_conflict);
1c8c601a8   Jeff Layton   locks: protect mo...
1136
  			}
7b2296afb   Jeff Layton   locks: give the b...
1137
  			spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
  			goto out;
7bbd1fc0e   NeilBrown   fs/locks: remove ...
1139
1140
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
1142
1143
1144
1145
  
  	/* If we're just looking for a conflict, we're done. */
  	error = 0;
  	if (request->fl_flags & FL_ACCESS)
  		goto out;
bd61e0a9c   Jeff Layton   locks: convert po...
1146
1147
1148
1149
  	/* 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   Linus Torvalds   Linux-2.6.12-rc2
1150
  	}
1cb360125   Jeff Layton   locks: comment cl...
1151
  	/* Process locks with this owner. */
bd61e0a9c   Jeff Layton   locks: convert po...
1152
1153
1154
1155
1156
  	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   Linus Torvalds   Linux-2.6.12-rc2
1157
  		if (request->fl_type == fl->fl_type) {
449231d6d   Olaf Kirch   From: Olaf Kirch ...
1158
1159
1160
1161
  			/* 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   Linus Torvalds   Linux-2.6.12-rc2
1162
  			if (fl->fl_end < request->fl_start - 1)
bd61e0a9c   Jeff Layton   locks: convert po...
1163
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
1165
1166
  			/* If the next lock in the list has entirely bigger
  			 * addresses than the new one, insert the lock here.
  			 */
449231d6d   Olaf Kirch   From: Olaf Kirch ...
1167
  			if (fl->fl_start - 1 > request->fl_end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  				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   Jeff Layton   Revert "locks: ke...
1184
  				locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
1186
1187
  				continue;
  			}
  			request = fl;
b9746ef80   Jeff Layton   locks: make "adde...
1188
  			added = true;
bd61e0a9c   Jeff Layton   locks: convert po...
1189
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
1192
1193
  			/* Processing for different lock types is a bit
  			 * more complex.
  			 */
  			if (fl->fl_end < request->fl_start)
bd61e0a9c   Jeff Layton   locks: convert po...
1194
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
  			if (fl->fl_start > request->fl_end)
  				break;
  			if (request->fl_type == F_UNLCK)
b9746ef80   Jeff Layton   locks: make "adde...
1198
  				added = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
  			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   Jeff Layton   Revert "locks: ke...
1213
  					locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
  					continue;
  				}
b84d49f94   Jeff Layton   locks: don't reus...
1216
1217
1218
1219
1220
1221
  				/*
  				 * 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   Linus Torvalds   Linux-2.6.12-rc2
1222
  				 */
b84d49f94   Jeff Layton   locks: don't reus...
1223
1224
1225
1226
  				error = -ENOLCK;
  				if (!new_fl)
  					goto out;
  				locks_copy_lock(new_fl, request);
5ef159681   yangerkun   locks: add locks_...
1227
  				locks_move_blocks(new_fl, request);
b84d49f94   Jeff Layton   locks: don't reus...
1228
1229
  				request = new_fl;
  				new_fl = NULL;
e084c1bd4   Jeff Layton   Revert "locks: ke...
1230
1231
  				locks_insert_lock_ctx(request, &fl->fl_list);
  				locks_delete_lock_ctx(fl, &dispose);
b9746ef80   Jeff Layton   locks: make "adde...
1232
  				added = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
1234
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  	}
0d9a490ab   Miklos Szeredi   [PATCH] locks: do...
1236
  	/*
1cb360125   Jeff Layton   locks: comment cl...
1237
1238
1239
  	 * 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   Miklos Szeredi   [PATCH] locks: do...
1240
1241
1242
1243
  	 */
  	error = -ENOLCK; /* "no luck" */
  	if (right && left == right && !new_fl2)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
  	error = 0;
  	if (!added) {
f475ae957   Trond Myklebust   VFS: Allow caller...
1246
1247
1248
  		if (request->fl_type == F_UNLCK) {
  			if (request->fl_flags & FL_EXISTS)
  				error = -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  			goto out;
f475ae957   Trond Myklebust   VFS: Allow caller...
1250
  		}
0d9a490ab   Miklos Szeredi   [PATCH] locks: do...
1251
1252
1253
1254
1255
  
  		if (!new_fl) {
  			error = -ENOLCK;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  		locks_copy_lock(new_fl, request);
5946c4319   NeilBrown   fs/locks: allow a...
1257
  		locks_move_blocks(new_fl, request);
e084c1bd4   Jeff Layton   Revert "locks: ke...
1258
  		locks_insert_lock_ctx(new_fl, &fl->fl_list);
2e2f756f8   Jeff Layton   locks: fix list i...
1259
  		fl = new_fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  		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   Jeff Layton   Revert "locks: ke...
1270
  			locks_insert_lock_ctx(left, &fl->fl_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
1274
1275
1276
1277
1278
1279
  		}
  		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   Jeff Layton   locks: add a dedi...
1280
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1281
  	percpu_up_read(&file_rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
1283
1284
1285
1286
1287
1288
  	/*
  	 * Free any unused locks.
  	 */
  	if (new_fl)
  		locks_free_lock(new_fl);
  	if (new_fl2)
  		locks_free_lock(new_fl2);
ed9814d85   Jeff Layton   locks: defer free...
1289
  	locks_dispose_list(&dispose);
1890910fd   Jeff Layton   locks: sprinkle s...
1290
  	trace_posix_lock_inode(inode, request, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
1292
1293
1294
1295
1296
1297
  	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   Marc Eshel   locks: allow {vfs...
1298
   * @conflock: Place to return a copy of the conflicting lock, if found.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
1300
1301
1302
   *
   * 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   Trond Myklebust   VFS: Allow caller...
1303
1304
1305
1306
   *
   * 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   Linus Torvalds   Linux-2.6.12-rc2
1307
   */
150b39345   Marc Eshel   locks: allow {vfs...
1308
  int posix_lock_file(struct file *filp, struct file_lock *fl,
5842add2f   Andy Adamson   [PATCH] VFS,fs/lo...
1309
1310
  			struct file_lock *conflock)
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1311
  	return posix_lock_inode(locks_inode(filp), fl, conflock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
  }
150b39345   Marc Eshel   locks: allow {vfs...
1313
  EXPORT_SYMBOL(posix_lock_file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
1315
  
  /**
29d01b22e   Jeff Layton   locks: new helper...
1316
1317
   * posix_lock_inode_wait - Apply a POSIX-style lock to a file
   * @inode: inode of file to which lock request should be applied
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
   * @fl: The lock to be applied
   *
616fb38fa   Benjamin Coddington   locks: cleanup po...
1320
   * Apply a POSIX style lock request to an inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
   */
616fb38fa   Benjamin Coddington   locks: cleanup po...
1322
  static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
1326
  {
  	int error;
  	might_sleep ();
  	for (;;) {
b4d629a39   Jeff Layton   locks: rename __p...
1327
  		error = posix_lock_inode(inode, fl, NULL);
bde74e4bc   Miklos Szeredi   locks: add specia...
1328
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
  			break;
dcf23ac3e   Linus Torvalds   locks: reinstate ...
1330
1331
  		error = wait_event_interruptible(fl->fl_wait,
  					list_empty(&fl->fl_blocked_member));
16306a61d   NeilBrown   fs/locks: always ...
1332
1333
  		if (error)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  	}
16306a61d   NeilBrown   fs/locks: always ...
1335
  	locks_delete_block(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
  	return error;
  }
29d01b22e   Jeff Layton   locks: new helper...
1338

9e8925b67   Jeff Layton   locks: Allow disa...
1339
  #ifdef CONFIG_MANDATORY_FILE_LOCKING
29d01b22e   Jeff Layton   locks: new helper...
1340
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
   * locks_mandatory_locked - Check for an active lock
d7a06983a   Jeff Layton   locks: fix locks_...
1342
   * @file: the file to check
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
1345
1346
   *
   * Searches the inode's list of locks to find any POSIX locks which conflict.
   * This function is called from locks_verify_locked() only.
   */
d7a06983a   Jeff Layton   locks: fix locks_...
1347
  int locks_mandatory_locked(struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
  {
bd61e0a9c   Jeff Layton   locks: convert po...
1349
  	int ret;
c568d6834   Miklos Szeredi   locks: fix file l...
1350
  	struct inode *inode = locks_inode(file);
bd61e0a9c   Jeff Layton   locks: convert po...
1351
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
  	struct file_lock *fl;
128a37852   Dmitry Vyukov   fs: fix data race...
1353
  	ctx = smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
1354
1355
  	if (!ctx || list_empty_careful(&ctx->flc_posix))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
1358
  	/*
  	 * Search the lock list for this inode for any POSIX locks.
  	 */
6109c8503   Jeff Layton   locks: add a dedi...
1359
  	spin_lock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
1360
1361
  	ret = 0;
  	list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
1362
  		if (fl->fl_owner != current->files &&
bd61e0a9c   Jeff Layton   locks: convert po...
1363
1364
  		    fl->fl_owner != file) {
  			ret = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
  			break;
bd61e0a9c   Jeff Layton   locks: convert po...
1366
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
  	}
6109c8503   Jeff Layton   locks: add a dedi...
1368
  	spin_unlock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
1369
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
1372
1373
  }
  
  /**
   * locks_mandatory_area - Check for a conflicting lock
acc15575e   Christoph Hellwig   locks: new locks_...
1374
   * @inode:	the file to check
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
   * @filp:       how the file was opened (if it was)
acc15575e   Christoph Hellwig   locks: new locks_...
1376
1377
1378
   * @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   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
   *
   * Searches the inode's list of locks to find any POSIX locks which conflict.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
   */
acc15575e   Christoph Hellwig   locks: new locks_...
1382
1383
  int locks_mandatory_area(struct inode *inode, struct file *filp, loff_t start,
  			 loff_t end, unsigned char type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
  {
  	struct file_lock fl;
  	int error;
29723adee   Jeff Layton   locks: make locks...
1387
  	bool sleep = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
1389
  
  	locks_init_lock(&fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
1392
1393
  	fl.fl_pid = current->tgid;
  	fl.fl_file = filp;
  	fl.fl_flags = FL_POSIX | FL_ACCESS;
  	if (filp && !(filp->f_flags & O_NONBLOCK))
29723adee   Jeff Layton   locks: make locks...
1394
  		sleep = true;
acc15575e   Christoph Hellwig   locks: new locks_...
1395
1396
1397
  	fl.fl_type = type;
  	fl.fl_start = start;
  	fl.fl_end = end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
  
  	for (;;) {
29723adee   Jeff Layton   locks: make locks...
1400
  		if (filp) {
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
1401
  			fl.fl_owner = filp;
29723adee   Jeff Layton   locks: make locks...
1402
  			fl.fl_flags &= ~FL_SLEEP;
b4d629a39   Jeff Layton   locks: rename __p...
1403
  			error = posix_lock_inode(inode, &fl, NULL);
29723adee   Jeff Layton   locks: make locks...
1404
1405
1406
1407
1408
1409
1410
  			if (!error)
  				break;
  		}
  
  		if (sleep)
  			fl.fl_flags |= FL_SLEEP;
  		fl.fl_owner = current->files;
b4d629a39   Jeff Layton   locks: rename __p...
1411
  		error = posix_lock_inode(inode, &fl, NULL);
bde74e4bc   Miklos Szeredi   locks: add specia...
1412
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
  			break;
dcf23ac3e   Linus Torvalds   locks: reinstate ...
1414
1415
  		error = wait_event_interruptible(fl.fl_wait,
  					list_empty(&fl.fl_blocked_member));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416
1417
1418
1419
1420
  		if (!error) {
  			/*
  			 * If we've been sleeping someone might have
  			 * changed the permissions behind our back.
  			 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
1421
  			if (__mandatory_lock(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1422
1423
  				continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
  		break;
  	}
16306a61d   NeilBrown   fs/locks: always ...
1426
  	locks_delete_block(&fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
1429
  
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
  EXPORT_SYMBOL(locks_mandatory_area);
9e8925b67   Jeff Layton   locks: Allow disa...
1431
  #endif /* CONFIG_MANDATORY_FILE_LOCKING */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432

778fc546f   J. Bruce Fields   locks: fix tracki...
1433
1434
1435
1436
1437
  static void lease_clear_pending(struct file_lock *fl, int arg)
  {
  	switch (arg) {
  	case F_UNLCK:
  		fl->fl_flags &= ~FL_UNLOCK_PENDING;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
1438
  		fallthrough;
778fc546f   J. Bruce Fields   locks: fix tracki...
1439
1440
1441
1442
  	case F_RDLCK:
  		fl->fl_flags &= ~FL_DOWNGRADE_PENDING;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
  /* We already had a lease on this file; just change its type */
7448cc37b   Jeff Layton   locks: clean up t...
1444
  int lease_modify(struct file_lock *fl, int arg, struct list_head *dispose)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1446
1447
1448
1449
  	int error = assign_type(fl, arg);
  
  	if (error)
  		return error;
778fc546f   J. Bruce Fields   locks: fix tracki...
1450
  	lease_clear_pending(fl, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
  	locks_wake_up_blocks(fl);
3b6e2723f   Filipe Brandenburger   locks: prevent si...
1452
1453
1454
1455
1456
  	if (arg == F_UNLCK) {
  		struct file *filp = fl->fl_file;
  
  		f_delown(filp);
  		filp->f_owner.signum = 0;
96d6d59ce   J. Bruce Fields   locks: move lease...
1457
1458
1459
1460
1461
1462
  		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   Jeff Layton   Revert "locks: ke...
1463
  		locks_delete_lock_ctx(fl, dispose);
3b6e2723f   Filipe Brandenburger   locks: prevent si...
1464
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
  EXPORT_SYMBOL(lease_modify);
778fc546f   J. Bruce Fields   locks: fix tracki...
1468
1469
1470
1471
1472
1473
1474
  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   Jeff Layton   locks: move freei...
1475
  static void time_out_leases(struct inode *inode, struct list_head *dispose)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
  {
8634b51f6   Jeff Layton   locks: convert le...
1477
1478
  	struct file_lock_context *ctx = inode->i_flctx;
  	struct file_lock *fl, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479

6109c8503   Jeff Layton   locks: add a dedi...
1480
  	lockdep_assert_held(&ctx->flc_lock);
f82b4b678   Jeff Layton   locks: move i_loc...
1481

8634b51f6   Jeff Layton   locks: convert le...
1482
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
62af4f1f7   Jeff Layton   locks: add some t...
1483
  		trace_time_out_leases(inode, fl);
778fc546f   J. Bruce Fields   locks: fix tracki...
1484
  		if (past_time(fl->fl_downgrade_time))
7448cc37b   Jeff Layton   locks: clean up t...
1485
  			lease_modify(fl, F_RDLCK, dispose);
778fc546f   J. Bruce Fields   locks: fix tracki...
1486
  		if (past_time(fl->fl_break_time))
7448cc37b   Jeff Layton   locks: clean up t...
1487
  			lease_modify(fl, F_UNLCK, dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
  	}
  }
df4e8d2c1   J. Bruce Fields   locks: implement ...
1490
1491
  static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
  {
d51f527f4   Ira Weiny   locks: Add trace_...
1492
  	bool rc;
28df3d153   J. Bruce Fields   nfsd: clients don...
1493
1494
1495
  	if (lease->fl_lmops->lm_breaker_owns_lease
  			&& lease->fl_lmops->lm_breaker_owns_lease(lease))
  		return false;
d51f527f4   Ira Weiny   locks: Add trace_...
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
  	if ((breaker->fl_flags & FL_LAYOUT) != (lease->fl_flags & FL_LAYOUT)) {
  		rc = false;
  		goto trace;
  	}
  	if ((breaker->fl_flags & FL_DELEG) && (lease->fl_flags & FL_LEASE)) {
  		rc = false;
  		goto trace;
  	}
  
  	rc = locks_conflict(breaker, lease);
  trace:
  	trace_leases_conflict(rc, lease, breaker);
  	return rc;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1509
  }
03d12ddf8   Jeff Layton   locks: __break_le...
1510
1511
1512
  static bool
  any_leases_conflict(struct inode *inode, struct file_lock *breaker)
  {
8634b51f6   Jeff Layton   locks: convert le...
1513
  	struct file_lock_context *ctx = inode->i_flctx;
03d12ddf8   Jeff Layton   locks: __break_le...
1514
  	struct file_lock *fl;
6109c8503   Jeff Layton   locks: add a dedi...
1515
  	lockdep_assert_held(&ctx->flc_lock);
03d12ddf8   Jeff Layton   locks: __break_le...
1516

8634b51f6   Jeff Layton   locks: convert le...
1517
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
03d12ddf8   Jeff Layton   locks: __break_le...
1518
1519
1520
1521
1522
  		if (leases_conflict(fl, breaker))
  			return true;
  	}
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
1525
  /**
   *	__break_lease	-	revoke all outstanding leases on file
   *	@inode: the inode of the file to return
df4e8d2c1   J. Bruce Fields   locks: implement ...
1526
1527
1528
1529
   *	@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   Linus Torvalds   Linux-2.6.12-rc2
1530
   *
87250dd26   david m. richter   leases: minor bre...
1531
1532
1533
   *	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   Linus Torvalds   Linux-2.6.12-rc2
1534
1535
   *	specified %O_NONBLOCK to your open().
   */
df4e8d2c1   J. Bruce Fields   locks: implement ...
1536
  int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  {
778fc546f   J. Bruce Fields   locks: fix tracki...
1538
  	int error = 0;
128a37852   Dmitry Vyukov   fs: fix data race...
1539
  	struct file_lock_context *ctx;
a901125c6   Yan, Zheng   locks: fix file_l...
1540
  	struct file_lock *new_fl, *fl, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
  	unsigned long break_time;
8737c9305   Al Viro   Switch may_open()...
1542
  	int want_write = (mode & O_ACCMODE) != O_RDONLY;
c45198eda   Jeff Layton   locks: move freei...
1543
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544

8737c9305   Al Viro   Switch may_open()...
1545
  	new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
6d4b9e38d   Linus Torvalds   vfs: fix handling...
1546
1547
  	if (IS_ERR(new_fl))
  		return PTR_ERR(new_fl);
df4e8d2c1   J. Bruce Fields   locks: implement ...
1548
  	new_fl->fl_flags = type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549

8634b51f6   Jeff Layton   locks: convert le...
1550
  	/* typically we will check that ctx is non-NULL before calling */
128a37852   Dmitry Vyukov   fs: fix data race...
1551
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1552
1553
  	if (!ctx) {
  		WARN_ON_ONCE(1);
cfddf9f4c   Wenwen Wang   locks: fix a memo...
1554
  		goto free_lock;
8634b51f6   Jeff Layton   locks: convert le...
1555
  	}
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1556
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1557
  	spin_lock(&ctx->flc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558

c45198eda   Jeff Layton   locks: move freei...
1559
  	time_out_leases(inode, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560

03d12ddf8   Jeff Layton   locks: __break_le...
1561
  	if (!any_leases_conflict(inode, new_fl))
778fc546f   J. Bruce Fields   locks: fix tracki...
1562
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
1564
1565
1566
1567
1568
  	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   Yan, Zheng   locks: fix file_l...
1569
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
df4e8d2c1   J. Bruce Fields   locks: implement ...
1570
1571
  		if (!leases_conflict(fl, new_fl))
  			continue;
778fc546f   J. Bruce Fields   locks: fix tracki...
1572
1573
1574
1575
  		if (want_write) {
  			if (fl->fl_flags & FL_UNLOCK_PENDING)
  				continue;
  			fl->fl_flags |= FL_UNLOCK_PENDING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  			fl->fl_break_time = break_time;
778fc546f   J. Bruce Fields   locks: fix tracki...
1577
  		} else {
8634b51f6   Jeff Layton   locks: convert le...
1578
  			if (lease_breaking(fl))
778fc546f   J. Bruce Fields   locks: fix tracki...
1579
1580
1581
  				continue;
  			fl->fl_flags |= FL_DOWNGRADE_PENDING;
  			fl->fl_downgrade_time = break_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582
  		}
4d01b7f5e   Jeff Layton   locks: give lm_br...
1583
  		if (fl->fl_lmops->lm_break(fl))
e084c1bd4   Jeff Layton   Revert "locks: ke...
1584
  			locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
  	}
8634b51f6   Jeff Layton   locks: convert le...
1586
  	if (list_empty(&ctx->flc_lease))
4d01b7f5e   Jeff Layton   locks: give lm_br...
1587
  		goto out;
843c6b2f4   Jeff Layton   locks: remove i_h...
1588
  	if (mode & O_NONBLOCK) {
62af4f1f7   Jeff Layton   locks: add some t...
1589
  		trace_break_lease_noblock(inode, new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
1591
1592
1593
1594
  		error = -EWOULDBLOCK;
  		goto out;
  	}
  
  restart:
8634b51f6   Jeff Layton   locks: convert le...
1595
1596
  	fl = list_first_entry(&ctx->flc_lease, struct file_lock, fl_list);
  	break_time = fl->fl_break_time;
f1c6bb2cb   Jeff Layton   locks: allow __br...
1597
  	if (break_time != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
  		break_time -= jiffies;
f1c6bb2cb   Jeff Layton   locks: allow __br...
1599
1600
  	if (break_time == 0)
  		break_time++;
fd7732e03   NeilBrown   fs/locks: create ...
1601
  	locks_insert_block(fl, new_fl, leases_conflict);
62af4f1f7   Jeff Layton   locks: add some t...
1602
  	trace_break_lease_block(inode, new_fl);
6109c8503   Jeff Layton   locks: add a dedi...
1603
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1604
  	percpu_up_read(&file_rwsem);
aba376607   Peter Zijlstra   fs/locks: Replace...
1605

c45198eda   Jeff Layton   locks: move freei...
1606
  	locks_dispose_list(&dispose);
4321e01e7   Matthew Wilcox   file locks: Use w...
1607
  	error = wait_event_interruptible_timeout(new_fl->fl_wait,
dcf23ac3e   Linus Torvalds   locks: reinstate ...
1608
1609
  					list_empty(&new_fl->fl_blocked_member),
  					break_time);
aba376607   Peter Zijlstra   fs/locks: Replace...
1610

02e525b2a   Peter Zijlstra   locking/percpu-rw...
1611
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1612
  	spin_lock(&ctx->flc_lock);
62af4f1f7   Jeff Layton   locks: add some t...
1613
  	trace_break_lease_unblock(inode, new_fl);
1c8c601a8   Jeff Layton   locks: protect mo...
1614
  	locks_delete_block(new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  	if (error >= 0) {
778fc546f   J. Bruce Fields   locks: fix tracki...
1616
1617
1618
1619
  		/*
  		 * Wait for the next conflicting lease that has not been
  		 * broken yet
  		 */
03d12ddf8   Jeff Layton   locks: __break_le...
1620
1621
1622
1623
  		if (error == 0)
  			time_out_leases(inode, &dispose);
  		if (any_leases_conflict(inode, new_fl))
  			goto restart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
1625
  		error = 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
  out:
6109c8503   Jeff Layton   locks: add a dedi...
1627
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1628
  	percpu_up_read(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1629
  	locks_dispose_list(&dispose);
cfddf9f4c   Wenwen Wang   locks: fix a memo...
1630
  free_lock:
6d4b9e38d   Linus Torvalds   vfs: fix handling...
1631
  	locks_free_lock(new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
1633
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1634
1635
1636
  EXPORT_SYMBOL(__break_lease);
  
  /**
76c479480   Amir Goldstein   nfsd: encode stat...
1637
   *	lease_get_mtime - update modified time of an inode with exclusive lease
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
   *	@inode: the inode
76c479480   Amir Goldstein   nfsd: encode stat...
1639
   *      @time:  pointer to a timespec which contains the last modified time
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
1641
1642
   *
   * This is to force NFS clients to flush their caches for files with
   * exclusive leases.  The justification is that if someone has an
a6b91919e   Randy Dunlap   fs: fix kernel-do...
1643
   * exclusive lease, then they could be modifying it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
   */
95582b008   Deepa Dinamani   vfs: change inode...
1645
  void lease_get_mtime(struct inode *inode, struct timespec64 *time)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  {
bfe860243   Jeff Layton   locks: close pote...
1647
  	bool has_lease = false;
128a37852   Dmitry Vyukov   fs: fix data race...
1648
  	struct file_lock_context *ctx;
8634b51f6   Jeff Layton   locks: convert le...
1649
  	struct file_lock *fl;
bfe860243   Jeff Layton   locks: close pote...
1650

128a37852   Dmitry Vyukov   fs: fix data race...
1651
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1652
  	if (ctx && !list_empty_careful(&ctx->flc_lease)) {
6109c8503   Jeff Layton   locks: add a dedi...
1653
  		spin_lock(&ctx->flc_lock);
8ace5dfb9   Geliang Tang   locks: use list_f...
1654
1655
1656
1657
  		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   Jeff Layton   locks: add a dedi...
1658
  		spin_unlock(&ctx->flc_lock);
bfe860243   Jeff Layton   locks: close pote...
1659
1660
1661
  	}
  
  	if (has_lease)
c2050a454   Deepa Dinamani   fs: Replace curre...
1662
  		*time = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
  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   Miklos Szeredi   locks: fix file l...
1692
  	struct inode *inode = locks_inode(filp);
128a37852   Dmitry Vyukov   fs: fix data race...
1693
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
  	int type = F_UNLCK;
c45198eda   Jeff Layton   locks: move freei...
1695
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1696

128a37852   Dmitry Vyukov   fs: fix data race...
1697
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1698
  	if (ctx && !list_empty_careful(&ctx->flc_lease)) {
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1699
  		percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1700
  		spin_lock(&ctx->flc_lock);
c568d6834   Miklos Szeredi   locks: fix file l...
1701
  		time_out_leases(inode, &dispose);
8634b51f6   Jeff Layton   locks: convert le...
1702
1703
1704
  		list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
  			if (fl->fl_file != filp)
  				continue;
778fc546f   J. Bruce Fields   locks: fix tracki...
1705
  			type = target_leasetype(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
  			break;
  		}
6109c8503   Jeff Layton   locks: add a dedi...
1708
  		spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1709
  		percpu_up_read(&file_rwsem);
5f43086bb   Peter Zijlstra   locking, fs/locks...
1710

8634b51f6   Jeff Layton   locks: convert le...
1711
  		locks_dispose_list(&dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
1714
  	return type;
  }
24cbe7845   Jeff Layton   locks: close pote...
1715
  /**
387e3746d   Amir Goldstein   locks: eliminate ...
1716
   * check_conflicting_open - see if the given file points to an inode that has
7bbd1fc0e   NeilBrown   fs/locks: remove ...
1717
1718
   *			    an existing open that would conflict with the
   *			    desired lease.
387e3746d   Amir Goldstein   locks: eliminate ...
1719
   * @filp:	file to check
24cbe7845   Jeff Layton   locks: close pote...
1720
   * @arg:	type of lease that we're trying to acquire
7fadc59cc   Randy Dunlap   fs: fix fs/locks....
1721
   * @flags:	current lock flags
24cbe7845   Jeff Layton   locks: close pote...
1722
1723
1724
1725
1726
   *
   * 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
387e3746d   Amir Goldstein   locks: eliminate ...
1727
  check_conflicting_open(struct file *filp, const long arg, int flags)
24cbe7845   Jeff Layton   locks: close pote...
1728
  {
387e3746d   Amir Goldstein   locks: eliminate ...
1729
1730
  	struct inode *inode = locks_inode(filp);
  	int self_wcount = 0, self_rcount = 0;
24cbe7845   Jeff Layton   locks: close pote...
1731

11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1732
1733
  	if (flags & FL_LAYOUT)
  		return 0;
94415b06e   J. Bruce Fields   nfsd4: a client's...
1734
1735
1736
  	if (flags & FL_DELEG)
  		/* We leave these checks to the caller. */
  		return 0;
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1737

387e3746d   Amir Goldstein   locks: eliminate ...
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
  	if (arg == F_RDLCK)
  		return inode_is_open_for_write(inode) ? -EAGAIN : 0;
  	else if (arg != F_WRLCK)
  		return 0;
  
  	/*
  	 * Make sure that only read/write count is from lease requestor.
  	 * Note that this will result in denying write leases when i_writecount
  	 * is negative, which is what we want.  (We shouldn't grant write leases
  	 * on files open for execution.)
  	 */
  	if (filp->f_mode & FMODE_WRITE)
  		self_wcount = 1;
  	else if (filp->f_mode & FMODE_READ)
  		self_rcount = 1;
24cbe7845   Jeff Layton   locks: close pote...
1753

387e3746d   Amir Goldstein   locks: eliminate ...
1754
1755
1756
  	if (atomic_read(&inode->i_writecount) != self_wcount ||
  	    atomic_read(&inode->i_readcount) != self_rcount)
  		return -EAGAIN;
24cbe7845   Jeff Layton   locks: close pote...
1757

387e3746d   Amir Goldstein   locks: eliminate ...
1758
  	return 0;
24cbe7845   Jeff Layton   locks: close pote...
1759
  }
e6f5c7893   Jeff Layton   locks: plumb a "p...
1760
1761
  static int
  generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1762
  {
8634b51f6   Jeff Layton   locks: convert le...
1763
  	struct file_lock *fl, *my_fl = NULL, *lease;
387e3746d   Amir Goldstein   locks: eliminate ...
1764
  	struct inode *inode = locks_inode(filp);
8634b51f6   Jeff Layton   locks: convert le...
1765
  	struct file_lock_context *ctx;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1766
  	bool is_deleg = (*flp)->fl_flags & FL_DELEG;
c1f24ef4e   J. Bruce Fields   locks: setlease c...
1767
  	int error;
c45198eda   Jeff Layton   locks: move freei...
1768
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769

096657b65   J. Bruce Fields   locks: fix leaks ...
1770
  	lease = *flp;
62af4f1f7   Jeff Layton   locks: add some t...
1771
  	trace_generic_add_lease(inode, lease);
5c1c669a1   Jeff Layton   locks: don't allo...
1772
1773
  	/* Note that arg is never F_UNLCK here */
  	ctx = locks_get_lock_context(inode, arg);
8634b51f6   Jeff Layton   locks: convert le...
1774
1775
  	if (!ctx)
  		return -ENOMEM;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1776
1777
1778
1779
1780
1781
1782
1783
  	/*
  	 * 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   Al Viro   wrappers for ->i_...
1784
  	if (is_deleg && !inode_trylock(inode))
df4e8d2c1   J. Bruce Fields   locks: implement ...
1785
1786
1787
1788
  		return -EAGAIN;
  
  	if (is_deleg && arg == F_WRLCK) {
  		/* Write delegations are not currently supported: */
5955102c9   Al Viro   wrappers for ->i_...
1789
  		inode_unlock(inode);
df4e8d2c1   J. Bruce Fields   locks: implement ...
1790
1791
1792
  		WARN_ON_ONCE(1);
  		return -EINVAL;
  	}
096657b65   J. Bruce Fields   locks: fix leaks ...
1793

02e525b2a   Peter Zijlstra   locking/percpu-rw...
1794
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1795
  	spin_lock(&ctx->flc_lock);
c45198eda   Jeff Layton   locks: move freei...
1796
  	time_out_leases(inode, &dispose);
387e3746d   Amir Goldstein   locks: eliminate ...
1797
  	error = check_conflicting_open(filp, arg, lease->fl_flags);
24cbe7845   Jeff Layton   locks: close pote...
1798
  	if (error)
096657b65   J. Bruce Fields   locks: fix leaks ...
1799
  		goto out;
6d5e8b05c   J. Bruce Fields   locks: share more...
1800

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
1802
1803
1804
1805
1806
1807
1808
  	/*
  	 * 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   J. Bruce Fields   locks: setlease c...
1809
  	error = -EAGAIN;
8634b51f6   Jeff Layton   locks: convert le...
1810
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1811
1812
  		if (fl->fl_file == filp &&
  		    fl->fl_owner == lease->fl_owner) {
8634b51f6   Jeff Layton   locks: convert le...
1813
  			my_fl = fl;
c1f24ef4e   J. Bruce Fields   locks: setlease c...
1814
1815
  			continue;
  		}
8634b51f6   Jeff Layton   locks: convert le...
1816

c1f24ef4e   J. Bruce Fields   locks: setlease c...
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
  		/*
  		 * 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   Linus Torvalds   Linux-2.6.12-rc2
1829
  	}
8634b51f6   Jeff Layton   locks: convert le...
1830
  	if (my_fl != NULL) {
0164bf023   Jeff Layton   locks: fix fasync...
1831
1832
  		lease = my_fl;
  		error = lease->fl_lmops->lm_change(lease, arg, &dispose);
1c7dd2ff4   Jeff Layton   locks: define a l...
1833
1834
1835
  		if (error)
  			goto out;
  		goto out_setup;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
1838
1839
  	error = -EINVAL;
  	if (!leases_enable)
  		goto out;
e084c1bd4   Jeff Layton   Revert "locks: ke...
1840
  	locks_insert_lock_ctx(lease, &ctx->flc_lease);
24cbe7845   Jeff Layton   locks: close pote...
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
  	/*
  	 * 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();
387e3746d   Amir Goldstein   locks: eliminate ...
1851
  	error = check_conflicting_open(filp, arg, lease->fl_flags);
8634b51f6   Jeff Layton   locks: convert le...
1852
  	if (error) {
e084c1bd4   Jeff Layton   Revert "locks: ke...
1853
  		locks_unlink_lock_ctx(lease);
8634b51f6   Jeff Layton   locks: convert le...
1854
1855
  		goto out;
  	}
1c7dd2ff4   Jeff Layton   locks: define a l...
1856
1857
1858
1859
  
  out_setup:
  	if (lease->fl_lmops->lm_setup)
  		lease->fl_lmops->lm_setup(lease, priv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
  out:
6109c8503   Jeff Layton   locks: add a dedi...
1861
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1862
  	percpu_up_read(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1863
  	locks_dispose_list(&dispose);
df4e8d2c1   J. Bruce Fields   locks: implement ...
1864
  	if (is_deleg)
5955102c9   Al Viro   wrappers for ->i_...
1865
  		inode_unlock(inode);
8634b51f6   Jeff Layton   locks: convert le...
1866
  	if (!error && !my_fl)
1c7dd2ff4   Jeff Layton   locks: define a l...
1867
  		*flp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
1869
  	return error;
  }
8335ebd94   J. Bruce Fields   leases: split up ...
1870

2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1871
  static int generic_delete_lease(struct file *filp, void *owner)
8335ebd94   J. Bruce Fields   leases: split up ...
1872
  {
0efaa7e82   Jeff Layton   locks: generic_de...
1873
  	int error = -EAGAIN;
8634b51f6   Jeff Layton   locks: convert le...
1874
  	struct file_lock *fl, *victim = NULL;
c568d6834   Miklos Szeredi   locks: fix file l...
1875
  	struct inode *inode = locks_inode(filp);
128a37852   Dmitry Vyukov   fs: fix data race...
1876
  	struct file_lock_context *ctx;
c45198eda   Jeff Layton   locks: move freei...
1877
  	LIST_HEAD(dispose);
8335ebd94   J. Bruce Fields   leases: split up ...
1878

128a37852   Dmitry Vyukov   fs: fix data race...
1879
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1880
1881
1882
1883
  	if (!ctx) {
  		trace_generic_delete_lease(inode, NULL);
  		return error;
  	}
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1884
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1885
  	spin_lock(&ctx->flc_lock);
8634b51f6   Jeff Layton   locks: convert le...
1886
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1887
1888
  		if (fl->fl_file == filp &&
  		    fl->fl_owner == owner) {
8634b51f6   Jeff Layton   locks: convert le...
1889
  			victim = fl;
0efaa7e82   Jeff Layton   locks: generic_de...
1890
  			break;
8634b51f6   Jeff Layton   locks: convert le...
1891
  		}
8335ebd94   J. Bruce Fields   leases: split up ...
1892
  	}
a9b1b455c   Jeff Layton   locks: fix generi...
1893
  	trace_generic_delete_lease(inode, victim);
8634b51f6   Jeff Layton   locks: convert le...
1894
  	if (victim)
7448cc37b   Jeff Layton   locks: clean up t...
1895
  		error = fl->fl_lmops->lm_change(victim, F_UNLCK, &dispose);
6109c8503   Jeff Layton   locks: add a dedi...
1896
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
1897
  	percpu_up_read(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1898
  	locks_dispose_list(&dispose);
0efaa7e82   Jeff Layton   locks: generic_de...
1899
  	return error;
8335ebd94   J. Bruce Fields   leases: split up ...
1900
1901
1902
1903
  }
  
  /**
   *	generic_setlease	-	sets a lease on an open file
1c7dd2ff4   Jeff Layton   locks: define a l...
1904
1905
1906
1907
1908
   *	@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   J. Bruce Fields   leases: split up ...
1909
1910
1911
   *
   *	The (input) flp->fl_lmops->lm_break function is required
   *	by break_lease().
8335ebd94   J. Bruce Fields   leases: split up ...
1912
   */
e6f5c7893   Jeff Layton   locks: plumb a "p...
1913
1914
  int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
  			void **priv)
8335ebd94   J. Bruce Fields   leases: split up ...
1915
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1916
  	struct inode *inode = locks_inode(filp);
8335ebd94   J. Bruce Fields   leases: split up ...
1917
  	int error;
8e96e3b7b   Eric W. Biederman   userns: Use uid_e...
1918
  	if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
8335ebd94   J. Bruce Fields   leases: split up ...
1919
1920
1921
1922
1923
1924
  		return -EACCES;
  	if (!S_ISREG(inode->i_mode))
  		return -EINVAL;
  	error = security_file_lock(filp, arg);
  	if (error)
  		return error;
8335ebd94   J. Bruce Fields   leases: split up ...
1925
1926
  	switch (arg) {
  	case F_UNLCK:
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1927
  		return generic_delete_lease(filp, *priv);
8335ebd94   J. Bruce Fields   leases: split up ...
1928
1929
  	case F_RDLCK:
  	case F_WRLCK:
0efaa7e82   Jeff Layton   locks: generic_de...
1930
1931
1932
1933
  		if (!(*flp)->fl_lmops->lm_break) {
  			WARN_ON_ONCE(1);
  			return -ENOLCK;
  		}
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1934

e6f5c7893   Jeff Layton   locks: plumb a "p...
1935
  		return generic_add_lease(filp, arg, flp, priv);
8335ebd94   J. Bruce Fields   leases: split up ...
1936
  	default:
8d657eb3b   Dave Jones   Remove easily use...
1937
  		return -EINVAL;
8335ebd94   J. Bruce Fields   leases: split up ...
1938
1939
  	}
  }
0af1a4504   Christoph Hellwig   rename setlease t...
1940
  EXPORT_SYMBOL(generic_setlease);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1941

18f6622eb   Jeff Layton   locks: create a n...
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
  #if IS_ENABLED(CONFIG_SRCU)
  /*
   * Kernel subsystems can register to be notified on any attempt to set
   * a new lease with the lease_notifier_chain. This is used by (e.g.) nfsd
   * to close files that it may have cached when there is an attempt to set a
   * conflicting lease.
   */
  static struct srcu_notifier_head lease_notifier_chain;
  
  static inline void
  lease_notifier_chain_init(void)
  {
  	srcu_init_notifier_head(&lease_notifier_chain);
  }
  
  static inline void
  setlease_notifier(long arg, struct file_lock *lease)
  {
  	if (arg != F_UNLCK)
  		srcu_notifier_call_chain(&lease_notifier_chain, arg, lease);
  }
  
  int lease_register_notifier(struct notifier_block *nb)
  {
  	return srcu_notifier_chain_register(&lease_notifier_chain, nb);
  }
  EXPORT_SYMBOL_GPL(lease_register_notifier);
  
  void lease_unregister_notifier(struct notifier_block *nb)
  {
  	srcu_notifier_chain_unregister(&lease_notifier_chain, nb);
  }
  EXPORT_SYMBOL_GPL(lease_unregister_notifier);
  
  #else /* !IS_ENABLED(CONFIG_SRCU) */
  static inline void
  lease_notifier_chain_init(void)
  {
  }
  
  static inline void
  setlease_notifier(long arg, struct file_lock *lease)
  {
  }
  
  int lease_register_notifier(struct notifier_block *nb)
  {
  	return 0;
  }
  EXPORT_SYMBOL_GPL(lease_register_notifier);
  
  void lease_unregister_notifier(struct notifier_block *nb)
  {
  }
  EXPORT_SYMBOL_GPL(lease_unregister_notifier);
  
  #endif /* IS_ENABLED(CONFIG_SRCU) */
b89f43213   Arnd Bergmann   fs/locks.c: prepa...
1999
  /**
e51673aa5   Jeff Layton   locks: clean up v...
2000
   * vfs_setlease        -       sets a lease on an open file
1c7dd2ff4   Jeff Layton   locks: define a l...
2001
2002
2003
2004
   * @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
7bbd1fc0e   NeilBrown   fs/locks: remove ...
2005
   *		NULL if lm_setup doesn't require it)
e51673aa5   Jeff Layton   locks: clean up v...
2006
2007
2008
   *
   * 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   Mauro Carvalho Chehab   fs: locks: Fix so...
2009
2010
   * 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   Jeff Layton   locks: clean up v...
2011
   * stack trace).
1c7dd2ff4   Jeff Layton   locks: define a l...
2012
2013
2014
   *
   * 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   Linus Torvalds   Linux-2.6.12-rc2
2015
   */
e6f5c7893   Jeff Layton   locks: plumb a "p...
2016
2017
  int
  vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2018
  {
18f6622eb   Jeff Layton   locks: create a n...
2019
2020
  	if (lease)
  		setlease_notifier(arg, *lease);
de2a4a501   Miklos Szeredi   Partially revert ...
2021
  	if (filp->f_op->setlease)
f82b4b678   Jeff Layton   locks: move i_loc...
2022
  		return filp->f_op->setlease(filp, arg, lease, priv);
1c7dd2ff4   Jeff Layton   locks: define a l...
2023
  	else
f82b4b678   Jeff Layton   locks: move i_loc...
2024
  		return generic_setlease(filp, arg, lease, priv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2025
  }
a9933cea7   J. Bruce Fields   locks: rename lea...
2026
  EXPORT_SYMBOL_GPL(vfs_setlease);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2027

0ceaf6c70   J. Bruce Fields   locks: prevent EN...
2028
  static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2029
  {
1c7dd2ff4   Jeff Layton   locks: define a l...
2030
  	struct file_lock *fl;
f7347ce4e   Linus Torvalds   fasync: re-organi...
2031
  	struct fasync_struct *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2032
  	int error;
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
2033
2034
2035
  	fl = lease_alloc(filp, arg);
  	if (IS_ERR(fl))
  		return PTR_ERR(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2036

f7347ce4e   Linus Torvalds   fasync: re-organi...
2037
2038
2039
2040
2041
  	new = fasync_alloc();
  	if (!new) {
  		locks_free_lock(fl);
  		return -ENOMEM;
  	}
1c7dd2ff4   Jeff Layton   locks: define a l...
2042
  	new->fa_fd = fd;
f7347ce4e   Linus Torvalds   fasync: re-organi...
2043

1c7dd2ff4   Jeff Layton   locks: define a l...
2044
  	error = vfs_setlease(filp, arg, &fl, (void **)&new);
2dfb928f7   Jeff Layton   locks: move locks...
2045
2046
  	if (fl)
  		locks_free_lock(fl);
f7347ce4e   Linus Torvalds   fasync: re-organi...
2047
2048
  	if (new)
  		fasync_free(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
2050
2051
2052
  	return error;
  }
  
  /**
0ceaf6c70   J. Bruce Fields   locks: prevent EN...
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
   *	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   Christoph Hellwig   fs: track fl_owne...
2065
  		return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp);
0ceaf6c70   J. Bruce Fields   locks: prevent EN...
2066
2067
2068
2069
  	return do_fcntl_add_lease(fd, filp, arg);
  }
  
  /**
29d01b22e   Jeff Layton   locks: new helper...
2070
2071
   * flock_lock_inode_wait - Apply a FLOCK-style lock to a file
   * @inode: inode of the file to apply to
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2072
2073
   * @fl: The lock to be applied
   *
29d01b22e   Jeff Layton   locks: new helper...
2074
   * Apply a FLOCK style lock request to an inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2075
   */
616fb38fa   Benjamin Coddington   locks: cleanup po...
2076
  static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2077
2078
2079
2080
  {
  	int error;
  	might_sleep();
  	for (;;) {
29d01b22e   Jeff Layton   locks: new helper...
2081
  		error = flock_lock_inode(inode, fl);
bde74e4bc   Miklos Szeredi   locks: add specia...
2082
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2083
  			break;
dcf23ac3e   Linus Torvalds   locks: reinstate ...
2084
2085
  		error = wait_event_interruptible(fl->fl_wait,
  				list_empty(&fl->fl_blocked_member));
16306a61d   NeilBrown   fs/locks: always ...
2086
2087
  		if (error)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
  	}
16306a61d   NeilBrown   fs/locks: always ...
2089
  	locks_delete_block(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2090
2091
  	return error;
  }
29d01b22e   Jeff Layton   locks: new helper...
2092
  /**
e55c34a66   Benjamin Coddington   locks: introduce ...
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
   * 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   Linus Torvalds   Linux-2.6.12-rc2
2117
2118
2119
2120
2121
   *	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   Mauro Carvalho Chehab   fs: locks: Fix so...
2122
   *	The @cmd can be one of:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
   *
80b79dd0e   Mauro Carvalho Chehab   fs: locks: Fix so...
2124
2125
2126
2127
2128
   *	- %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   Linus Torvalds   Linux-2.6.12-rc2
2129
2130
2131
2132
   *
   *	%LOCK_MAND can be combined with %LOCK_READ or %LOCK_WRITE to allow other
   *	processes read and write access respectively.
   */
002c8976e   Heiko Carstens   [CVE-2009-0029] S...
2133
  SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
  {
2903ff019   Al Viro   switch simple cas...
2135
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2136
2137
2138
2139
2140
  	struct file_lock *lock;
  	int can_sleep, unlock;
  	int error;
  
  	error = -EBADF;
2903ff019   Al Viro   switch simple cas...
2141
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2142
2143
2144
2145
2146
  		goto out;
  
  	can_sleep = !(cmd & LOCK_NB);
  	cmd &= ~LOCK_NB;
  	unlock = (cmd == LOCK_UN);
aeb5d7270   Al Viro   [PATCH] introduce...
2147
  	if (!unlock && !(cmd & LOCK_MAND) &&
2903ff019   Al Viro   switch simple cas...
2148
  	    !(f.file->f_mode & (FMODE_READ|FMODE_WRITE)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2149
  		goto out_putf;
d6367d624   NeilBrown   fs/locks: use pro...
2150
  	lock = flock_make_lock(f.file, cmd, NULL);
6e129d006   Jeff Layton   locks: flock_make...
2151
2152
  	if (IS_ERR(lock)) {
  		error = PTR_ERR(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2153
  		goto out_putf;
6e129d006   Jeff Layton   locks: flock_make...
2154
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2155
2156
  	if (can_sleep)
  		lock->fl_flags |= FL_SLEEP;
2903ff019   Al Viro   switch simple cas...
2157
  	error = security_file_lock(f.file, lock->fl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2158
2159
  	if (error)
  		goto out_free;
de2a4a501   Miklos Szeredi   Partially revert ...
2160
  	if (f.file->f_op->flock)
2903ff019   Al Viro   switch simple cas...
2161
  		error = f.file->f_op->flock(f.file,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2162
2163
2164
  					  (can_sleep) ? F_SETLKW : F_SETLK,
  					  lock);
  	else
4f6563677   Benjamin Coddington   Move locks API us...
2165
  		error = locks_lock_file_wait(f.file, lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166
2167
  
   out_free:
993dfa877   Trond Myklebust   [PATCH] fs/locks....
2168
  	locks_free_lock(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169
2170
  
   out_putf:
2903ff019   Al Viro   switch simple cas...
2171
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2172
2173
2174
   out:
  	return error;
  }
3ee17abd1   J. Bruce Fields   locks: factor out...
2175
2176
2177
  /**
   * vfs_test_lock - test file byte range lock
   * @filp: The file to test lock for
6924c5549   J. Bruce Fields   locks: fix vfs_te...
2178
   * @fl: The lock to test; also used to hold result
3ee17abd1   J. Bruce Fields   locks: factor out...
2179
2180
2181
2182
2183
2184
   *
   * 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   Miklos Szeredi   Partially revert ...
2185
  	if (filp->f_op->lock)
3ee17abd1   J. Bruce Fields   locks: factor out...
2186
2187
2188
2189
2190
  		return filp->f_op->lock(filp, F_GETLK, fl);
  	posix_test_lock(filp, fl);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(vfs_test_lock);
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
  /**
   * 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   Konstantin Khorenko   fs/lock: skip loc...
2207
2208
2209
2210
2211
2212
2213
  	/*
  	 * 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   Benjamin Coddington   fs/locks: Remove ...
2214
2215
2216
2217
2218
2219
2220
  
  	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   J. Bruce Fields   locks: create pos...
2221
2222
  static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
  {
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
2223
  	flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current));
c2fa1b8a6   J. Bruce Fields   locks: create pos...
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
  #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   J. Bruce Fields   locks: fix F_GETL...
2238
  	flock->l_type = fl->fl_type;
c2fa1b8a6   J. Bruce Fields   locks: create pos...
2239
2240
2241
2242
2243
2244
  	return 0;
  }
  
  #if BITS_PER_LONG == 32
  static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
  {
9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
2245
  	flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current));
c2fa1b8a6   J. Bruce Fields   locks: create pos...
2246
2247
2248
2249
2250
2251
2252
  	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   Linus Torvalds   Linux-2.6.12-rc2
2253
2254
2255
  /* Report the first existing lock that would conflict with l.
   * This implements the F_GETLK command of fcntl().
   */
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2256
  int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2257
  {
52306e882   Benjamin Coddington   fs/locks: Use all...
2258
  	struct file_lock *fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2259
  	int error;
52306e882   Benjamin Coddington   fs/locks: Use all...
2260
2261
2262
  	fl = locks_alloc_lock();
  	if (fl == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
  	error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2264
  	if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2265
  		goto out;
52306e882   Benjamin Coddington   fs/locks: Use all...
2266
  	error = flock_to_posix_lock(filp, fl, flock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2267
2268
  	if (error)
  		goto out;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2269
  	if (cmd == F_OFD_GETLK) {
90478939d   Jeff Layton   locks: require th...
2270
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2271
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2272
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2273
  		cmd = F_GETLK;
52306e882   Benjamin Coddington   fs/locks: Use all...
2274
2275
  		fl->fl_flags |= FL_OFDLCK;
  		fl->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2276
  	}
52306e882   Benjamin Coddington   fs/locks: Use all...
2277
  	error = vfs_test_lock(filp, fl);
3ee17abd1   J. Bruce Fields   locks: factor out...
2278
2279
  	if (error)
  		goto out;
7bbd1fc0e   NeilBrown   fs/locks: remove ...
2280

52306e882   Benjamin Coddington   fs/locks: Use all...
2281
2282
2283
  	flock->l_type = fl->fl_type;
  	if (fl->fl_type != F_UNLCK) {
  		error = posix_lock_to_flock(flock, fl);
c2fa1b8a6   J. Bruce Fields   locks: create pos...
2284
  		if (error)
52306e882   Benjamin Coddington   fs/locks: Use all...
2285
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2286
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
  out:
52306e882   Benjamin Coddington   fs/locks: Use all...
2288
  	locks_free_lock(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2289
2290
  	return error;
  }
7723ec977   Marc Eshel   locks: factor out...
2291
2292
2293
2294
2295
  /**
   * 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   Marc Eshel   locks: allow {vfs...
2296
2297
2298
2299
2300
2301
2302
2303
   * @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   Marc Eshel   locks: add fl_gra...
2304
2305
2306
2307
   *
   * 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   J. Bruce Fields   locks: rename loc...
2308
   * lm_grant is set. Callers expecting ->lock() to return asynchronously
2beb6614f   Marc Eshel   locks: add fl_gra...
2309
2310
   * 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   J. Bruce Fields   locks: rename loc...
2311
   * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
2beb6614f   Marc Eshel   locks: add fl_gra...
2312
2313
   * request completes.
   * If the request is for non-blocking lock the file system should return
bde74e4bc   Miklos Szeredi   locks: add specia...
2314
2315
   * 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   Marc Eshel   locks: add fl_gra...
2316
2317
2318
2319
2320
   * 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   J. Bruce Fields   locks: rename loc...
2321
   * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
2beb6614f   Marc Eshel   locks: add fl_gra...
2322
   * return code.
7723ec977   Marc Eshel   locks: factor out...
2323
   */
150b39345   Marc Eshel   locks: allow {vfs...
2324
  int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
7723ec977   Marc Eshel   locks: factor out...
2325
  {
de2a4a501   Miklos Szeredi   Partially revert ...
2326
  	if (filp->f_op->lock)
7723ec977   Marc Eshel   locks: factor out...
2327
2328
  		return filp->f_op->lock(filp, cmd, fl);
  	else
150b39345   Marc Eshel   locks: allow {vfs...
2329
  		return posix_lock_file(filp, fl, conf);
7723ec977   Marc Eshel   locks: factor out...
2330
2331
  }
  EXPORT_SYMBOL_GPL(vfs_lock_file);
b648a6de0   Miklos Szeredi   locks: cleanup co...
2332
2333
2334
2335
2336
2337
2338
2339
  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   Miklos Szeredi   locks: allow ->lo...
2340
2341
2342
  	for (;;) {
  		error = vfs_lock_file(filp, cmd, fl, NULL);
  		if (error != FILE_LOCK_DEFERRED)
b648a6de0   Miklos Szeredi   locks: cleanup co...
2343
  			break;
dcf23ac3e   Linus Torvalds   locks: reinstate ...
2344
2345
  		error = wait_event_interruptible(fl->fl_wait,
  					list_empty(&fl->fl_blocked_member));
16306a61d   NeilBrown   fs/locks: always ...
2346
2347
  		if (error)
  			break;
b648a6de0   Miklos Szeredi   locks: cleanup co...
2348
  	}
16306a61d   NeilBrown   fs/locks: always ...
2349
  	locks_delete_block(fl);
b648a6de0   Miklos Szeredi   locks: cleanup co...
2350
2351
2352
  
  	return error;
  }
6ca7d9101   Benjamin Coddington   locks: Use more f...
2353
  /* Ensure that fl->fl_file has compatible f_mode for F_SETLK calls */
cf01f4eef   Jeff Layton   locks: only valid...
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
  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   Linus Torvalds   Linux-2.6.12-rc2
2368
2369
2370
  /* Apply the lock described by l to an open file descriptor.
   * This implements both the F_SETLK and F_SETLKW commands of fcntl().
   */
c293621bb   Peter Staubach   [PATCH] stale POS...
2371
  int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2372
  		struct flock *flock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2373
2374
  {
  	struct file_lock *file_lock = locks_alloc_lock();
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2375
  	struct inode *inode = locks_inode(filp);
0b2bac2f1   Al Viro   [PATCH] fix SMP o...
2376
  	struct file *f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2377
2378
2379
2380
  	int error;
  
  	if (file_lock == NULL)
  		return -ENOLCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381
2382
2383
  	/* Don't allow mandatory locks on files that may be memory mapped
  	 * and shared.
  	 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2384
  	if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2385
2386
2387
  		error = -EAGAIN;
  		goto out;
  	}
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2388
  	error = flock_to_posix_lock(filp, file_lock, flock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2389
2390
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2391

cf01f4eef   Jeff Layton   locks: only valid...
2392
2393
2394
  	error = check_fmode_for_setlk(file_lock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2395
2396
  	/*
  	 * If the cmd is requesting file-private locks, then set the
cff2fce58   Jeff Layton   locks: rename FL_...
2397
  	 * FL_OFDLCK flag and override the owner.
5d50ffd7c   Jeff Layton   locks: add new fc...
2398
2399
  	 */
  	switch (cmd) {
0d3f7a2dd   Jeff Layton   locks: rename fil...
2400
  	case F_OFD_SETLK:
90478939d   Jeff Layton   locks: require th...
2401
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2402
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2403
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2404
  		cmd = F_SETLK;
cff2fce58   Jeff Layton   locks: rename FL_...
2405
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2406
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2407
  		break;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2408
  	case F_OFD_SETLKW:
90478939d   Jeff Layton   locks: require th...
2409
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2410
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2411
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2412
  		cmd = F_SETLKW;
cff2fce58   Jeff Layton   locks: rename FL_...
2413
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2414
  		file_lock->fl_owner = filp;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
2415
  		fallthrough;
5d50ffd7c   Jeff Layton   locks: add new fc...
2416
  	case F_SETLKW:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2417
2418
  		file_lock->fl_flags |= FL_SLEEP;
  	}
5d50ffd7c   Jeff Layton   locks: add new fc...
2419

b648a6de0   Miklos Szeredi   locks: cleanup co...
2420
  	error = do_lock_file_wait(filp, cmd, file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421

c293621bb   Peter Staubach   [PATCH] stale POS...
2422
  	/*
0752ba807   Jeff Layton   locks: don't chec...
2423
2424
2425
  	 * 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   Peter Staubach   [PATCH] stale POS...
2426
  	 */
0752ba807   Jeff Layton   locks: don't chec...
2427
2428
  	if (!error && file_lock->fl_type != F_UNLCK &&
  	    !(file_lock->fl_flags & FL_OFDLCK)) {
7f3697e24   Jeff Layton   locks: fix unlock...
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
  		/*
  		 * 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(&current->files->file_lock);
  		f = fcheck(fd);
  		spin_unlock(&current->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   Linus Torvalds   Linux-2.6.12-rc2
2443
  	}
c293621bb   Peter Staubach   [PATCH] stale POS...
2444
  out:
1890910fd   Jeff Layton   locks: sprinkle s...
2445
  	trace_fcntl_setlk(inode, file_lock, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
2447
2448
2449
2450
2451
2452
2453
  	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   Christoph Hellwig   fs/locks: pass ke...
2454
  int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2455
  {
52306e882   Benjamin Coddington   fs/locks: Use all...
2456
  	struct file_lock *fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2457
  	int error;
52306e882   Benjamin Coddington   fs/locks: Use all...
2458
2459
2460
  	fl = locks_alloc_lock();
  	if (fl == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2461
  	error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2462
  	if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2463
  		goto out;
52306e882   Benjamin Coddington   fs/locks: Use all...
2464
  	error = flock64_to_posix_lock(filp, fl, flock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2465
2466
  	if (error)
  		goto out;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2467
  	if (cmd == F_OFD_GETLK) {
90478939d   Jeff Layton   locks: require th...
2468
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2469
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2470
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2471
  		cmd = F_GETLK64;
52306e882   Benjamin Coddington   fs/locks: Use all...
2472
2473
  		fl->fl_flags |= FL_OFDLCK;
  		fl->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2474
  	}
52306e882   Benjamin Coddington   fs/locks: Use all...
2475
  	error = vfs_test_lock(filp, fl);
3ee17abd1   J. Bruce Fields   locks: factor out...
2476
2477
  	if (error)
  		goto out;
52306e882   Benjamin Coddington   fs/locks: Use all...
2478
2479
2480
  	flock->l_type = fl->fl_type;
  	if (fl->fl_type != F_UNLCK)
  		posix_lock_to_flock64(flock, fl);
f328296e2   Kinglong Mee   locks: Copy fl_lm...
2481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2482
  out:
52306e882   Benjamin Coddington   fs/locks: Use all...
2483
  	locks_free_lock(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2484
2485
2486
2487
2488
2489
  	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   Peter Staubach   [PATCH] stale POS...
2490
  int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2491
  		struct flock64 *flock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2492
2493
  {
  	struct file_lock *file_lock = locks_alloc_lock();
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2494
  	struct inode *inode = locks_inode(filp);
0b2bac2f1   Al Viro   [PATCH] fix SMP o...
2495
  	struct file *f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2496
2497
2498
2499
  	int error;
  
  	if (file_lock == NULL)
  		return -ENOLCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2500
2501
2502
  	/* Don't allow mandatory locks on files that may be memory mapped
  	 * and shared.
  	 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2503
  	if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2504
2505
2506
  		error = -EAGAIN;
  		goto out;
  	}
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2507
  	error = flock64_to_posix_lock(filp, file_lock, flock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2508
2509
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2510

cf01f4eef   Jeff Layton   locks: only valid...
2511
2512
2513
  	error = check_fmode_for_setlk(file_lock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2514
2515
  	/*
  	 * If the cmd is requesting file-private locks, then set the
cff2fce58   Jeff Layton   locks: rename FL_...
2516
  	 * FL_OFDLCK flag and override the owner.
5d50ffd7c   Jeff Layton   locks: add new fc...
2517
2518
  	 */
  	switch (cmd) {
0d3f7a2dd   Jeff Layton   locks: rename fil...
2519
  	case F_OFD_SETLK:
90478939d   Jeff Layton   locks: require th...
2520
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2521
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2522
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2523
  		cmd = F_SETLK64;
cff2fce58   Jeff Layton   locks: rename FL_...
2524
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2525
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2526
  		break;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2527
  	case F_OFD_SETLKW:
90478939d   Jeff Layton   locks: require th...
2528
  		error = -EINVAL;
a75d30c77   Christoph Hellwig   fs/locks: pass ke...
2529
  		if (flock->l_pid != 0)
90478939d   Jeff Layton   locks: require th...
2530
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2531
  		cmd = F_SETLKW64;
cff2fce58   Jeff Layton   locks: rename FL_...
2532
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2533
  		file_lock->fl_owner = filp;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
2534
  		fallthrough;
5d50ffd7c   Jeff Layton   locks: add new fc...
2535
  	case F_SETLKW64:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2536
2537
  		file_lock->fl_flags |= FL_SLEEP;
  	}
5d50ffd7c   Jeff Layton   locks: add new fc...
2538

b648a6de0   Miklos Szeredi   locks: cleanup co...
2539
  	error = do_lock_file_wait(filp, cmd, file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2540

c293621bb   Peter Staubach   [PATCH] stale POS...
2541
  	/*
0752ba807   Jeff Layton   locks: don't chec...
2542
2543
2544
  	 * 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   Peter Staubach   [PATCH] stale POS...
2545
  	 */
0752ba807   Jeff Layton   locks: don't chec...
2546
2547
  	if (!error && file_lock->fl_type != F_UNLCK &&
  	    !(file_lock->fl_flags & FL_OFDLCK)) {
7f3697e24   Jeff Layton   locks: fix unlock...
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
  		/*
  		 * 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(&current->files->file_lock);
  		f = fcheck(fd);
  		spin_unlock(&current->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   Linus Torvalds   Linux-2.6.12-rc2
2562
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
  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   Jeff Layton   locks: sprinkle s...
2576
  	int error;
c568d6834   Miklos Szeredi   locks: fix file l...
2577
  	struct inode *inode = locks_inode(filp);
ff7b86b82   Miklos Szeredi   [PATCH] locks: cl...
2578
  	struct file_lock lock;
128a37852   Dmitry Vyukov   fs: fix data race...
2579
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2580
2581
2582
2583
2584
2585
  
  	/*
  	 * 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   Miklos Szeredi   locks: fix file l...
2586
  	ctx =  smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
2587
  	if (!ctx || list_empty(&ctx->flc_posix))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2588
  		return;
d6367d624   NeilBrown   fs/locks: use pro...
2589
  	locks_init_lock(&lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2590
  	lock.fl_type = F_UNLCK;
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
2591
  	lock.fl_flags = FL_POSIX | FL_CLOSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2592
2593
2594
2595
2596
2597
2598
  	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   Jeff Layton   locks: sprinkle s...
2599
  	error = vfs_lock_file(filp, F_SETLK, &lock, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2600

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2601
2602
  	if (lock.fl_ops && lock.fl_ops->fl_release_private)
  		lock.fl_ops->fl_release_private(&lock);
c568d6834   Miklos Szeredi   locks: fix file l...
2603
  	trace_locks_remove_posix(inode, &lock, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2604
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2605
  EXPORT_SYMBOL(locks_remove_posix);
3d8e560de   Jeff Layton   locks: consolidat...
2606
  /* The i_flctx must be valid when calling into here */
dd459bb19   Jeff Layton   locks: have locks...
2607
  static void
128a37852   Dmitry Vyukov   fs: fix data race...
2608
  locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
dd459bb19   Jeff Layton   locks: have locks...
2609
  {
d6367d624   NeilBrown   fs/locks: use pro...
2610
  	struct file_lock fl;
c568d6834   Miklos Szeredi   locks: fix file l...
2611
  	struct inode *inode = locks_inode(filp);
dd459bb19   Jeff Layton   locks: have locks...
2612

3d8e560de   Jeff Layton   locks: consolidat...
2613
  	if (list_empty(&flctx->flc_flock))
dd459bb19   Jeff Layton   locks: have locks...
2614
  		return;
d6367d624   NeilBrown   fs/locks: use pro...
2615
2616
  	flock_make_lock(filp, LOCK_UN, &fl);
  	fl.fl_flags |= FL_CLOSE;
de2a4a501   Miklos Szeredi   Partially revert ...
2617
  	if (filp->f_op->flock)
dd459bb19   Jeff Layton   locks: have locks...
2618
2619
  		filp->f_op->flock(filp, F_SETLKW, &fl);
  	else
bcd7f78d0   Jeff Layton   locks: have flock...
2620
  		flock_lock_inode(inode, &fl);
dd459bb19   Jeff Layton   locks: have locks...
2621
2622
2623
2624
  
  	if (fl.fl_ops && fl.fl_ops->fl_release_private)
  		fl.fl_ops->fl_release_private(&fl);
  }
3d8e560de   Jeff Layton   locks: consolidat...
2625
  /* The i_flctx must be valid when calling into here */
8634b51f6   Jeff Layton   locks: convert le...
2626
  static void
128a37852   Dmitry Vyukov   fs: fix data race...
2627
  locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
8634b51f6   Jeff Layton   locks: convert le...
2628
  {
8634b51f6   Jeff Layton   locks: convert le...
2629
2630
  	struct file_lock *fl, *tmp;
  	LIST_HEAD(dispose);
3d8e560de   Jeff Layton   locks: consolidat...
2631
  	if (list_empty(&ctx->flc_lease))
8634b51f6   Jeff Layton   locks: convert le...
2632
  		return;
02e525b2a   Peter Zijlstra   locking/percpu-rw...
2633
  	percpu_down_read(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
2634
  	spin_lock(&ctx->flc_lock);
8634b51f6   Jeff Layton   locks: convert le...
2635
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list)
c4e136cda   Jeff Layton   locks: only remov...
2636
2637
  		if (filp == fl->fl_file)
  			lease_modify(fl, F_UNLCK, &dispose);
6109c8503   Jeff Layton   locks: add a dedi...
2638
  	spin_unlock(&ctx->flc_lock);
02e525b2a   Peter Zijlstra   locking/percpu-rw...
2639
  	percpu_up_read(&file_rwsem);
5f43086bb   Peter Zijlstra   locking, fs/locks...
2640

8634b51f6   Jeff Layton   locks: convert le...
2641
2642
  	locks_dispose_list(&dispose);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2643
2644
2645
  /*
   * This function is called on the last close of an open file.
   */
78ed8a133   Jeff Layton   locks: rename loc...
2646
  void locks_remove_file(struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2647
  {
128a37852   Dmitry Vyukov   fs: fix data race...
2648
  	struct file_lock_context *ctx;
c568d6834   Miklos Szeredi   locks: fix file l...
2649
  	ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
128a37852   Dmitry Vyukov   fs: fix data race...
2650
  	if (!ctx)
3d8e560de   Jeff Layton   locks: consolidat...
2651
  		return;
dd459bb19   Jeff Layton   locks: have locks...
2652
  	/* remove any OFD locks */
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2653
  	locks_remove_posix(filp, filp);
5d50ffd7c   Jeff Layton   locks: add new fc...
2654

dd459bb19   Jeff Layton   locks: have locks...
2655
  	/* remove flock locks */
128a37852   Dmitry Vyukov   fs: fix data race...
2656
  	locks_remove_flock(filp, ctx);
dd459bb19   Jeff Layton   locks: have locks...
2657

8634b51f6   Jeff Layton   locks: convert le...
2658
  	/* remove any leases */
128a37852   Dmitry Vyukov   fs: fix data race...
2659
  	locks_remove_lease(filp, ctx);
3953704fd   Benjamin Coddington   locks: restore a ...
2660
2661
2662
2663
2664
2665
  
  	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   Linus Torvalds   Linux-2.6.12-rc2
2666
2667
2668
  }
  
  /**
9b9d2ab41   Marc Eshel   locks: add lock c...
2669
2670
2671
2672
2673
2674
2675
2676
   * 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   Miklos Szeredi   Partially revert ...
2677
  	if (filp->f_op->lock)
9b9d2ab41   Marc Eshel   locks: add lock c...
2678
2679
2680
  		return filp->f_op->lock(filp, F_CANCELLK, fl);
  	return 0;
  }
9b9d2ab41   Marc Eshel   locks: add lock c...
2681
  EXPORT_SYMBOL_GPL(vfs_cancel_lock);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2682
  #ifdef CONFIG_PROC_FS
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2683
  #include <linux/proc_fs.h>
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2684
  #include <linux/seq_file.h>
7012b02a2   Jeff Layton   locks: move file_...
2685
2686
2687
2688
  struct locks_iterator {
  	int	li_cpu;
  	loff_t	li_pos;
  };
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2689
  static void lock_get_status(struct seq_file *f, struct file_lock *fl,
99dc82925   Jerome Marchand   procfs: fix numbe...
2690
  			    loff_t id, char *pfx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2691
2692
  {
  	struct inode *inode = NULL;
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2693
  	unsigned int fl_pid;
9d78edeae   Alexey Gladkov   proc: proc_pid_ns...
2694
  	struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)->i_sb);
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2695

9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
2696
2697
  	fl_pid = locks_translate_pid(fl, proc_pidns);
  	/*
1cf8e5de4   Konstantin Khorenko   fs/lock: show loc...
2698
2699
2700
  	 * 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   Benjamin Coddington   fs/locks: Remove ...
2701
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2702
2703
  
  	if (fl->fl_file != NULL)
c568d6834   Miklos Szeredi   locks: fix file l...
2704
  		inode = locks_inode(fl->fl_file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2705

99dc82925   Jerome Marchand   procfs: fix numbe...
2706
  	seq_printf(f, "%lld:%s ", id, pfx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2707
  	if (IS_POSIX(fl)) {
c918d42a2   Jeff Layton   locks: make /proc...
2708
  		if (fl->fl_flags & FL_ACCESS)
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2709
  			seq_puts(f, "ACCESS");
cff2fce58   Jeff Layton   locks: rename FL_...
2710
  		else if (IS_OFDLCK(fl))
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2711
  			seq_puts(f, "OFDLCK");
c918d42a2   Jeff Layton   locks: make /proc...
2712
  		else
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2713
  			seq_puts(f, "POSIX ");
c918d42a2   Jeff Layton   locks: make /proc...
2714
2715
  
  		seq_printf(f, " %s ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2716
  			     (inode == NULL) ? "*NOINODE*" :
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2717
  			     mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2718
2719
  	} else if (IS_FLOCK(fl)) {
  		if (fl->fl_type & LOCK_MAND) {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2720
  			seq_puts(f, "FLOCK  MSNFS     ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2721
  		} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2722
  			seq_puts(f, "FLOCK  ADVISORY  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2723
2724
  		}
  	} else if (IS_LEASE(fl)) {
8144f1f69   Jeff Layton   locks: show deleg...
2725
2726
2727
2728
  		if (fl->fl_flags & FL_DELEG)
  			seq_puts(f, "DELEG  ");
  		else
  			seq_puts(f, "LEASE  ");
ab83fa4b4   J. Bruce Fields   locks: minor leas...
2729
  		if (lease_breaking(fl))
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2730
  			seq_puts(f, "BREAKING  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2731
  		else if (fl->fl_file)
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2732
  			seq_puts(f, "ACTIVE    ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2733
  		else
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2734
  			seq_puts(f, "BREAKER   ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2735
  	} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2736
  		seq_puts(f, "UNKNOWN UNKNOWN  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2737
2738
  	}
  	if (fl->fl_type & LOCK_MAND) {
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2739
  		seq_printf(f, "%s ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2740
2741
2742
2743
  			       (fl->fl_type & LOCK_READ)
  			       ? (fl->fl_type & LOCK_WRITE) ? "RW   " : "READ "
  			       : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
  	} else {
43e4cb942   Pavel Begunkov   locks: Fix procfs...
2744
2745
2746
2747
  		int type = IS_LEASE(fl) ? target_leasetype(fl) : fl->fl_type;
  
  		seq_printf(f, "%s ", (type == F_WRLCK) ? "WRITE" :
  				     (type == F_RDLCK) ? "READ" : "UNLCK");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2748
2749
  	}
  	if (inode) {
3648888e9   Jeff Layton   locks: get rid of...
2750
  		/* userspace relies on this representation of dev_t */
98ca480a8   Amir Goldstein   locks: print unsi...
2751
  		seq_printf(f, "%d %02x:%02x:%lu ", fl_pid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2752
2753
  				MAJOR(inode->i_sb->s_dev),
  				MINOR(inode->i_sb->s_dev), inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2754
  	} else {
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2755
  		seq_printf(f, "%d <none>:0 ", fl_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2756
2757
2758
  	}
  	if (IS_POSIX(fl)) {
  		if (fl->fl_end == OFFSET_MAX)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2759
2760
  			seq_printf(f, "%Ld EOF
  ", fl->fl_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2761
  		else
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2762
2763
  			seq_printf(f, "%Ld %Ld
  ", fl->fl_start, fl->fl_end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2764
  	} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2765
2766
  		seq_puts(f, "0 EOF
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2767
2768
  	}
  }
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2769
  static int locks_show(struct seq_file *f, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2770
  {
7012b02a2   Jeff Layton   locks: move file_...
2771
  	struct locks_iterator *iter = f->private;
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2772
  	struct file_lock *fl, *bfl;
9d78edeae   Alexey Gladkov   proc: proc_pid_ns...
2773
  	struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2774

139ca04ee   Jeff Layton   locks: convert fl...
2775
  	fl = hlist_entry(v, struct file_lock, fl_link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2776

9d5b86ac1   Benjamin Coddington   fs/locks: Remove ...
2777
  	if (locks_translate_pid(fl, proc_pidns) == 0)
d67fd44f6   Nikolay Borisov   locks: Filter /pr...
2778
  		return 0;
7012b02a2   Jeff Layton   locks: move file_...
2779
  	lock_get_status(f, fl, iter->li_pos, "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2780

ada5c1da8   NeilBrown   fs/locks: rename ...
2781
  	list_for_each_entry(bfl, &fl->fl_blocked_requests, fl_blocked_member)
7012b02a2   Jeff Layton   locks: move file_...
2782
  		lock_get_status(f, bfl, iter->li_pos, " ->");
094f28252   Matthias Kaehlcke   fs/locks.c: use l...
2783

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2784
2785
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2786

6c8c90319   Andrey Vagin   proc: show locks ...
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
  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   Miklos Szeredi   locks: fix file l...
2810
  	struct inode *inode = locks_inode(filp);
6c8c90319   Andrey Vagin   proc: show locks ...
2811
2812
  	struct file_lock_context *ctx;
  	int id = 0;
128a37852   Dmitry Vyukov   fs: fix data race...
2813
  	ctx = smp_load_acquire(&inode->i_flctx);
6c8c90319   Andrey Vagin   proc: show locks ...
2814
2815
2816
2817
2818
2819
2820
2821
2822
  	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   Pavel Emelyanov   Rework /proc/lock...
2823
  static void *locks_start(struct seq_file *f, loff_t *pos)
b03dfdec0   Jeff Layton   locks: add __acqu...
2824
  	__acquires(&blocked_lock_lock)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2825
  {
7012b02a2   Jeff Layton   locks: move file_...
2826
  	struct locks_iterator *iter = f->private;
99dc82925   Jerome Marchand   procfs: fix numbe...
2827

7012b02a2   Jeff Layton   locks: move file_...
2828
  	iter->li_pos = *pos + 1;
aba376607   Peter Zijlstra   fs/locks: Replace...
2829
  	percpu_down_write(&file_rwsem);
7b2296afb   Jeff Layton   locks: give the b...
2830
  	spin_lock(&blocked_lock_lock);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
2831
  	return seq_hlist_start_percpu(&file_lock_list.hlist, &iter->li_cpu, *pos);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2832
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2833

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2834
2835
  static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
  {
7012b02a2   Jeff Layton   locks: move file_...
2836
2837
2838
  	struct locks_iterator *iter = f->private;
  
  	++iter->li_pos;
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
2839
  	return seq_hlist_next_percpu(v, &file_lock_list.hlist, &iter->li_cpu, pos);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2840
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2841

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2842
  static void locks_stop(struct seq_file *f, void *v)
b03dfdec0   Jeff Layton   locks: add __acqu...
2843
  	__releases(&blocked_lock_lock)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2844
  {
7b2296afb   Jeff Layton   locks: give the b...
2845
  	spin_unlock(&blocked_lock_lock);
aba376607   Peter Zijlstra   fs/locks: Replace...
2846
  	percpu_up_write(&file_rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2847
  }
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2848
  static const struct seq_operations locks_seq_operations = {
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2849
2850
2851
2852
2853
  	.start	= locks_start,
  	.next	= locks_next,
  	.stop	= locks_stop,
  	.show	= locks_show,
  };
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2854

d8ba7a363   Alexey Dobriyan   proc: move rest o...
2855
2856
  static int __init proc_locks_init(void)
  {
44414d82c   Christoph Hellwig   proc: introduce p...
2857
2858
  	proc_create_seq_private("locks", 0, NULL, &locks_seq_operations,
  			sizeof(struct locks_iterator), NULL);
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2859
2860
  	return 0;
  }
918992267   Paul Gortmaker   fs: make locks.c ...
2861
  fs_initcall(proc_locks_init);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2862
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2863
2864
  static int __init filelock_init(void)
  {
7012b02a2   Jeff Layton   locks: move file_...
2865
  	int i;
4a075e39c   Jeff Layton   locks: add a new ...
2866
2867
  	flctx_cache = kmem_cache_create("file_lock_ctx",
  			sizeof(struct file_lock_context), 0, SLAB_PANIC, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2868
  	filelock_cache = kmem_cache_create("file_lock_cache",
ee19cc406   Miklos Szeredi   fs: locks: remove...
2869
  			sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
2870
2871
2872
2873
2874
2875
  	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   Jeff Layton   locks: move file_...
2876

18f6622eb   Jeff Layton   locks: create a n...
2877
  	lease_notifier_chain_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2878
2879
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2880
  core_initcall(filelock_init);