Blame view

fs/locks.c 73.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  /*
   *  linux/fs/locks.c
   *
   *  Provide support for fcntl()'s F_GETLK, F_SETLK, and F_SETLKW calls.
   *  Doug Evans (dje@spiff.uucp), August 07, 1992
   *
   *  Deadlock detection added.
   *  FIXME: one thing isn't handled yet:
   *	- mandatory locks (requires lots of changes elsewhere)
   *  Kelly Carmichael (kelly@[142.24.8.65]), September 17, 1994.
   *
   *  Miscellaneous edits, and a total rewrite of posix_lock_file() code.
   *  Kai Petzke (wpp@marie.physik.tu-berlin.de), 1994
   *  
   *  Converted file_lock_table to a linked list from an array, which eliminates
   *  the limits on how many active file locks are open.
   *  Chad Page (pageone@netcom.com), November 27, 1994
   * 
   *  Removed dependency on file descriptors. dup()'ed file descriptors now
   *  get the same locks as the original file descriptors, and a close() on
   *  any file descriptor removes ALL the locks on the file for the current
   *  process. Since locks still depend on the process id, locks are inherited
   *  after an exec() but not after a fork(). This agrees with POSIX, and both
   *  BSD and SVR4 practice.
   *  Andy Walker (andy@lysaker.kvaerner.no), February 14, 1995
   *
   *  Scrapped free list which is redundant now that we allocate locks
   *  dynamically with kmalloc()/kfree().
   *  Andy Walker (andy@lysaker.kvaerner.no), February 21, 1995
   *
   *  Implemented two lock personalities - FL_FLOCK and FL_POSIX.
   *
   *  FL_POSIX locks are created with calls to fcntl() and lockf() through the
   *  fcntl() system call. They have the semantics described above.
   *
   *  FL_FLOCK locks are created with calls to flock(), through the flock()
   *  system call, which is new. Old C libraries implement flock() via fcntl()
   *  and will continue to use the old, broken implementation.
   *
   *  FL_FLOCK locks follow the 4.4 BSD flock() semantics. They are associated
   *  with a file pointer (filp). As a result they can be shared by a parent
   *  process and its children after a fork(). They are removed when the last
   *  file descriptor referring to the file pointer is closed (unless explicitly
   *  unlocked). 
   *
   *  FL_FLOCK locks never deadlock, an existing lock is always removed before
   *  upgrading from shared to exclusive (or vice versa). When this happens
   *  any processes blocked by the current lock are woken up and allowed to
   *  run before the new lock is applied.
   *  Andy Walker (andy@lysaker.kvaerner.no), June 09, 1995
   *
   *  Removed some race conditions in flock_lock_file(), marked other possible
   *  races. Just grep for FIXME to see them. 
   *  Dmitry Gorodchanin (pgmdsg@ibi.com), February 09, 1996.
   *
   *  Addressed Dmitry's concerns. Deadlock checking no longer recursive.
   *  Lock allocation changed to GFP_ATOMIC as we can't afford to sleep
   *  once we've checked for blocking and deadlocking.
   *  Andy Walker (andy@lysaker.kvaerner.no), April 03, 1996.
   *
   *  Initial implementation of mandatory locks. SunOS turned out to be
   *  a rotten model, so I implemented the "obvious" semantics.
395cf9691   Paul Bolle   doc: fix broken r...
63
   *  See 'Documentation/filesystems/mandatory-locking.txt' for details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
   *  Andy Walker (andy@lysaker.kvaerner.no), April 06, 1996.
   *
   *  Don't allow mandatory locks on mmap()'ed files. Added simple functions to
   *  check if a file has mandatory locks, used by mmap(), open() and creat() to
   *  see if system call should be rejected. Ref. HP-UX/SunOS/Solaris Reference
   *  Manual, Section 2.
   *  Andy Walker (andy@lysaker.kvaerner.no), April 09, 1996.
   *
   *  Tidied up block list handling. Added '/proc/locks' interface.
   *  Andy Walker (andy@lysaker.kvaerner.no), April 24, 1996.
   *
   *  Fixed deadlock condition for pathological code that mixes calls to
   *  flock() and fcntl().
   *  Andy Walker (andy@lysaker.kvaerner.no), April 29, 1996.
   *
   *  Allow only one type of locking scheme (FL_POSIX or FL_FLOCK) to be in use
   *  for a given file at a time. Changed the CONFIG_LOCK_MANDATORY scheme to
   *  guarantee sensible behaviour in the case where file system modules might
   *  be compiled with different options than the kernel itself.
   *  Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996.
   *
   *  Added a couple of missing wake_up() calls. Thanks to Thomas Meckel
   *  (Thomas.Meckel@mni.fh-giessen.de) for spotting this.
   *  Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996.
   *
   *  Changed FL_POSIX locks to use the block list in the same way as FL_FLOCK
   *  locks. Changed process synchronisation to avoid dereferencing locks that
   *  have already been freed.
   *  Andy Walker (andy@lysaker.kvaerner.no), Sep 21, 1996.
   *
   *  Made the block list a circular list to minimise searching in the list.
   *  Andy Walker (andy@lysaker.kvaerner.no), Sep 25, 1996.
   *
   *  Made mandatory locking a mount option. Default is not to allow mandatory
   *  locking.
   *  Andy Walker (andy@lysaker.kvaerner.no), Oct 04, 1996.
   *
   *  Some adaptations for NFS support.
   *  Olaf Kirch (okir@monad.swb.de), Dec 1996,
   *
   *  Fixed /proc/locks interface so that we can't overrun the buffer we are handed.
   *  Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997.
   *
   *  Use slab allocator instead of kmalloc/kfree.
   *  Use generic list implementation from <linux/list.h>.
   *  Sped up posix_locks_deadlock by only considering blocked locks.
   *  Matthew Wilcox <willy@debian.org>, March, 2000.
   *
   *  Leases and LOCK_MAND
   *  Matthew Wilcox <willy@debian.org>, June, 2000.
   *  Stephen Rothwell <sfr@canb.auug.org.au>, June, 2000.
   */
  
  #include <linux/capability.h>
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
119
  #include <linux/fdtable.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
  #include <linux/fs.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
  #include <linux/security.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  #include <linux/syscalls.h>
  #include <linux/time.h>
4fb3a5386   Dipankar Sarma   [PATCH] files: fi...
126
  #include <linux/rcupdate.h>
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
127
  #include <linux/pid_namespace.h>
48f741865   Jeff Layton   locks: turn the b...
128
  #include <linux/hashtable.h>
7012b02a2   Jeff Layton   locks: move file_...
129
  #include <linux/percpu.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130

62af4f1f7   Jeff Layton   locks: add some t...
131
132
  #define CREATE_TRACE_POINTS
  #include <trace/events/filelock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
  #include <asm/uaccess.h>
  
  #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...
137
  #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
cff2fce58   Jeff Layton   locks: rename FL_...
138
  #define IS_OFDLCK(fl)	(fl->fl_flags & FL_OFDLCK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

c568d6834   Miklos Szeredi   locks: fix file l...
140
141
142
143
  static inline bool is_remote_lock(struct file *filp)
  {
  	return likely(!(filp->f_path.dentry->d_sb->s_flags & MS_NOREMOTELOCK));
  }
ab83fa4b4   J. Bruce Fields   locks: minor leas...
144
145
  static bool lease_breaking(struct file_lock *fl)
  {
778fc546f   J. Bruce Fields   locks: fix tracki...
146
147
148
149
150
151
152
153
154
155
  	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...
156
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
  int leases_enable = 1;
  int lease_break_time = 45;
1c8c601a8   Jeff Layton   locks: protect mo...
159
  /*
7012b02a2   Jeff Layton   locks: move file_...
160
   * The global file_lock_list is only used for displaying /proc/locks, so we
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
161
162
163
164
165
   * 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...
166
   */
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
167
168
169
170
171
  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...
172
  DEFINE_STATIC_PERCPU_RWSEM(file_rwsem);
889746917   Jeff Layton   locks: encapsulat...
173

1c8c601a8   Jeff Layton   locks: protect mo...
174
  /*
48f741865   Jeff Layton   locks: turn the b...
175
   * The blocked_hash is used to find POSIX lock loops for deadlock detection.
7b2296afb   Jeff Layton   locks: give the b...
176
   * It is protected by blocked_lock_lock.
48f741865   Jeff Layton   locks: turn the b...
177
178
179
180
181
182
183
   *
   * 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...
184
   */
48f741865   Jeff Layton   locks: turn the b...
185
186
  #define BLOCKED_HASH_BITS	7
  static DEFINE_HASHTABLE(blocked_hash, BLOCKED_HASH_BITS);
889746917   Jeff Layton   locks: encapsulat...
187

1c8c601a8   Jeff Layton   locks: protect mo...
188
  /*
7b2296afb   Jeff Layton   locks: give the b...
189
190
   * 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...
191
192
193
194
195
196
   *
   * In addition, it also protects the fl->fl_block list, and the fl->fl_next
   * pointer for file_lock structures that are acting as lock requests (in
   * contrast to those that are acting as records of acquired locks).
   *
   * Note that when we acquire this lock in order to change the above fields,
6109c8503   Jeff Layton   locks: add a dedi...
197
   * we often hold the flc_lock as well. In certain cases, when reading the fields
1c8c601a8   Jeff Layton   locks: protect mo...
198
   * protected by this lock, we can skip acquiring it iff we already hold the
6109c8503   Jeff Layton   locks: add a dedi...
199
   * flc_lock.
1c8c601a8   Jeff Layton   locks: protect mo...
200
201
   *
   * In particular, adding an entry to the fl_block list requires that you hold
6109c8503   Jeff Layton   locks: add a dedi...
202
203
   * both the flc_lock and the blocked_lock_lock (acquired in that order).
   * Deleting an entry from the list however only requires the file_lock_lock.
1c8c601a8   Jeff Layton   locks: protect mo...
204
   */
7b2296afb   Jeff Layton   locks: give the b...
205
  static DEFINE_SPINLOCK(blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

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

4a075e39c   Jeff Layton   locks: add a new ...
210
  static struct file_lock_context *
5c1c669a1   Jeff Layton   locks: don't allo...
211
  locks_get_lock_context(struct inode *inode, int type)
4a075e39c   Jeff Layton   locks: add a new ...
212
  {
128a37852   Dmitry Vyukov   fs: fix data race...
213
  	struct file_lock_context *ctx;
4a075e39c   Jeff Layton   locks: add a new ...
214

128a37852   Dmitry Vyukov   fs: fix data race...
215
216
217
  	/* paired with cmpxchg() below */
  	ctx = smp_load_acquire(&inode->i_flctx);
  	if (likely(ctx) || type == F_UNLCK)
4a075e39c   Jeff Layton   locks: add a new ...
218
  		goto out;
128a37852   Dmitry Vyukov   fs: fix data race...
219
220
  	ctx = kmem_cache_alloc(flctx_cache, GFP_KERNEL);
  	if (!ctx)
4a075e39c   Jeff Layton   locks: add a new ...
221
  		goto out;
128a37852   Dmitry Vyukov   fs: fix data race...
222
223
224
225
  	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 ...
226
227
228
229
230
  
  	/*
  	 * 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...
231
232
233
234
  	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 ...
235
  out:
1890910fd   Jeff Layton   locks: sprinkle s...
236
  	trace_locks_get_lock_context(inode, type, ctx);
128a37852   Dmitry Vyukov   fs: fix data race...
237
  	return ctx;
4a075e39c   Jeff Layton   locks: add a new ...
238
  }
e24dadab0   Jeff Layton   locks: prink more...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  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");
  	}
  }
4a075e39c   Jeff Layton   locks: add a new ...
267
  void
f27a0fe08   Jeff Layton   locks: pass inode...
268
  locks_free_lock_context(struct inode *inode)
4a075e39c   Jeff Layton   locks: add a new ...
269
  {
f27a0fe08   Jeff Layton   locks: pass inode...
270
  	struct file_lock_context *ctx = inode->i_flctx;
e24dadab0   Jeff Layton   locks: prink more...
271
272
  	if (unlikely(ctx)) {
  		locks_check_ctx_lists(inode);
4a075e39c   Jeff Layton   locks: add a new ...
273
274
275
  		kmem_cache_free(flctx_cache, ctx);
  	}
  }
ee19cc406   Miklos Szeredi   fs: locks: remove...
276
  static void locks_init_lock_heads(struct file_lock *fl)
a51cb91d8   Miklos Szeredi   fs: fix lock init...
277
  {
139ca04ee   Jeff Layton   locks: convert fl...
278
  	INIT_HLIST_NODE(&fl->fl_link);
6dee60f69   Jeff Layton   locks: add new st...
279
  	INIT_LIST_HEAD(&fl->fl_list);
ee19cc406   Miklos Szeredi   fs: locks: remove...
280
281
  	INIT_LIST_HEAD(&fl->fl_block);
  	init_waitqueue_head(&fl->fl_wait);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
282
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  /* Allocate an empty lock structure. */
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
284
  struct file_lock *locks_alloc_lock(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  {
ee19cc406   Miklos Szeredi   fs: locks: remove...
286
  	struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
287
288
  
  	if (fl)
ee19cc406   Miklos Szeredi   fs: locks: remove...
289
  		locks_init_lock_heads(fl);
a51cb91d8   Miklos Szeredi   fs: fix lock init...
290
291
  
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  }
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
293
  EXPORT_SYMBOL_GPL(locks_alloc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294

a9e61e25f   Felix Blyakher   lockd: call locks...
295
  void locks_release_private(struct file_lock *fl)
47831f35b   Trond Myklebust   VFS: Fix __posix_...
296
297
298
299
300
301
  {
  	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_...
302

5c97d7b14   Kinglong Mee   locks: New ops in...
303
  	if (fl->fl_lmops) {
cae80b305   Jeff Layton   locks: change lm_...
304
305
306
307
  		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...
308
309
  		fl->fl_lmops = NULL;
  	}
47831f35b   Trond Myklebust   VFS: Fix __posix_...
310
  }
a9e61e25f   Felix Blyakher   lockd: call locks...
311
  EXPORT_SYMBOL_GPL(locks_release_private);
47831f35b   Trond Myklebust   VFS: Fix __posix_...
312

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  /* Free a lock which is not in use. */
05fa3135f   J. Bruce Fields   locks: fix setlea...
314
  void locks_free_lock(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  {
5ce29646e   Miklos Szeredi   [PATCH] locks: do...
316
  	BUG_ON(waitqueue_active(&fl->fl_wait));
6dee60f69   Jeff Layton   locks: add new st...
317
  	BUG_ON(!list_empty(&fl->fl_list));
5ce29646e   Miklos Szeredi   [PATCH] locks: do...
318
  	BUG_ON(!list_empty(&fl->fl_block));
139ca04ee   Jeff Layton   locks: convert fl...
319
  	BUG_ON(!hlist_unhashed(&fl->fl_link));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

47831f35b   Trond Myklebust   VFS: Fix __posix_...
321
  	locks_release_private(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  	kmem_cache_free(filelock_cache, fl);
  }
05fa3135f   J. Bruce Fields   locks: fix setlea...
324
  EXPORT_SYMBOL(locks_free_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325

ed9814d85   Jeff Layton   locks: defer free...
326
327
328
329
330
331
  static void
  locks_dispose_list(struct list_head *dispose)
  {
  	struct file_lock *fl;
  
  	while (!list_empty(dispose)) {
6dee60f69   Jeff Layton   locks: add new st...
332
333
  		fl = list_first_entry(dispose, struct file_lock, fl_list);
  		list_del_init(&fl->fl_list);
ed9814d85   Jeff Layton   locks: defer free...
334
335
336
  		locks_free_lock(fl);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
  void locks_init_lock(struct file_lock *fl)
  {
ee19cc406   Miklos Szeredi   fs: locks: remove...
339
340
  	memset(fl, 0, sizeof(struct file_lock));
  	locks_init_lock_heads(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
  }
  
  EXPORT_SYMBOL(locks_init_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
  /*
   * Initialize a new lock from an existing file_lock structure.
   */
3fe0fff18   Kinglong Mee   locks: Rename __l...
347
  void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
  {
  	new->fl_owner = fl->fl_owner;
  	new->fl_pid = fl->fl_pid;
0996905f9   Trond Myklebust   lockd: posix_test...
351
  	new->fl_file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
355
  	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...
356
  	new->fl_lmops = fl->fl_lmops;
0996905f9   Trond Myklebust   lockd: posix_test...
357
  	new->fl_ops = NULL;
f328296e2   Kinglong Mee   locks: Copy fl_lm...
358
359
360
  
  	if (fl->fl_lmops) {
  		if (fl->fl_lmops->lm_get_owner)
cae80b305   Jeff Layton   locks: change lm_...
361
  			fl->fl_lmops->lm_get_owner(fl->fl_owner);
f328296e2   Kinglong Mee   locks: Copy fl_lm...
362
  	}
0996905f9   Trond Myklebust   lockd: posix_test...
363
  }
3fe0fff18   Kinglong Mee   locks: Rename __l...
364
  EXPORT_SYMBOL(locks_copy_conflock);
0996905f9   Trond Myklebust   lockd: posix_test...
365
366
367
  
  void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
  {
566709bd6   Jeff Layton   locks: don't call...
368
369
  	/* "new" must be a freshly-initialized lock */
  	WARN_ON_ONCE(new->fl_ops);
0996905f9   Trond Myklebust   lockd: posix_test...
370

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

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

f328296e2   Kinglong Mee   locks: Copy fl_lm...
376
377
378
379
  	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
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
  }
  
  EXPORT_SYMBOL(locks_copy_lock);
  
  static inline int flock_translate_cmd(int cmd) {
  	if (cmd & LOCK_MAND)
  		return cmd & (LOCK_MAND | LOCK_RW);
  	switch (cmd) {
  	case LOCK_SH:
  		return F_RDLCK;
  	case LOCK_EX:
  		return F_WRLCK;
  	case LOCK_UN:
  		return F_UNLCK;
  	}
  	return -EINVAL;
  }
  
  /* Fill in a file_lock structure with an appropriate FLOCK lock. */
6e129d006   Jeff Layton   locks: flock_make...
399
400
  static struct file_lock *
  flock_make_lock(struct file *filp, unsigned int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
  {
  	struct file_lock *fl;
  	int type = flock_translate_cmd(cmd);
6e129d006   Jeff Layton   locks: flock_make...
404

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  	if (type < 0)
6e129d006   Jeff Layton   locks: flock_make...
406
  		return ERR_PTR(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
  	
  	fl = locks_alloc_lock();
  	if (fl == NULL)
6e129d006   Jeff Layton   locks: flock_make...
410
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
  
  	fl->fl_file = filp;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
413
  	fl->fl_owner = filp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
418
  	fl->fl_pid = current->tgid;
  	fl->fl_flags = FL_FLOCK;
  	fl->fl_type = type;
  	fl->fl_end = OFFSET_MAX;
  	
6e129d006   Jeff Layton   locks: flock_make...
419
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  }
0ec4f431e   J. Bruce Fields   locks: fix checki...
421
  static int assign_type(struct file_lock *fl, long type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
425
426
427
428
429
430
431
432
433
  {
  	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 ...
434
435
  static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
  				 struct flock64 *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  	switch (l->l_whence) {
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
438
  	case SEEK_SET:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
439
  		fl->fl_start = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  		break;
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
441
  	case SEEK_CUR:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
442
  		fl->fl_start = filp->f_pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  		break;
f5579f8c7   Josef 'Jeff' Sipek   [PATCH] VFS: Use ...
444
  	case SEEK_END:
ef12e72a0   J. Bruce Fields   locks: fix posix ...
445
  		fl->fl_start = i_size_read(file_inode(filp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
  		break;
  	default:
  		return -EINVAL;
  	}
ef12e72a0   J. Bruce Fields   locks: fix posix ...
450
451
452
453
454
  	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
455
456
457
  
  	/* POSIX-1996 leaves the case l->l_len < 0 undefined;
  	   POSIX-2001 defines it. */
4c780a468   Trond Myklebust   Fix Connectathon ...
458
  	if (l->l_len > 0) {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
459
460
461
  		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 ...
462
  	} else if (l->l_len < 0) {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
463
  		if (fl->fl_start + l->l_len < 0)
4c780a468   Trond Myklebust   Fix Connectathon ...
464
  			return -EINVAL;
ef12e72a0   J. Bruce Fields   locks: fix posix ...
465
466
467
468
  		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
469
470
471
472
473
474
475
476
477
  	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 ...
478
479
480
481
482
  /* 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
483
  {
ef12e72a0   J. Bruce Fields   locks: fix posix ...
484
485
486
487
488
489
490
491
  	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
492
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
  
  /* default lease lock manager operations */
4d01b7f5e   Jeff Layton   locks: give lm_br...
495
496
  static bool
  lease_break_callback(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
  {
  	kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
4d01b7f5e   Jeff Layton   locks: give lm_br...
499
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  }
1c7dd2ff4   Jeff Layton   locks: define a l...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  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;
  
  	__f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
  }
7b021967c   Alexey Dobriyan   const: make lock_...
517
  static const struct lock_manager_operations lease_manager_ops = {
8fb47a4fb   J. Bruce Fields   locks: rename loc...
518
  	.lm_break = lease_break_callback,
8fb47a4fb   J. Bruce Fields   locks: rename loc...
519
  	.lm_change = lease_modify,
1c7dd2ff4   Jeff Layton   locks: define a l...
520
  	.lm_setup = lease_setup,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
  };
  
  /*
   * Initialize a lease, use the default lock manager operations
   */
0ec4f431e   J. Bruce Fields   locks: fix checki...
526
  static int lease_init(struct file *filp, long type, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
   {
75dff55af   Trond Myklebust   [PATCH] fs/locks....
528
529
  	if (assign_type(fl, type) != 0)
  		return -EINVAL;
7ca76311f   Jeff Layton   locks: set fl_own...
530
  	fl->fl_owner = filp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
534
  	fl->fl_pid = current->tgid;
  
  	fl->fl_file = filp;
  	fl->fl_flags = FL_LEASE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
542
  	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...
543
  static struct file_lock *lease_alloc(struct file *filp, long type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  {
  	struct file_lock *fl = locks_alloc_lock();
75dff55af   Trond Myklebust   [PATCH] fs/locks....
546
  	int error = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  
  	if (fl == NULL)
e32b8ee27   J. Bruce Fields   locks: clean up l...
549
  		return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  
  	error = lease_init(filp, type, fl);
75dff55af   Trond Myklebust   [PATCH] fs/locks....
552
553
  	if (error) {
  		locks_free_lock(fl);
e32b8ee27   J. Bruce Fields   locks: clean up l...
554
  		return ERR_PTR(error);
75dff55af   Trond Myklebust   [PATCH] fs/locks....
555
  	}
e32b8ee27   J. Bruce Fields   locks: clean up l...
556
  	return fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
564
565
566
567
568
569
  }
  
  /* 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...
570
  static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  {
8fb47a4fb   J. Bruce Fields   locks: rename loc...
572
  	if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  		return fl2->fl_lmops == fl1->fl_lmops &&
8fb47a4fb   J. Bruce Fields   locks: rename loc...
574
  			fl1->fl_lmops->lm_compare_owner(fl1, fl2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
  	return fl1->fl_owner == fl2->fl_owner;
  }
6109c8503   Jeff Layton   locks: add a dedi...
577
  /* Must be called with the flc_lock held! */
6ca10ed8e   Jeff Layton   locks: remove "in...
578
  static void locks_insert_global_locks(struct file_lock *fl)
889746917   Jeff Layton   locks: encapsulat...
579
  {
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
580
  	struct file_lock_list_struct *fll = this_cpu_ptr(&file_lock_list);
aba376607   Peter Zijlstra   fs/locks: Replace...
581
  	percpu_rwsem_assert_held(&file_rwsem);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
582
  	spin_lock(&fll->lock);
7012b02a2   Jeff Layton   locks: move file_...
583
  	fl->fl_link_cpu = smp_processor_id();
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
584
585
  	hlist_add_head(&fl->fl_link, &fll->hlist);
  	spin_unlock(&fll->lock);
889746917   Jeff Layton   locks: encapsulat...
586
  }
6109c8503   Jeff Layton   locks: add a dedi...
587
  /* Must be called with the flc_lock held! */
6ca10ed8e   Jeff Layton   locks: remove "in...
588
  static void locks_delete_global_locks(struct file_lock *fl)
889746917   Jeff Layton   locks: encapsulat...
589
  {
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
590
  	struct file_lock_list_struct *fll;
aba376607   Peter Zijlstra   fs/locks: Replace...
591
  	percpu_rwsem_assert_held(&file_rwsem);
7012b02a2   Jeff Layton   locks: move file_...
592
593
  	/*
  	 * Avoid taking lock if already unhashed. This is safe since this check
6109c8503   Jeff Layton   locks: add a dedi...
594
  	 * is done while holding the flc_lock, and new insertions into the list
7012b02a2   Jeff Layton   locks: move file_...
595
596
597
598
  	 * also require that it be held.
  	 */
  	if (hlist_unhashed(&fl->fl_link))
  		return;
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
599
600
601
  
  	fll = per_cpu_ptr(&file_lock_list, fl->fl_link_cpu);
  	spin_lock(&fll->lock);
139ca04ee   Jeff Layton   locks: convert fl...
602
  	hlist_del_init(&fl->fl_link);
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
603
  	spin_unlock(&fll->lock);
889746917   Jeff Layton   locks: encapsulat...
604
  }
3999e4936   Jeff Layton   locks: add a new ...
605
606
607
608
609
610
611
  static unsigned long
  posix_owner_key(struct file_lock *fl)
  {
  	if (fl->fl_lmops && fl->fl_lmops->lm_owner_key)
  		return fl->fl_lmops->lm_owner_key(fl);
  	return (unsigned long)fl->fl_owner;
  }
6ca10ed8e   Jeff Layton   locks: remove "in...
612
  static void locks_insert_global_blocked(struct file_lock *waiter)
889746917   Jeff Layton   locks: encapsulat...
613
  {
663d5af75   Daniel Wagner   locks: Add lockde...
614
  	lockdep_assert_held(&blocked_lock_lock);
3999e4936   Jeff Layton   locks: add a new ...
615
  	hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter));
889746917   Jeff Layton   locks: encapsulat...
616
  }
6ca10ed8e   Jeff Layton   locks: remove "in...
617
  static void locks_delete_global_blocked(struct file_lock *waiter)
889746917   Jeff Layton   locks: encapsulat...
618
  {
663d5af75   Daniel Wagner   locks: Add lockde...
619
  	lockdep_assert_held(&blocked_lock_lock);
48f741865   Jeff Layton   locks: turn the b...
620
  	hash_del(&waiter->fl_link);
889746917   Jeff Layton   locks: encapsulat...
621
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
  /* 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...
624
   *
7b2296afb   Jeff Layton   locks: give the b...
625
   * Must be called with blocked_lock_lock held.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
   */
33443c42f   Matt Mackall   [PATCH] tiny: Uni...
627
  static void __locks_delete_block(struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
  {
889746917   Jeff Layton   locks: encapsulat...
629
  	locks_delete_global_blocked(waiter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  	list_del_init(&waiter->fl_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
  	waiter->fl_next = NULL;
  }
1a9e64a71   Jeff Layton   cifs: use posix_u...
633
  static void locks_delete_block(struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  {
7b2296afb   Jeff Layton   locks: give the b...
635
  	spin_lock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  	__locks_delete_block(waiter);
7b2296afb   Jeff Layton   locks: give the b...
637
  	spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
  }
  
  /* 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...
644
   *
6109c8503   Jeff Layton   locks: add a dedi...
645
646
647
648
   * Must be called with both the flc_lock and blocked_lock_lock held. The
   * fl_block list itself is protected by the blocked_lock_lock, but by ensuring
   * that the flc_lock is also held on insertions we can avoid taking the
   * blocked_lock_lock in some cases when we see that the fl_block list is empty.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
   */
1c8c601a8   Jeff Layton   locks: protect mo...
650
651
  static void __locks_insert_block(struct file_lock *blocker,
  					struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  {
6dc0fe8f8   J. Bruce Fields   [PATCH] VFS,fs/lo...
653
  	BUG_ON(!list_empty(&waiter->fl_block));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  	waiter->fl_next = blocker;
889746917   Jeff Layton   locks: encapsulat...
655
  	list_add_tail(&waiter->fl_block, &blocker->fl_block);
cff2fce58   Jeff Layton   locks: rename FL_...
656
  	if (IS_POSIX(blocker) && !IS_OFDLCK(blocker))
1c8c601a8   Jeff Layton   locks: protect mo...
657
658
  		locks_insert_global_blocked(waiter);
  }
6109c8503   Jeff Layton   locks: add a dedi...
659
  /* Must be called with flc_lock held. */
1c8c601a8   Jeff Layton   locks: protect mo...
660
661
662
  static void locks_insert_block(struct file_lock *blocker,
  					struct file_lock *waiter)
  {
7b2296afb   Jeff Layton   locks: give the b...
663
  	spin_lock(&blocked_lock_lock);
1c8c601a8   Jeff Layton   locks: protect mo...
664
  	__locks_insert_block(blocker, waiter);
7b2296afb   Jeff Layton   locks: give the b...
665
  	spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  }
1cb360125   Jeff Layton   locks: comment cl...
667
668
669
  /*
   * Wake up processes blocked waiting for blocker.
   *
6109c8503   Jeff Layton   locks: add a dedi...
670
   * Must be called with the inode->flc_lock held!
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
   */
  static void locks_wake_up_blocks(struct file_lock *blocker)
  {
4e8c765d3   Jeff Layton   locks: avoid taki...
674
675
  	/*
  	 * Avoid taking global lock if list is empty. This is safe since new
6109c8503   Jeff Layton   locks: add a dedi...
676
677
678
  	 * blocked requests are only added to the list under the flc_lock, and
  	 * the flc_lock is always held here. Note that removal from the fl_block
  	 * list does not require the flc_lock, so we must recheck list_empty()
7b2296afb   Jeff Layton   locks: give the b...
679
  	 * after acquiring the blocked_lock_lock.
4e8c765d3   Jeff Layton   locks: avoid taki...
680
681
682
  	 */
  	if (list_empty(&blocker->fl_block))
  		return;
7b2296afb   Jeff Layton   locks: give the b...
683
  	spin_lock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
  	while (!list_empty(&blocker->fl_block)) {
f0c1cd0ea   Pavel Emelyanov   Use list_first_en...
685
686
687
  		struct file_lock *waiter;
  
  		waiter = list_first_entry(&blocker->fl_block,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
  				struct file_lock, fl_block);
  		__locks_delete_block(waiter);
8fb47a4fb   J. Bruce Fields   locks: rename loc...
690
691
  		if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
  			waiter->fl_lmops->lm_notify(waiter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
  		else
  			wake_up(&waiter->fl_wait);
  	}
7b2296afb   Jeff Layton   locks: give the b...
695
  	spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  }
5263e31e4   Jeff Layton   locks: move flock...
697
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
698
  locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
5263e31e4   Jeff Layton   locks: move flock...
699
700
701
702
703
  {
  	fl->fl_nspid = get_pid(task_tgid(current));
  	list_add_tail(&fl->fl_list, before);
  	locks_insert_global_locks(fl);
  }
8634b51f6   Jeff Layton   locks: convert le...
704
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
705
  locks_unlink_lock_ctx(struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  {
889746917   Jeff Layton   locks: encapsulat...
707
  	locks_delete_global_locks(fl);
8634b51f6   Jeff Layton   locks: convert le...
708
  	list_del_init(&fl->fl_list);
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
709
710
711
712
  	if (fl->fl_nspid) {
  		put_pid(fl->fl_nspid);
  		fl->fl_nspid = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
  	locks_wake_up_blocks(fl);
24cbe7845   Jeff Layton   locks: close pote...
714
  }
8634b51f6   Jeff Layton   locks: convert le...
715
  static void
e084c1bd4   Jeff Layton   Revert "locks: ke...
716
  locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
24cbe7845   Jeff Layton   locks: close pote...
717
  {
e084c1bd4   Jeff Layton   Revert "locks: ke...
718
  	locks_unlink_lock_ctx(fl);
ed9814d85   Jeff Layton   locks: defer free...
719
  	if (dispose)
6dee60f69   Jeff Layton   locks: add new st...
720
  		list_add(&fl->fl_list, dispose);
ed9814d85   Jeff Layton   locks: defer free...
721
722
  	else
  		locks_free_lock(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. Common functionality
   * checks for shared/exclusive status of overlapping locks.
   */
  static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
  {
  	if (sys_fl->fl_type == F_WRLCK)
  		return 1;
  	if (caller_fl->fl_type == F_WRLCK)
  		return 1;
  	return 0;
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific
   * checking before calling the locks_conflict().
   */
  static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
  {
  	/* POSIX locks owned by the same process do not conflict with
  	 * each other.
  	 */
9b8c86956   Jeff Layton   locks: remove ext...
745
  	if (posix_same_owner(caller_fl, sys_fl))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  		return (0);
  
  	/* Check whether they overlap */
  	if (!locks_overlap(caller_fl, sys_fl))
  		return 0;
  
  	return (locks_conflict(caller_fl, sys_fl));
  }
  
  /* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific
   * checking before calling the locks_conflict().
   */
  static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
  {
  	/* FLOCK locks referring to the same filp do not conflict with
  	 * each other.
  	 */
9b8c86956   Jeff Layton   locks: remove ext...
763
  	if (caller_fl->fl_file == sys_fl->fl_file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
769
  		return (0);
  	if ((caller_fl->fl_type & LOCK_MAND) || (sys_fl->fl_type & LOCK_MAND))
  		return 0;
  
  	return (locks_conflict(caller_fl, sys_fl));
  }
6d34ac199   J. Bruce Fields   locks: make posix...
770
  void
9d6a8c5c2   Marc Eshel   locks: give posix...
771
  posix_test_lock(struct file *filp, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
773
  {
  	struct file_lock *cfl;
bd61e0a9c   Jeff Layton   locks: convert po...
774
  	struct file_lock_context *ctx;
c568d6834   Miklos Szeredi   locks: fix file l...
775
  	struct inode *inode = locks_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776

128a37852   Dmitry Vyukov   fs: fix data race...
777
  	ctx = smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
778
779
780
781
  	if (!ctx || list_empty_careful(&ctx->flc_posix)) {
  		fl->fl_type = F_UNLCK;
  		return;
  	}
6109c8503   Jeff Layton   locks: add a dedi...
782
  	spin_lock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
783
784
785
786
787
788
789
  	list_for_each_entry(cfl, &ctx->flc_posix, fl_list) {
  		if (posix_locks_conflict(fl, cfl)) {
  			locks_copy_conflock(fl, cfl);
  			if (cfl->fl_nspid)
  				fl->fl_pid = pid_vnr(cfl->fl_nspid);
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  	}
bd61e0a9c   Jeff Layton   locks: convert po...
791
792
  	fl->fl_type = F_UNLCK;
  out:
6109c8503   Jeff Layton   locks: add a dedi...
793
  	spin_unlock(&ctx->flc_lock);
6d34ac199   J. Bruce Fields   locks: make posix...
794
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  EXPORT_SYMBOL(posix_test_lock);
b533184fc   J. Bruce Fields   locks: clarify po...
797
798
799
800
801
  /*
   * Deadlock detection:
   *
   * We attempt to detect deadlocks that are due purely to posix file
   * locks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
   *
b533184fc   J. Bruce Fields   locks: clarify po...
803
804
805
806
807
808
809
   * 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
810
   *
b533184fc   J. Bruce Fields   locks: clarify po...
811
812
813
   * 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...
814
   *
b533184fc   J. Bruce Fields   locks: clarify po...
815
816
817
   * 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...
818
   * To handle those cases, we just bail out after a few iterations.
57b65325f   Jeff Layton   locks: skip deadl...
819
   *
cff2fce58   Jeff Layton   locks: rename FL_...
820
   * For FL_OFDLCK locks, the owner is the filp, not the files_struct.
57b65325f   Jeff Layton   locks: skip deadl...
821
822
823
824
   * 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_...
825
   * In principle, we could do a more limited deadlock detection on FL_OFDLCK
57b65325f   Jeff Layton   locks: skip deadl...
826
827
   * 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
828
   */
97855b49b   J. Bruce Fields   locks: fix possib...
829
830
  
  #define MAX_DEADLK_ITERATIONS 10
b533184fc   J. Bruce Fields   locks: clarify po...
831
832
833
834
  /* 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 ...
835
  	hash_for_each_possible(blocked_hash, fl, fl_link, posix_owner_key(block_fl)) {
b533184fc   J. Bruce Fields   locks: clarify po...
836
837
838
839
840
  		if (posix_same_owner(fl, block_fl))
  			return fl->fl_next;
  	}
  	return NULL;
  }
7b2296afb   Jeff Layton   locks: give the b...
841
  /* Must be called with the blocked_lock_lock held! */
b0904e147   Adrian Bunk   [PATCH] fs/locks....
842
  static int posix_locks_deadlock(struct file_lock *caller_fl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
  				struct file_lock *block_fl)
  {
97855b49b   J. Bruce Fields   locks: fix possib...
845
  	int i = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846

663d5af75   Daniel Wagner   locks: Add lockde...
847
  	lockdep_assert_held(&blocked_lock_lock);
57b65325f   Jeff Layton   locks: skip deadl...
848
849
  	/*
  	 * This deadlock detector can't reasonably detect deadlocks with
cff2fce58   Jeff Layton   locks: rename FL_...
850
  	 * FL_OFDLCK locks, since they aren't owned by a process, per-se.
57b65325f   Jeff Layton   locks: skip deadl...
851
  	 */
cff2fce58   Jeff Layton   locks: rename FL_...
852
  	if (IS_OFDLCK(caller_fl))
57b65325f   Jeff Layton   locks: skip deadl...
853
  		return 0;
b533184fc   J. Bruce Fields   locks: clarify po...
854
855
856
857
858
  	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
859
860
861
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
  /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
02888f41e   J. Bruce Fields   locks: fix flock_...
863
   * after any leases, but before any posix locks.
f475ae957   Trond Myklebust   VFS: Allow caller...
864
865
866
867
   *
   * 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
868
   */
bcd7f78d0   Jeff Layton   locks: have flock...
869
  static int flock_lock_inode(struct inode *inode, struct file_lock *request)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  {
993dfa877   Trond Myklebust   [PATCH] fs/locks....
871
  	struct file_lock *new_fl = NULL;
5263e31e4   Jeff Layton   locks: move flock...
872
873
  	struct file_lock *fl;
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
  	int error = 0;
5263e31e4   Jeff Layton   locks: move flock...
875
  	bool found = false;
ed9814d85   Jeff Layton   locks: defer free...
876
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877

5c1c669a1   Jeff Layton   locks: don't allo...
878
879
880
881
882
883
  	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...
884

b89f43213   Arnd Bergmann   fs/locks.c: prepa...
885
  	if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
84d535ade   Pavel Emelyanov   Memory shortage c...
886
  		new_fl = locks_alloc_lock();
b89f43213   Arnd Bergmann   fs/locks.c: prepa...
887
888
  		if (!new_fl)
  			return -ENOMEM;
84d535ade   Pavel Emelyanov   Memory shortage c...
889
  	}
87709e28d   Peter Zijlstra   fs/locks: Use per...
890
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
891
  	spin_lock(&ctx->flc_lock);
b89f43213   Arnd Bergmann   fs/locks.c: prepa...
892
893
  	if (request->fl_flags & FL_ACCESS)
  		goto find_conflict;
5263e31e4   Jeff Layton   locks: move flock...
894
  	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
bcd7f78d0   Jeff Layton   locks: have flock...
895
  		if (request->fl_file != fl->fl_file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
  			continue;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
897
  		if (request->fl_type == fl->fl_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
  			goto out;
5263e31e4   Jeff Layton   locks: move flock...
899
  		found = true;
e084c1bd4   Jeff Layton   Revert "locks: ke...
900
  		locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

f475ae957   Trond Myklebust   VFS: Allow caller...
904
905
906
  	if (request->fl_type == F_UNLCK) {
  		if ((request->fl_flags & FL_EXISTS) && !found)
  			error = -ENOENT;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
907
  		goto out;
f475ae957   Trond Myklebust   VFS: Allow caller...
908
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909

f07f18dd6   Trond Myklebust   VFS: Add support ...
910
  find_conflict:
5263e31e4   Jeff Layton   locks: move flock...
911
  	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
993dfa877   Trond Myklebust   [PATCH] fs/locks....
912
  		if (!flock_locks_conflict(request, fl))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
  			continue;
  		error = -EAGAIN;
bde74e4bc   Miklos Szeredi   locks: add specia...
915
916
917
918
  		if (!(request->fl_flags & FL_SLEEP))
  			goto out;
  		error = FILE_LOCK_DEFERRED;
  		locks_insert_block(fl, request);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
  		goto out;
  	}
f07f18dd6   Trond Myklebust   VFS: Add support ...
921
922
  	if (request->fl_flags & FL_ACCESS)
  		goto out;
993dfa877   Trond Myklebust   [PATCH] fs/locks....
923
  	locks_copy_lock(new_fl, request);
e084c1bd4   Jeff Layton   Revert "locks: ke...
924
  	locks_insert_lock_ctx(new_fl, &ctx->flc_flock);
993dfa877   Trond Myklebust   [PATCH] fs/locks....
925
  	new_fl = NULL;
9cedc194a   Kirill Korotaev   [PATCH] Return er...
926
  	error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
  
  out:
6109c8503   Jeff Layton   locks: add a dedi...
929
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
930
  	percpu_up_read_preempt_enable(&file_rwsem);
993dfa877   Trond Myklebust   [PATCH] fs/locks....
931
932
  	if (new_fl)
  		locks_free_lock(new_fl);
ed9814d85   Jeff Layton   locks: defer free...
933
  	locks_dispose_list(&dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
  	return error;
  }
b4d629a39   Jeff Layton   locks: rename __p...
936
937
  static int posix_lock_inode(struct inode *inode, struct file_lock *request,
  			    struct file_lock *conflock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
  {
bd61e0a9c   Jeff Layton   locks: convert po...
939
  	struct file_lock *fl, *tmp;
39005d022   Miklos Szeredi   [PATCH] locks: do...
940
941
  	struct file_lock *new_fl = NULL;
  	struct file_lock *new_fl2 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
  	struct file_lock *left = NULL;
  	struct file_lock *right = NULL;
bd61e0a9c   Jeff Layton   locks: convert po...
944
  	struct file_lock_context *ctx;
b9746ef80   Jeff Layton   locks: make "adde...
945
946
  	int error;
  	bool added = false;
ed9814d85   Jeff Layton   locks: defer free...
947
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
955
  	/*
  	 * 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...
956
957
  	 *
  	 * In some cases we can be sure, that no new locks will be needed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  	 */
39005d022   Miklos Szeredi   [PATCH] locks: do...
959
960
961
962
963
964
  	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
965

87709e28d   Peter Zijlstra   fs/locks: Use per...
966
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
967
  	spin_lock(&ctx->flc_lock);
1cb360125   Jeff Layton   locks: comment cl...
968
969
970
  	/*
  	 * 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...
971
  	 * blocker's list of waiters and the global blocked_hash.
1cb360125   Jeff Layton   locks: comment cl...
972
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
  	if (request->fl_type != F_UNLCK) {
bd61e0a9c   Jeff Layton   locks: convert po...
974
  		list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  			if (!posix_locks_conflict(request, fl))
  				continue;
5842add2f   Andy Adamson   [PATCH] VFS,fs/lo...
977
  			if (conflock)
3fe0fff18   Kinglong Mee   locks: Rename __l...
978
  				locks_copy_conflock(conflock, fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
981
  			error = -EAGAIN;
  			if (!(request->fl_flags & FL_SLEEP))
  				goto out;
1c8c601a8   Jeff Layton   locks: protect mo...
982
983
984
985
  			/*
  			 * 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
986
  			error = -EDEADLK;
7b2296afb   Jeff Layton   locks: give the b...
987
  			spin_lock(&blocked_lock_lock);
1c8c601a8   Jeff Layton   locks: protect mo...
988
989
990
991
  			if (likely(!posix_locks_deadlock(request, fl))) {
  				error = FILE_LOCK_DEFERRED;
  				__locks_insert_block(fl, request);
  			}
7b2296afb   Jeff Layton   locks: give the b...
992
  			spin_unlock(&blocked_lock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
998
999
1000
  			goto out;
    		}
    	}
  
  	/* 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...
1001
1002
1003
1004
  	/* 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
1005
  	}
1cb360125   Jeff Layton   locks: comment cl...
1006
  	/* Process locks with this owner. */
bd61e0a9c   Jeff Layton   locks: convert po...
1007
1008
1009
1010
1011
  	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
1012
  		if (request->fl_type == fl->fl_type) {
449231d6d   Olaf Kirch   From: Olaf Kirch ...
1013
1014
1015
1016
  			/* 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
1017
  			if (fl->fl_end < request->fl_start - 1)
bd61e0a9c   Jeff Layton   locks: convert po...
1018
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
1021
  			/* 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 ...
1022
  			if (fl->fl_start - 1 > request->fl_end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  				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...
1039
  				locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
  				continue;
  			}
  			request = fl;
b9746ef80   Jeff Layton   locks: make "adde...
1043
  			added = true;
bd61e0a9c   Jeff Layton   locks: convert po...
1044
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
1048
  			/* Processing for different lock types is a bit
  			 * more complex.
  			 */
  			if (fl->fl_end < request->fl_start)
bd61e0a9c   Jeff Layton   locks: convert po...
1049
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
  			if (fl->fl_start > request->fl_end)
  				break;
  			if (request->fl_type == F_UNLCK)
b9746ef80   Jeff Layton   locks: make "adde...
1053
  				added = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  			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...
1068
  					locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1069
1070
  					continue;
  				}
b84d49f94   Jeff Layton   locks: don't reus...
1071
1072
1073
1074
1075
1076
  				/*
  				 * 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
1077
  				 */
b84d49f94   Jeff Layton   locks: don't reus...
1078
1079
1080
1081
1082
1083
  				error = -ENOLCK;
  				if (!new_fl)
  					goto out;
  				locks_copy_lock(new_fl, request);
  				request = new_fl;
  				new_fl = NULL;
e084c1bd4   Jeff Layton   Revert "locks: ke...
1084
1085
  				locks_insert_lock_ctx(request, &fl->fl_list);
  				locks_delete_lock_ctx(fl, &dispose);
b9746ef80   Jeff Layton   locks: make "adde...
1086
  				added = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  	}
0d9a490ab   Miklos Szeredi   [PATCH] locks: do...
1090
  	/*
1cb360125   Jeff Layton   locks: comment cl...
1091
1092
1093
  	 * 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...
1094
1095
1096
1097
  	 */
  	error = -ENOLCK; /* "no luck" */
  	if (right && left == right && !new_fl2)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
1099
  	error = 0;
  	if (!added) {
f475ae957   Trond Myklebust   VFS: Allow caller...
1100
1101
1102
  		if (request->fl_type == F_UNLCK) {
  			if (request->fl_flags & FL_EXISTS)
  				error = -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
  			goto out;
f475ae957   Trond Myklebust   VFS: Allow caller...
1104
  		}
0d9a490ab   Miklos Szeredi   [PATCH] locks: do...
1105
1106
1107
1108
1109
  
  		if (!new_fl) {
  			error = -ENOLCK;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
  		locks_copy_lock(new_fl, request);
e084c1bd4   Jeff Layton   Revert "locks: ke...
1111
  		locks_insert_lock_ctx(new_fl, &fl->fl_list);
2e2f756f8   Jeff Layton   locks: fix list i...
1112
  		fl = new_fl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
  		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...
1123
  			locks_insert_lock_ctx(left, &fl->fl_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
1125
1126
1127
1128
1129
1130
1131
1132
  		}
  		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...
1133
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
1134
  	percpu_up_read_preempt_enable(&file_rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
1137
1138
1139
1140
1141
  	/*
  	 * 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...
1142
  	locks_dispose_list(&dispose);
1890910fd   Jeff Layton   locks: sprinkle s...
1143
  	trace_posix_lock_inode(inode, request, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
1146
1147
1148
1149
1150
  	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...
1151
   * @conflock: Place to return a copy of the conflicting lock, if found.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
1154
1155
   *
   * 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...
1156
1157
1158
1159
   *
   * 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
1160
   */
150b39345   Marc Eshel   locks: allow {vfs...
1161
  int posix_lock_file(struct file *filp, struct file_lock *fl,
5842add2f   Andy Adamson   [PATCH] VFS,fs/lo...
1162
1163
  			struct file_lock *conflock)
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1164
  	return posix_lock_inode(locks_inode(filp), fl, conflock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
  }
150b39345   Marc Eshel   locks: allow {vfs...
1166
  EXPORT_SYMBOL(posix_lock_file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
1168
  
  /**
29d01b22e   Jeff Layton   locks: new helper...
1169
1170
   * 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
1171
1172
   * @fl: The lock to be applied
   *
616fb38fa   Benjamin Coddington   locks: cleanup po...
1173
   * Apply a POSIX style lock request to an inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
   */
616fb38fa   Benjamin Coddington   locks: cleanup po...
1175
  static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
1177
1178
1179
  {
  	int error;
  	might_sleep ();
  	for (;;) {
b4d629a39   Jeff Layton   locks: rename __p...
1180
  		error = posix_lock_inode(inode, fl, NULL);
bde74e4bc   Miklos Szeredi   locks: add specia...
1181
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
  			break;
  		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
  		if (!error)
  			continue;
  
  		locks_delete_block(fl);
  		break;
  	}
  	return error;
  }
29d01b22e   Jeff Layton   locks: new helper...
1192

9e8925b67   Jeff Layton   locks: Allow disa...
1193
  #ifdef CONFIG_MANDATORY_FILE_LOCKING
29d01b22e   Jeff Layton   locks: new helper...
1194
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
   * locks_mandatory_locked - Check for an active lock
d7a06983a   Jeff Layton   locks: fix locks_...
1196
   * @file: the file to check
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
1198
1199
1200
   *
   * 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_...
1201
  int locks_mandatory_locked(struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
  {
bd61e0a9c   Jeff Layton   locks: convert po...
1203
  	int ret;
c568d6834   Miklos Szeredi   locks: fix file l...
1204
  	struct inode *inode = locks_inode(file);
bd61e0a9c   Jeff Layton   locks: convert po...
1205
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
  	struct file_lock *fl;
128a37852   Dmitry Vyukov   fs: fix data race...
1207
  	ctx = smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
1208
1209
  	if (!ctx || list_empty_careful(&ctx->flc_posix))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
1212
  	/*
  	 * Search the lock list for this inode for any POSIX locks.
  	 */
6109c8503   Jeff Layton   locks: add a dedi...
1213
  	spin_lock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
1214
1215
  	ret = 0;
  	list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
1216
  		if (fl->fl_owner != current->files &&
bd61e0a9c   Jeff Layton   locks: convert po...
1217
1218
  		    fl->fl_owner != file) {
  			ret = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
  			break;
bd61e0a9c   Jeff Layton   locks: convert po...
1220
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
  	}
6109c8503   Jeff Layton   locks: add a dedi...
1222
  	spin_unlock(&ctx->flc_lock);
bd61e0a9c   Jeff Layton   locks: convert po...
1223
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
1226
1227
  }
  
  /**
   * locks_mandatory_area - Check for a conflicting lock
acc15575e   Christoph Hellwig   locks: new locks_...
1228
   * @inode:	the file to check
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
   * @filp:       how the file was opened (if it was)
acc15575e   Christoph Hellwig   locks: new locks_...
1230
1231
1232
   * @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
1233
1234
   *
   * Searches the inode's list of locks to find any POSIX locks which conflict.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
   */
acc15575e   Christoph Hellwig   locks: new locks_...
1236
1237
  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
1238
1239
1240
  {
  	struct file_lock fl;
  	int error;
29723adee   Jeff Layton   locks: make locks...
1241
  	bool sleep = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
1243
  
  	locks_init_lock(&fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
  	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...
1248
  		sleep = true;
acc15575e   Christoph Hellwig   locks: new locks_...
1249
1250
1251
  	fl.fl_type = type;
  	fl.fl_start = start;
  	fl.fl_end = end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
1253
  
  	for (;;) {
29723adee   Jeff Layton   locks: make locks...
1254
  		if (filp) {
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
1255
  			fl.fl_owner = filp;
29723adee   Jeff Layton   locks: make locks...
1256
  			fl.fl_flags &= ~FL_SLEEP;
b4d629a39   Jeff Layton   locks: rename __p...
1257
  			error = posix_lock_inode(inode, &fl, NULL);
29723adee   Jeff Layton   locks: make locks...
1258
1259
1260
1261
1262
1263
1264
  			if (!error)
  				break;
  		}
  
  		if (sleep)
  			fl.fl_flags |= FL_SLEEP;
  		fl.fl_owner = current->files;
b4d629a39   Jeff Layton   locks: rename __p...
1265
  		error = posix_lock_inode(inode, &fl, NULL);
bde74e4bc   Miklos Szeredi   locks: add specia...
1266
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
1270
1271
1272
1273
  			break;
  		error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
  		if (!error) {
  			/*
  			 * If we've been sleeping someone might have
  			 * changed the permissions behind our back.
  			 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
1274
  			if (__mandatory_lock(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  				continue;
  		}
  
  		locks_delete_block(&fl);
  		break;
  	}
  
  	return error;
  }
  
  EXPORT_SYMBOL(locks_mandatory_area);
9e8925b67   Jeff Layton   locks: Allow disa...
1286
  #endif /* CONFIG_MANDATORY_FILE_LOCKING */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287

778fc546f   J. Bruce Fields   locks: fix tracki...
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
  static void lease_clear_pending(struct file_lock *fl, int arg)
  {
  	switch (arg) {
  	case F_UNLCK:
  		fl->fl_flags &= ~FL_UNLOCK_PENDING;
  		/* fall through: */
  	case F_RDLCK:
  		fl->fl_flags &= ~FL_DOWNGRADE_PENDING;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
  /* We already had a lease on this file; just change its type */
7448cc37b   Jeff Layton   locks: clean up t...
1299
  int lease_modify(struct file_lock *fl, int arg, struct list_head *dispose)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
1302
1303
1304
  	int error = assign_type(fl, arg);
  
  	if (error)
  		return error;
778fc546f   J. Bruce Fields   locks: fix tracki...
1305
  	lease_clear_pending(fl, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
  	locks_wake_up_blocks(fl);
3b6e2723f   Filipe Brandenburger   locks: prevent si...
1307
1308
1309
1310
1311
  	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...
1312
1313
1314
1315
1316
1317
  		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...
1318
  		locks_delete_lock_ctx(fl, dispose);
3b6e2723f   Filipe Brandenburger   locks: prevent si...
1319
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  EXPORT_SYMBOL(lease_modify);
778fc546f   J. Bruce Fields   locks: fix tracki...
1323
1324
1325
1326
1327
1328
1329
  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...
1330
  static void time_out_leases(struct inode *inode, struct list_head *dispose)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
  {
8634b51f6   Jeff Layton   locks: convert le...
1332
1333
  	struct file_lock_context *ctx = inode->i_flctx;
  	struct file_lock *fl, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334

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

8634b51f6   Jeff Layton   locks: convert le...
1337
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
62af4f1f7   Jeff Layton   locks: add some t...
1338
  		trace_time_out_leases(inode, fl);
778fc546f   J. Bruce Fields   locks: fix tracki...
1339
  		if (past_time(fl->fl_downgrade_time))
7448cc37b   Jeff Layton   locks: clean up t...
1340
  			lease_modify(fl, F_RDLCK, dispose);
778fc546f   J. Bruce Fields   locks: fix tracki...
1341
  		if (past_time(fl->fl_break_time))
7448cc37b   Jeff Layton   locks: clean up t...
1342
  			lease_modify(fl, F_UNLCK, dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
  	}
  }
df4e8d2c1   J. Bruce Fields   locks: implement ...
1345
1346
  static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
  {
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1347
1348
  	if ((breaker->fl_flags & FL_LAYOUT) != (lease->fl_flags & FL_LAYOUT))
  		return false;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1349
1350
1351
1352
  	if ((breaker->fl_flags & FL_DELEG) && (lease->fl_flags & FL_LEASE))
  		return false;
  	return locks_conflict(breaker, lease);
  }
03d12ddf8   Jeff Layton   locks: __break_le...
1353
1354
1355
  static bool
  any_leases_conflict(struct inode *inode, struct file_lock *breaker)
  {
8634b51f6   Jeff Layton   locks: convert le...
1356
  	struct file_lock_context *ctx = inode->i_flctx;
03d12ddf8   Jeff Layton   locks: __break_le...
1357
  	struct file_lock *fl;
6109c8503   Jeff Layton   locks: add a dedi...
1358
  	lockdep_assert_held(&ctx->flc_lock);
03d12ddf8   Jeff Layton   locks: __break_le...
1359

8634b51f6   Jeff Layton   locks: convert le...
1360
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
03d12ddf8   Jeff Layton   locks: __break_le...
1361
1362
1363
1364
1365
  		if (leases_conflict(fl, breaker))
  			return true;
  	}
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
  /**
   *	__break_lease	-	revoke all outstanding leases on file
   *	@inode: the inode of the file to return
df4e8d2c1   J. Bruce Fields   locks: implement ...
1369
1370
1371
1372
   *	@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
1373
   *
87250dd26   david m. richter   leases: minor bre...
1374
1375
1376
   *	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
1377
1378
   *	specified %O_NONBLOCK to your open().
   */
df4e8d2c1   J. Bruce Fields   locks: implement ...
1379
  int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
  {
778fc546f   J. Bruce Fields   locks: fix tracki...
1381
  	int error = 0;
128a37852   Dmitry Vyukov   fs: fix data race...
1382
  	struct file_lock_context *ctx;
a901125c6   Yan, Zheng   locks: fix file_l...
1383
  	struct file_lock *new_fl, *fl, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
  	unsigned long break_time;
8737c9305   Al Viro   Switch may_open()...
1385
  	int want_write = (mode & O_ACCMODE) != O_RDONLY;
c45198eda   Jeff Layton   locks: move freei...
1386
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387

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

8634b51f6   Jeff Layton   locks: convert le...
1393
  	/* typically we will check that ctx is non-NULL before calling */
128a37852   Dmitry Vyukov   fs: fix data race...
1394
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1395
1396
1397
1398
  	if (!ctx) {
  		WARN_ON_ONCE(1);
  		return error;
  	}
87709e28d   Peter Zijlstra   fs/locks: Use per...
1399
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1400
  	spin_lock(&ctx->flc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401

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

03d12ddf8   Jeff Layton   locks: __break_le...
1404
  	if (!any_leases_conflict(inode, new_fl))
778fc546f   J. Bruce Fields   locks: fix tracki...
1405
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
1409
1410
1411
  	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...
1412
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
df4e8d2c1   J. Bruce Fields   locks: implement ...
1413
1414
  		if (!leases_conflict(fl, new_fl))
  			continue;
778fc546f   J. Bruce Fields   locks: fix tracki...
1415
1416
1417
1418
  		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
1419
  			fl->fl_break_time = break_time;
778fc546f   J. Bruce Fields   locks: fix tracki...
1420
  		} else {
8634b51f6   Jeff Layton   locks: convert le...
1421
  			if (lease_breaking(fl))
778fc546f   J. Bruce Fields   locks: fix tracki...
1422
1423
1424
  				continue;
  			fl->fl_flags |= FL_DOWNGRADE_PENDING;
  			fl->fl_downgrade_time = break_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
  		}
4d01b7f5e   Jeff Layton   locks: give lm_br...
1426
  		if (fl->fl_lmops->lm_break(fl))
e084c1bd4   Jeff Layton   Revert "locks: ke...
1427
  			locks_delete_lock_ctx(fl, &dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428
  	}
8634b51f6   Jeff Layton   locks: convert le...
1429
  	if (list_empty(&ctx->flc_lease))
4d01b7f5e   Jeff Layton   locks: give lm_br...
1430
  		goto out;
843c6b2f4   Jeff Layton   locks: remove i_h...
1431
  	if (mode & O_NONBLOCK) {
62af4f1f7   Jeff Layton   locks: add some t...
1432
  		trace_break_lease_noblock(inode, new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
1435
1436
1437
  		error = -EWOULDBLOCK;
  		goto out;
  	}
  
  restart:
8634b51f6   Jeff Layton   locks: convert le...
1438
1439
  	fl = list_first_entry(&ctx->flc_lease, struct file_lock, fl_list);
  	break_time = fl->fl_break_time;
f1c6bb2cb   Jeff Layton   locks: allow __br...
1440
  	if (break_time != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
  		break_time -= jiffies;
f1c6bb2cb   Jeff Layton   locks: allow __br...
1442
1443
  	if (break_time == 0)
  		break_time++;
8634b51f6   Jeff Layton   locks: convert le...
1444
  	locks_insert_block(fl, new_fl);
62af4f1f7   Jeff Layton   locks: add some t...
1445
  	trace_break_lease_block(inode, new_fl);
6109c8503   Jeff Layton   locks: add a dedi...
1446
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
1447
  	percpu_up_read_preempt_enable(&file_rwsem);
aba376607   Peter Zijlstra   fs/locks: Replace...
1448

c45198eda   Jeff Layton   locks: move freei...
1449
  	locks_dispose_list(&dispose);
4321e01e7   Matthew Wilcox   file locks: Use w...
1450
1451
  	error = wait_event_interruptible_timeout(new_fl->fl_wait,
  						!new_fl->fl_next, break_time);
aba376607   Peter Zijlstra   fs/locks: Replace...
1452

87709e28d   Peter Zijlstra   fs/locks: Use per...
1453
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1454
  	spin_lock(&ctx->flc_lock);
62af4f1f7   Jeff Layton   locks: add some t...
1455
  	trace_break_lease_unblock(inode, new_fl);
1c8c601a8   Jeff Layton   locks: protect mo...
1456
  	locks_delete_block(new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  	if (error >= 0) {
778fc546f   J. Bruce Fields   locks: fix tracki...
1458
1459
1460
1461
  		/*
  		 * Wait for the next conflicting lease that has not been
  		 * broken yet
  		 */
03d12ddf8   Jeff Layton   locks: __break_le...
1462
1463
1464
1465
  		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
1466
1467
  		error = 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
  out:
6109c8503   Jeff Layton   locks: add a dedi...
1469
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
1470
  	percpu_up_read_preempt_enable(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1471
  	locks_dispose_list(&dispose);
6d4b9e38d   Linus Torvalds   vfs: fix handling...
1472
  	locks_free_lock(new_fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
1474
1475
1476
1477
1478
  	return error;
  }
  
  EXPORT_SYMBOL(__break_lease);
  
  /**
a6b91919e   Randy Dunlap   fs: fix kernel-do...
1479
   *	lease_get_mtime - get the last modified time of an inode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
1482
1483
1484
   *	@inode: the inode
   *      @time:  pointer to a timespec which will contain the last modified time
   *
   * 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...
1485
   * exclusive lease, then they could be modifying it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
1487
1488
   */
  void lease_get_mtime(struct inode *inode, struct timespec *time)
  {
bfe860243   Jeff Layton   locks: close pote...
1489
  	bool has_lease = false;
128a37852   Dmitry Vyukov   fs: fix data race...
1490
  	struct file_lock_context *ctx;
8634b51f6   Jeff Layton   locks: convert le...
1491
  	struct file_lock *fl;
bfe860243   Jeff Layton   locks: close pote...
1492

128a37852   Dmitry Vyukov   fs: fix data race...
1493
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1494
  	if (ctx && !list_empty_careful(&ctx->flc_lease)) {
6109c8503   Jeff Layton   locks: add a dedi...
1495
  		spin_lock(&ctx->flc_lock);
8ace5dfb9   Geliang Tang   locks: use list_f...
1496
1497
1498
1499
  		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...
1500
  		spin_unlock(&ctx->flc_lock);
bfe860243   Jeff Layton   locks: close pote...
1501
1502
1503
  	}
  
  	if (has_lease)
c2050a454   Deepa Dinamani   fs: Replace curre...
1504
  		*time = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
  	else
  		*time = inode->i_mtime;
  }
  
  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...
1537
  	struct inode *inode = locks_inode(filp);
128a37852   Dmitry Vyukov   fs: fix data race...
1538
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539
  	int type = F_UNLCK;
c45198eda   Jeff Layton   locks: move freei...
1540
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541

128a37852   Dmitry Vyukov   fs: fix data race...
1542
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1543
  	if (ctx && !list_empty_careful(&ctx->flc_lease)) {
5f43086bb   Peter Zijlstra   locking, fs/locks...
1544
  		percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1545
  		spin_lock(&ctx->flc_lock);
c568d6834   Miklos Szeredi   locks: fix file l...
1546
  		time_out_leases(inode, &dispose);
8634b51f6   Jeff Layton   locks: convert le...
1547
1548
1549
  		list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
  			if (fl->fl_file != filp)
  				continue;
778fc546f   J. Bruce Fields   locks: fix tracki...
1550
  			type = target_leasetype(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
1552
  			break;
  		}
6109c8503   Jeff Layton   locks: add a dedi...
1553
  		spin_unlock(&ctx->flc_lock);
5f43086bb   Peter Zijlstra   locking, fs/locks...
1554
  		percpu_up_read_preempt_enable(&file_rwsem);
8634b51f6   Jeff Layton   locks: convert le...
1555
  		locks_dispose_list(&dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
1558
  	return type;
  }
24cbe7845   Jeff Layton   locks: close pote...
1559
1560
1561
1562
1563
1564
  /**
   * check_conflicting_open - see if the given dentry points to a file that has
   * 			    an existing open that would conflict with the
   * 			    desired lease.
   * @dentry:	dentry to check
   * @arg:	type of lease that we're trying to acquire
7fadc59cc   Randy Dunlap   fs: fix fs/locks....
1565
   * @flags:	current lock flags
24cbe7845   Jeff Layton   locks: close pote...
1566
1567
1568
1569
1570
   *
   * Check to see if there's an existing open fd on this file that would
   * conflict with the lease we're trying to set.
   */
  static int
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1571
  check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
24cbe7845   Jeff Layton   locks: close pote...
1572
1573
1574
  {
  	int ret = 0;
  	struct inode *inode = dentry->d_inode;
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1575
1576
  	if (flags & FL_LAYOUT)
  		return 0;
4d0c5ba2f   Miklos Szeredi   vfs: do get_write...
1577
1578
  	if ((arg == F_RDLCK) &&
  	    (atomic_read(&d_real_inode(dentry)->i_writecount) > 0))
24cbe7845   Jeff Layton   locks: close pote...
1579
1580
1581
1582
1583
1584
1585
1586
  		return -EAGAIN;
  
  	if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
  	    (atomic_read(&inode->i_count) > 1)))
  		ret = -EAGAIN;
  
  	return ret;
  }
e6f5c7893   Jeff Layton   locks: plumb a "p...
1587
1588
  static int
  generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  {
8634b51f6   Jeff Layton   locks: convert le...
1590
  	struct file_lock *fl, *my_fl = NULL, *lease;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
1591
  	struct dentry *dentry = filp->f_path.dentry;
c568d6834   Miklos Szeredi   locks: fix file l...
1592
  	struct inode *inode = dentry->d_inode;
8634b51f6   Jeff Layton   locks: convert le...
1593
  	struct file_lock_context *ctx;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1594
  	bool is_deleg = (*flp)->fl_flags & FL_DELEG;
c1f24ef4e   J. Bruce Fields   locks: setlease c...
1595
  	int error;
c45198eda   Jeff Layton   locks: move freei...
1596
  	LIST_HEAD(dispose);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597

096657b65   J. Bruce Fields   locks: fix leaks ...
1598
  	lease = *flp;
62af4f1f7   Jeff Layton   locks: add some t...
1599
  	trace_generic_add_lease(inode, lease);
5c1c669a1   Jeff Layton   locks: don't allo...
1600
1601
  	/* Note that arg is never F_UNLCK here */
  	ctx = locks_get_lock_context(inode, arg);
8634b51f6   Jeff Layton   locks: convert le...
1602
1603
  	if (!ctx)
  		return -ENOMEM;
df4e8d2c1   J. Bruce Fields   locks: implement ...
1604
1605
1606
1607
1608
1609
1610
1611
  	/*
  	 * 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_...
1612
  	if (is_deleg && !inode_trylock(inode))
df4e8d2c1   J. Bruce Fields   locks: implement ...
1613
1614
1615
1616
  		return -EAGAIN;
  
  	if (is_deleg && arg == F_WRLCK) {
  		/* Write delegations are not currently supported: */
5955102c9   Al Viro   wrappers for ->i_...
1617
  		inode_unlock(inode);
df4e8d2c1   J. Bruce Fields   locks: implement ...
1618
1619
1620
  		WARN_ON_ONCE(1);
  		return -EINVAL;
  	}
096657b65   J. Bruce Fields   locks: fix leaks ...
1621

87709e28d   Peter Zijlstra   fs/locks: Use per...
1622
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1623
  	spin_lock(&ctx->flc_lock);
c45198eda   Jeff Layton   locks: move freei...
1624
  	time_out_leases(inode, &dispose);
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1625
  	error = check_conflicting_open(dentry, arg, lease->fl_flags);
24cbe7845   Jeff Layton   locks: close pote...
1626
  	if (error)
096657b65   J. Bruce Fields   locks: fix leaks ...
1627
  		goto out;
6d5e8b05c   J. Bruce Fields   locks: share more...
1628

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
1631
1632
1633
1634
1635
1636
  	/*
  	 * 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...
1637
  	error = -EAGAIN;
8634b51f6   Jeff Layton   locks: convert le...
1638
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1639
1640
  		if (fl->fl_file == filp &&
  		    fl->fl_owner == lease->fl_owner) {
8634b51f6   Jeff Layton   locks: convert le...
1641
  			my_fl = fl;
c1f24ef4e   J. Bruce Fields   locks: setlease c...
1642
1643
  			continue;
  		}
8634b51f6   Jeff Layton   locks: convert le...
1644

c1f24ef4e   J. Bruce Fields   locks: setlease c...
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
  		/*
  		 * 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
1657
  	}
8634b51f6   Jeff Layton   locks: convert le...
1658
  	if (my_fl != NULL) {
0164bf023   Jeff Layton   locks: fix fasync...
1659
1660
  		lease = my_fl;
  		error = lease->fl_lmops->lm_change(lease, arg, &dispose);
1c7dd2ff4   Jeff Layton   locks: define a l...
1661
1662
1663
  		if (error)
  			goto out;
  		goto out_setup;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1665
1666
1667
  	error = -EINVAL;
  	if (!leases_enable)
  		goto out;
e084c1bd4   Jeff Layton   Revert "locks: ke...
1668
  	locks_insert_lock_ctx(lease, &ctx->flc_lease);
24cbe7845   Jeff Layton   locks: close pote...
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  	/*
  	 * The check in break_lease() is lockless. It's possible for another
  	 * open to race in after we did the earlier check for a conflicting
  	 * open but before the lease was inserted. Check again for a
  	 * conflicting open and cancel the lease if there is one.
  	 *
  	 * We also add a barrier here to ensure that the insertion of the lock
  	 * precedes these checks.
  	 */
  	smp_mb();
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1679
  	error = check_conflicting_open(dentry, arg, lease->fl_flags);
8634b51f6   Jeff Layton   locks: convert le...
1680
  	if (error) {
e084c1bd4   Jeff Layton   Revert "locks: ke...
1681
  		locks_unlink_lock_ctx(lease);
8634b51f6   Jeff Layton   locks: convert le...
1682
1683
  		goto out;
  	}
1c7dd2ff4   Jeff Layton   locks: define a l...
1684
1685
1686
1687
  
  out_setup:
  	if (lease->fl_lmops->lm_setup)
  		lease->fl_lmops->lm_setup(lease, priv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
  out:
6109c8503   Jeff Layton   locks: add a dedi...
1689
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
1690
  	percpu_up_read_preempt_enable(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1691
  	locks_dispose_list(&dispose);
df4e8d2c1   J. Bruce Fields   locks: implement ...
1692
  	if (is_deleg)
5955102c9   Al Viro   wrappers for ->i_...
1693
  		inode_unlock(inode);
8634b51f6   Jeff Layton   locks: convert le...
1694
  	if (!error && !my_fl)
1c7dd2ff4   Jeff Layton   locks: define a l...
1695
  		*flp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1696
1697
  	return error;
  }
8335ebd94   J. Bruce Fields   leases: split up ...
1698

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

128a37852   Dmitry Vyukov   fs: fix data race...
1707
  	ctx = smp_load_acquire(&inode->i_flctx);
8634b51f6   Jeff Layton   locks: convert le...
1708
1709
1710
1711
  	if (!ctx) {
  		trace_generic_delete_lease(inode, NULL);
  		return error;
  	}
87709e28d   Peter Zijlstra   fs/locks: Use per...
1712
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
1713
  	spin_lock(&ctx->flc_lock);
8634b51f6   Jeff Layton   locks: convert le...
1714
  	list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1715
1716
  		if (fl->fl_file == filp &&
  		    fl->fl_owner == owner) {
8634b51f6   Jeff Layton   locks: convert le...
1717
  			victim = fl;
0efaa7e82   Jeff Layton   locks: generic_de...
1718
  			break;
8634b51f6   Jeff Layton   locks: convert le...
1719
  		}
8335ebd94   J. Bruce Fields   leases: split up ...
1720
  	}
a9b1b455c   Jeff Layton   locks: fix generi...
1721
  	trace_generic_delete_lease(inode, victim);
8634b51f6   Jeff Layton   locks: convert le...
1722
  	if (victim)
7448cc37b   Jeff Layton   locks: clean up t...
1723
  		error = fl->fl_lmops->lm_change(victim, F_UNLCK, &dispose);
6109c8503   Jeff Layton   locks: add a dedi...
1724
  	spin_unlock(&ctx->flc_lock);
87709e28d   Peter Zijlstra   fs/locks: Use per...
1725
  	percpu_up_read_preempt_enable(&file_rwsem);
c45198eda   Jeff Layton   locks: move freei...
1726
  	locks_dispose_list(&dispose);
0efaa7e82   Jeff Layton   locks: generic_de...
1727
  	return error;
8335ebd94   J. Bruce Fields   leases: split up ...
1728
1729
1730
1731
  }
  
  /**
   *	generic_setlease	-	sets a lease on an open file
1c7dd2ff4   Jeff Layton   locks: define a l...
1732
1733
1734
1735
1736
   *	@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 ...
1737
1738
1739
   *
   *	The (input) flp->fl_lmops->lm_break function is required
   *	by break_lease().
8335ebd94   J. Bruce Fields   leases: split up ...
1740
   */
e6f5c7893   Jeff Layton   locks: plumb a "p...
1741
1742
  int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
  			void **priv)
8335ebd94   J. Bruce Fields   leases: split up ...
1743
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1744
  	struct inode *inode = locks_inode(filp);
8335ebd94   J. Bruce Fields   leases: split up ...
1745
  	int error;
8e96e3b7b   Eric W. Biederman   userns: Use uid_e...
1746
  	if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
8335ebd94   J. Bruce Fields   leases: split up ...
1747
1748
1749
1750
1751
1752
  		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 ...
1753
1754
  	switch (arg) {
  	case F_UNLCK:
2ab99ee12   Christoph Hellwig   fs: track fl_owne...
1755
  		return generic_delete_lease(filp, *priv);
8335ebd94   J. Bruce Fields   leases: split up ...
1756
1757
  	case F_RDLCK:
  	case F_WRLCK:
0efaa7e82   Jeff Layton   locks: generic_de...
1758
1759
1760
1761
  		if (!(*flp)->fl_lmops->lm_break) {
  			WARN_ON_ONCE(1);
  			return -ENOLCK;
  		}
11afe9f76   Christoph Hellwig   fs: add FL_LAYOUT...
1762

e6f5c7893   Jeff Layton   locks: plumb a "p...
1763
  		return generic_add_lease(filp, arg, flp, priv);
8335ebd94   J. Bruce Fields   leases: split up ...
1764
  	default:
8d657eb3b   Dave Jones   Remove easily use...
1765
  		return -EINVAL;
8335ebd94   J. Bruce Fields   leases: split up ...
1766
1767
  	}
  }
0af1a4504   Christoph Hellwig   rename setlease t...
1768
  EXPORT_SYMBOL(generic_setlease);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769

b89f43213   Arnd Bergmann   fs/locks.c: prepa...
1770
  /**
e51673aa5   Jeff Layton   locks: clean up v...
1771
   * vfs_setlease        -       sets a lease on an open file
1c7dd2ff4   Jeff Layton   locks: define a l...
1772
1773
1774
1775
1776
   * @filp:	file pointer
   * @arg:	type of lease to obtain
   * @lease:	file_lock to use when adding a lease
   * @priv:	private info for lm_setup when adding a lease (may be
   * 		NULL if lm_setup doesn't require it)
e51673aa5   Jeff Layton   locks: clean up v...
1777
1778
1779
1780
1781
1782
   *
   * 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
   * 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
   * stack trace).
1c7dd2ff4   Jeff Layton   locks: define a l...
1783
1784
1785
   *
   * 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
1786
   */
e6f5c7893   Jeff Layton   locks: plumb a "p...
1787
1788
  int
  vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1790
  	if (filp->f_op->setlease && is_remote_lock(filp))
f82b4b678   Jeff Layton   locks: move i_loc...
1791
  		return filp->f_op->setlease(filp, arg, lease, priv);
1c7dd2ff4   Jeff Layton   locks: define a l...
1792
  	else
f82b4b678   Jeff Layton   locks: move i_loc...
1793
  		return generic_setlease(filp, arg, lease, priv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
  }
a9933cea7   J. Bruce Fields   locks: rename lea...
1795
  EXPORT_SYMBOL_GPL(vfs_setlease);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796

0ceaf6c70   J. Bruce Fields   locks: prevent EN...
1797
  static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
  {
1c7dd2ff4   Jeff Layton   locks: define a l...
1799
  	struct file_lock *fl;
f7347ce4e   Linus Torvalds   fasync: re-organi...
1800
  	struct fasync_struct *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  	int error;
c5b1f0d92   Arnd Bergmann   locks/nfsd: alloc...
1802
1803
1804
  	fl = lease_alloc(filp, arg);
  	if (IS_ERR(fl))
  		return PTR_ERR(fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805

f7347ce4e   Linus Torvalds   fasync: re-organi...
1806
1807
1808
1809
1810
  	new = fasync_alloc();
  	if (!new) {
  		locks_free_lock(fl);
  		return -ENOMEM;
  	}
1c7dd2ff4   Jeff Layton   locks: define a l...
1811
  	new->fa_fd = fd;
f7347ce4e   Linus Torvalds   fasync: re-organi...
1812

1c7dd2ff4   Jeff Layton   locks: define a l...
1813
  	error = vfs_setlease(filp, arg, &fl, (void **)&new);
2dfb928f7   Jeff Layton   locks: move locks...
1814
1815
  	if (fl)
  		locks_free_lock(fl);
f7347ce4e   Linus Torvalds   fasync: re-organi...
1816
1817
  	if (new)
  		fasync_free(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
1820
1821
  	return error;
  }
  
  /**
0ceaf6c70   J. Bruce Fields   locks: prevent EN...
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
   *	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...
1834
  		return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp);
0ceaf6c70   J. Bruce Fields   locks: prevent EN...
1835
1836
1837
1838
  	return do_fcntl_add_lease(fd, filp, arg);
  }
  
  /**
29d01b22e   Jeff Layton   locks: new helper...
1839
1840
   * 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
1841
1842
   * @fl: The lock to be applied
   *
29d01b22e   Jeff Layton   locks: new helper...
1843
   * Apply a FLOCK style lock request to an inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
   */
616fb38fa   Benjamin Coddington   locks: cleanup po...
1845
  static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
1847
1848
1849
  {
  	int error;
  	might_sleep();
  	for (;;) {
29d01b22e   Jeff Layton   locks: new helper...
1850
  		error = flock_lock_inode(inode, fl);
bde74e4bc   Miklos Szeredi   locks: add specia...
1851
  		if (error != FILE_LOCK_DEFERRED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
  			break;
  		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
  		if (!error)
  			continue;
  
  		locks_delete_block(fl);
  		break;
  	}
  	return error;
  }
29d01b22e   Jeff Layton   locks: new helper...
1862
  /**
e55c34a66   Benjamin Coddington   locks: introduce ...
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
   * 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
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
   *	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.
   *	The @cmd can be one of
   *
   *	%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.
   *
   *	%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...
1905
  SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
  {
2903ff019   Al Viro   switch simple cas...
1907
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
1909
1910
1911
1912
  	struct file_lock *lock;
  	int can_sleep, unlock;
  	int error;
  
  	error = -EBADF;
2903ff019   Al Viro   switch simple cas...
1913
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
1916
1917
1918
  		goto out;
  
  	can_sleep = !(cmd & LOCK_NB);
  	cmd &= ~LOCK_NB;
  	unlock = (cmd == LOCK_UN);
aeb5d7270   Al Viro   [PATCH] introduce...
1919
  	if (!unlock && !(cmd & LOCK_MAND) &&
2903ff019   Al Viro   switch simple cas...
1920
  	    !(f.file->f_mode & (FMODE_READ|FMODE_WRITE)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  		goto out_putf;
6e129d006   Jeff Layton   locks: flock_make...
1922
1923
1924
  	lock = flock_make_lock(f.file, cmd);
  	if (IS_ERR(lock)) {
  		error = PTR_ERR(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
  		goto out_putf;
6e129d006   Jeff Layton   locks: flock_make...
1926
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
1928
  	if (can_sleep)
  		lock->fl_flags |= FL_SLEEP;
2903ff019   Al Viro   switch simple cas...
1929
  	error = security_file_lock(f.file, lock->fl_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
  	if (error)
  		goto out_free;
c568d6834   Miklos Szeredi   locks: fix file l...
1932
  	if (f.file->f_op->flock && is_remote_lock(f.file))
2903ff019   Al Viro   switch simple cas...
1933
  		error = f.file->f_op->flock(f.file,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
1935
1936
  					  (can_sleep) ? F_SETLKW : F_SETLK,
  					  lock);
  	else
4f6563677   Benjamin Coddington   Move locks API us...
1937
  		error = locks_lock_file_wait(f.file, lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
1939
  
   out_free:
993dfa877   Trond Myklebust   [PATCH] fs/locks....
1940
  	locks_free_lock(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1941
1942
  
   out_putf:
2903ff019   Al Viro   switch simple cas...
1943
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944
1945
1946
   out:
  	return error;
  }
3ee17abd1   J. Bruce Fields   locks: factor out...
1947
1948
1949
  /**
   * vfs_test_lock - test file byte range lock
   * @filp: The file to test lock for
6924c5549   J. Bruce Fields   locks: fix vfs_te...
1950
   * @fl: The lock to test; also used to hold result
3ee17abd1   J. Bruce Fields   locks: factor out...
1951
1952
1953
1954
1955
1956
   *
   * 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)
  {
c568d6834   Miklos Szeredi   locks: fix file l...
1957
  	if (filp->f_op->lock && is_remote_lock(filp))
3ee17abd1   J. Bruce Fields   locks: factor out...
1958
1959
1960
1961
1962
  		return filp->f_op->lock(filp, F_GETLK, fl);
  	posix_test_lock(filp, fl);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(vfs_test_lock);
c2fa1b8a6   J. Bruce Fields   locks: create pos...
1963
1964
  static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
  {
cff2fce58   Jeff Layton   locks: rename FL_...
1965
  	flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
c2fa1b8a6   J. Bruce Fields   locks: create pos...
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
  #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...
1980
  	flock->l_type = fl->fl_type;
c2fa1b8a6   J. Bruce Fields   locks: create pos...
1981
1982
1983
1984
1985
1986
  	return 0;
  }
  
  #if BITS_PER_LONG == 32
  static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
  {
cff2fce58   Jeff Layton   locks: rename FL_...
1987
  	flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
c2fa1b8a6   J. Bruce Fields   locks: create pos...
1988
1989
1990
1991
1992
1993
1994
  	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
1995
1996
1997
  /* Report the first existing lock that would conflict with l.
   * This implements the F_GETLK command of fcntl().
   */
c1e62b8fc   Jeff Layton   locks: pass the c...
1998
  int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1999
  {
9d6a8c5c2   Marc Eshel   locks: give posix...
2000
  	struct file_lock file_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
  	struct flock flock;
  	int error;
  
  	error = -EFAULT;
  	if (copy_from_user(&flock, l, sizeof(flock)))
  		goto out;
  	error = -EINVAL;
  	if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
  		goto out;
  
  	error = flock_to_posix_lock(filp, &file_lock, &flock);
  	if (error)
  		goto out;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2014
  	if (cmd == F_OFD_GETLK) {
90478939d   Jeff Layton   locks: require th...
2015
2016
2017
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2018
  		cmd = F_GETLK;
cff2fce58   Jeff Layton   locks: rename FL_...
2019
  		file_lock.fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2020
  		file_lock.fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2021
  	}
3ee17abd1   J. Bruce Fields   locks: factor out...
2022
2023
2024
  	error = vfs_test_lock(filp, &file_lock);
  	if (error)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2025
   
9d6a8c5c2   Marc Eshel   locks: give posix...
2026
2027
2028
  	flock.l_type = file_lock.fl_type;
  	if (file_lock.fl_type != F_UNLCK) {
  		error = posix_lock_to_flock(&flock, &file_lock);
c2fa1b8a6   J. Bruce Fields   locks: create pos...
2029
  		if (error)
f328296e2   Kinglong Mee   locks: Copy fl_lm...
2030
  			goto rel_priv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2031
2032
2033
2034
  	}
  	error = -EFAULT;
  	if (!copy_to_user(l, &flock, sizeof(flock)))
  		error = 0;
f328296e2   Kinglong Mee   locks: Copy fl_lm...
2035
2036
  rel_priv:
  	locks_release_private(&file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2037
2038
2039
  out:
  	return error;
  }
7723ec977   Marc Eshel   locks: factor out...
2040
2041
2042
2043
2044
  /**
   * 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...
2045
2046
2047
2048
2049
2050
2051
2052
   * @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...
2053
2054
2055
2056
   *
   * 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...
2057
   * lm_grant is set. Callers expecting ->lock() to return asynchronously
2beb6614f   Marc Eshel   locks: add fl_gra...
2058
2059
   * 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...
2060
   * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
2beb6614f   Marc Eshel   locks: add fl_gra...
2061
2062
   * request completes.
   * If the request is for non-blocking lock the file system should return
bde74e4bc   Miklos Szeredi   locks: add specia...
2063
2064
   * 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...
2065
2066
2067
2068
2069
   * 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...
2070
   * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
2beb6614f   Marc Eshel   locks: add fl_gra...
2071
   * return code.
7723ec977   Marc Eshel   locks: factor out...
2072
   */
150b39345   Marc Eshel   locks: allow {vfs...
2073
  int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
7723ec977   Marc Eshel   locks: factor out...
2074
  {
c568d6834   Miklos Szeredi   locks: fix file l...
2075
  	if (filp->f_op->lock && is_remote_lock(filp))
7723ec977   Marc Eshel   locks: factor out...
2076
2077
  		return filp->f_op->lock(filp, cmd, fl);
  	else
150b39345   Marc Eshel   locks: allow {vfs...
2078
  		return posix_lock_file(filp, fl, conf);
7723ec977   Marc Eshel   locks: factor out...
2079
2080
  }
  EXPORT_SYMBOL_GPL(vfs_lock_file);
b648a6de0   Miklos Szeredi   locks: cleanup co...
2081
2082
2083
2084
2085
2086
2087
2088
  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...
2089
2090
2091
  	for (;;) {
  		error = vfs_lock_file(filp, cmd, fl, NULL);
  		if (error != FILE_LOCK_DEFERRED)
b648a6de0   Miklos Szeredi   locks: cleanup co...
2092
  			break;
764c76b37   Miklos Szeredi   locks: allow ->lo...
2093
2094
2095
2096
2097
2098
  		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
  		if (!error)
  			continue;
  
  		locks_delete_block(fl);
  		break;
b648a6de0   Miklos Szeredi   locks: cleanup co...
2099
2100
2101
2102
  	}
  
  	return error;
  }
6ca7d9101   Benjamin Coddington   locks: Use more f...
2103
  /* Ensure that fl->fl_file has compatible f_mode for F_SETLK calls */
cf01f4eef   Jeff Layton   locks: only valid...
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
  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
2118
2119
2120
  /* 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...
2121
2122
  int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
  		struct flock __user *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
2124
2125
2126
  {
  	struct file_lock *file_lock = locks_alloc_lock();
  	struct flock flock;
  	struct inode *inode;
0b2bac2f1   Al Viro   [PATCH] fix SMP o...
2127
  	struct file *f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2128
2129
2130
2131
  	int error;
  
  	if (file_lock == NULL)
  		return -ENOLCK;
c568d6834   Miklos Szeredi   locks: fix file l...
2132
  	inode = locks_inode(filp);
1890910fd   Jeff Layton   locks: sprinkle s...
2133

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
2135
2136
2137
2138
2139
  	/*
  	 * This might block, so we do it before checking the inode.
  	 */
  	error = -EFAULT;
  	if (copy_from_user(&flock, l, sizeof(flock)))
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2140
2141
2142
  	/* Don't allow mandatory locks on files that may be memory mapped
  	 * and shared.
  	 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2143
  	if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
2146
2147
2148
2149
2150
  		error = -EAGAIN;
  		goto out;
  	}
  
  	error = flock_to_posix_lock(filp, file_lock, &flock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2151

cf01f4eef   Jeff Layton   locks: only valid...
2152
2153
2154
  	error = check_fmode_for_setlk(file_lock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2155
2156
  	/*
  	 * If the cmd is requesting file-private locks, then set the
cff2fce58   Jeff Layton   locks: rename FL_...
2157
  	 * FL_OFDLCK flag and override the owner.
5d50ffd7c   Jeff Layton   locks: add new fc...
2158
2159
  	 */
  	switch (cmd) {
0d3f7a2dd   Jeff Layton   locks: rename fil...
2160
  	case F_OFD_SETLK:
90478939d   Jeff Layton   locks: require th...
2161
2162
2163
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2164
  		cmd = F_SETLK;
cff2fce58   Jeff Layton   locks: rename FL_...
2165
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2166
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2167
  		break;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2168
  	case F_OFD_SETLKW:
90478939d   Jeff Layton   locks: require th...
2169
2170
2171
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2172
  		cmd = F_SETLKW;
cff2fce58   Jeff Layton   locks: rename FL_...
2173
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2174
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2175
2176
  		/* Fallthrough */
  	case F_SETLKW:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2177
2178
  		file_lock->fl_flags |= FL_SLEEP;
  	}
5d50ffd7c   Jeff Layton   locks: add new fc...
2179

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

c293621bb   Peter Staubach   [PATCH] stale POS...
2182
  	/*
0752ba807   Jeff Layton   locks: don't chec...
2183
2184
2185
  	 * 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...
2186
  	 */
0752ba807   Jeff Layton   locks: don't chec...
2187
2188
  	if (!error && file_lock->fl_type != F_UNLCK &&
  	    !(file_lock->fl_flags & FL_OFDLCK)) {
7f3697e24   Jeff Layton   locks: fix unlock...
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  		/*
  		 * 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
2203
  	}
c293621bb   Peter Staubach   [PATCH] stale POS...
2204
  out:
1890910fd   Jeff Layton   locks: sprinkle s...
2205
  	trace_fcntl_setlk(inode, file_lock, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2206
2207
2208
2209
2210
2211
2212
2213
  	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().
   */
c1e62b8fc   Jeff Layton   locks: pass the c...
2214
  int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2215
  {
9d6a8c5c2   Marc Eshel   locks: give posix...
2216
  	struct file_lock file_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
  	struct flock64 flock;
  	int error;
  
  	error = -EFAULT;
  	if (copy_from_user(&flock, l, sizeof(flock)))
  		goto out;
  	error = -EINVAL;
  	if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
  		goto out;
  
  	error = flock64_to_posix_lock(filp, &file_lock, &flock);
  	if (error)
  		goto out;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2230
  	if (cmd == F_OFD_GETLK) {
90478939d   Jeff Layton   locks: require th...
2231
2232
2233
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2234
  		cmd = F_GETLK64;
cff2fce58   Jeff Layton   locks: rename FL_...
2235
  		file_lock.fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2236
  		file_lock.fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2237
  	}
3ee17abd1   J. Bruce Fields   locks: factor out...
2238
2239
2240
  	error = vfs_test_lock(filp, &file_lock);
  	if (error)
  		goto out;
9d6a8c5c2   Marc Eshel   locks: give posix...
2241
2242
2243
  	flock.l_type = file_lock.fl_type;
  	if (file_lock.fl_type != F_UNLCK)
  		posix_lock_to_flock64(&flock, &file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2244
2245
2246
  	error = -EFAULT;
  	if (!copy_to_user(l, &flock, sizeof(flock)))
  		error = 0;
f328296e2   Kinglong Mee   locks: Copy fl_lm...
2247
2248
  
  	locks_release_private(&file_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249
2250
2251
2252
2253
2254
2255
  out:
  	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...
2256
2257
  int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
  		struct flock64 __user *l)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2258
2259
2260
2261
  {
  	struct file_lock *file_lock = locks_alloc_lock();
  	struct flock64 flock;
  	struct inode *inode;
0b2bac2f1   Al Viro   [PATCH] fix SMP o...
2262
  	struct file *f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
  	int error;
  
  	if (file_lock == NULL)
  		return -ENOLCK;
  
  	/*
  	 * This might block, so we do it before checking the inode.
  	 */
  	error = -EFAULT;
  	if (copy_from_user(&flock, l, sizeof(flock)))
  		goto out;
c568d6834   Miklos Szeredi   locks: fix file l...
2274
  	inode = locks_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275
2276
2277
2278
  
  	/* Don't allow mandatory locks on files that may be memory mapped
  	 * and shared.
  	 */
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2279
  	if (mandatory_lock(inode) && mapping_writably_mapped(filp->f_mapping)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
2281
2282
2283
2284
2285
2286
  		error = -EAGAIN;
  		goto out;
  	}
  
  	error = flock64_to_posix_lock(filp, file_lock, &flock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2287

cf01f4eef   Jeff Layton   locks: only valid...
2288
2289
2290
  	error = check_fmode_for_setlk(file_lock);
  	if (error)
  		goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2291
2292
  	/*
  	 * If the cmd is requesting file-private locks, then set the
cff2fce58   Jeff Layton   locks: rename FL_...
2293
  	 * FL_OFDLCK flag and override the owner.
5d50ffd7c   Jeff Layton   locks: add new fc...
2294
2295
  	 */
  	switch (cmd) {
0d3f7a2dd   Jeff Layton   locks: rename fil...
2296
  	case F_OFD_SETLK:
90478939d   Jeff Layton   locks: require th...
2297
2298
2299
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2300
  		cmd = F_SETLK64;
cff2fce58   Jeff Layton   locks: rename FL_...
2301
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2302
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2303
  		break;
0d3f7a2dd   Jeff Layton   locks: rename fil...
2304
  	case F_OFD_SETLKW:
90478939d   Jeff Layton   locks: require th...
2305
2306
2307
  		error = -EINVAL;
  		if (flock.l_pid != 0)
  			goto out;
5d50ffd7c   Jeff Layton   locks: add new fc...
2308
  		cmd = F_SETLKW64;
cff2fce58   Jeff Layton   locks: rename FL_...
2309
  		file_lock->fl_flags |= FL_OFDLCK;
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2310
  		file_lock->fl_owner = filp;
5d50ffd7c   Jeff Layton   locks: add new fc...
2311
2312
  		/* Fallthrough */
  	case F_SETLKW64:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2313
2314
  		file_lock->fl_flags |= FL_SLEEP;
  	}
5d50ffd7c   Jeff Layton   locks: add new fc...
2315

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

c293621bb   Peter Staubach   [PATCH] stale POS...
2318
  	/*
0752ba807   Jeff Layton   locks: don't chec...
2319
2320
2321
  	 * 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...
2322
  	 */
0752ba807   Jeff Layton   locks: don't chec...
2323
2324
  	if (!error && file_lock->fl_type != F_UNLCK &&
  	    !(file_lock->fl_flags & FL_OFDLCK)) {
7f3697e24   Jeff Layton   locks: fix unlock...
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
  		/*
  		 * 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
2339
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
  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...
2353
  	int error;
c568d6834   Miklos Szeredi   locks: fix file l...
2354
  	struct inode *inode = locks_inode(filp);
ff7b86b82   Miklos Szeredi   [PATCH] locks: cl...
2355
  	struct file_lock lock;
128a37852   Dmitry Vyukov   fs: fix data race...
2356
  	struct file_lock_context *ctx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2357
2358
2359
2360
2361
2362
  
  	/*
  	 * 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...
2363
  	ctx =  smp_load_acquire(&inode->i_flctx);
bd61e0a9c   Jeff Layton   locks: convert po...
2364
  	if (!ctx || list_empty(&ctx->flc_posix))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2365
2366
2367
  		return;
  
  	lock.fl_type = F_UNLCK;
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
2368
  	lock.fl_flags = FL_POSIX | FL_CLOSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2369
2370
2371
2372
2373
2374
2375
  	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...
2376
  	error = vfs_lock_file(filp, F_SETLK, &lock, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2377

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2378
2379
  	if (lock.fl_ops && lock.fl_ops->fl_release_private)
  		lock.fl_ops->fl_release_private(&lock);
c568d6834   Miklos Szeredi   locks: fix file l...
2380
  	trace_locks_remove_posix(inode, &lock, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381
2382
2383
  }
  
  EXPORT_SYMBOL(locks_remove_posix);
3d8e560de   Jeff Layton   locks: consolidat...
2384
  /* The i_flctx must be valid when calling into here */
dd459bb19   Jeff Layton   locks: have locks...
2385
  static void
128a37852   Dmitry Vyukov   fs: fix data race...
2386
  locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
dd459bb19   Jeff Layton   locks: have locks...
2387
2388
2389
2390
2391
2392
2393
2394
2395
  {
  	struct file_lock fl = {
  		.fl_owner = filp,
  		.fl_pid = current->tgid,
  		.fl_file = filp,
  		.fl_flags = FL_FLOCK,
  		.fl_type = F_UNLCK,
  		.fl_end = OFFSET_MAX,
  	};
c568d6834   Miklos Szeredi   locks: fix file l...
2396
  	struct inode *inode = locks_inode(filp);
dd459bb19   Jeff Layton   locks: have locks...
2397

3d8e560de   Jeff Layton   locks: consolidat...
2398
  	if (list_empty(&flctx->flc_flock))
dd459bb19   Jeff Layton   locks: have locks...
2399
  		return;
c568d6834   Miklos Szeredi   locks: fix file l...
2400
  	if (filp->f_op->flock && is_remote_lock(filp))
dd459bb19   Jeff Layton   locks: have locks...
2401
2402
  		filp->f_op->flock(filp, F_SETLKW, &fl);
  	else
bcd7f78d0   Jeff Layton   locks: have flock...
2403
  		flock_lock_inode(inode, &fl);
dd459bb19   Jeff Layton   locks: have locks...
2404
2405
2406
2407
  
  	if (fl.fl_ops && fl.fl_ops->fl_release_private)
  		fl.fl_ops->fl_release_private(&fl);
  }
3d8e560de   Jeff Layton   locks: consolidat...
2408
  /* The i_flctx must be valid when calling into here */
8634b51f6   Jeff Layton   locks: convert le...
2409
  static void
128a37852   Dmitry Vyukov   fs: fix data race...
2410
  locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
8634b51f6   Jeff Layton   locks: convert le...
2411
  {
8634b51f6   Jeff Layton   locks: convert le...
2412
2413
  	struct file_lock *fl, *tmp;
  	LIST_HEAD(dispose);
3d8e560de   Jeff Layton   locks: consolidat...
2414
  	if (list_empty(&ctx->flc_lease))
8634b51f6   Jeff Layton   locks: convert le...
2415
  		return;
5f43086bb   Peter Zijlstra   locking, fs/locks...
2416
  	percpu_down_read_preempt_disable(&file_rwsem);
6109c8503   Jeff Layton   locks: add a dedi...
2417
  	spin_lock(&ctx->flc_lock);
8634b51f6   Jeff Layton   locks: convert le...
2418
  	list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list)
c4e136cda   Jeff Layton   locks: only remov...
2419
2420
  		if (filp == fl->fl_file)
  			lease_modify(fl, F_UNLCK, &dispose);
6109c8503   Jeff Layton   locks: add a dedi...
2421
  	spin_unlock(&ctx->flc_lock);
5f43086bb   Peter Zijlstra   locking, fs/locks...
2422
  	percpu_up_read_preempt_enable(&file_rwsem);
8634b51f6   Jeff Layton   locks: convert le...
2423
2424
  	locks_dispose_list(&dispose);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2425
2426
2427
  /*
   * This function is called on the last close of an open file.
   */
78ed8a133   Jeff Layton   locks: rename loc...
2428
  void locks_remove_file(struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
  {
128a37852   Dmitry Vyukov   fs: fix data race...
2430
  	struct file_lock_context *ctx;
c568d6834   Miklos Szeredi   locks: fix file l...
2431
  	ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
128a37852   Dmitry Vyukov   fs: fix data race...
2432
  	if (!ctx)
3d8e560de   Jeff Layton   locks: consolidat...
2433
  		return;
dd459bb19   Jeff Layton   locks: have locks...
2434
  	/* remove any OFD locks */
73a8f5f7e   Christoph Hellwig   locks: purge fl_o...
2435
  	locks_remove_posix(filp, filp);
5d50ffd7c   Jeff Layton   locks: add new fc...
2436

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

8634b51f6   Jeff Layton   locks: convert le...
2440
  	/* remove any leases */
128a37852   Dmitry Vyukov   fs: fix data race...
2441
  	locks_remove_lease(filp, ctx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2442
2443
2444
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
   *	posix_unblock_lock - stop waiting for a file lock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
2447
2448
2449
   *	@waiter: the lock which was waiting
   *
   *	lockd needs to block waiting for locks.
   */
64a318ee2   J. Bruce Fields   NLM: Further canc...
2450
  int
f891a29f4   Jeff Layton   locks: drop the u...
2451
  posix_unblock_lock(struct file_lock *waiter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2452
  {
64a318ee2   J. Bruce Fields   NLM: Further canc...
2453
  	int status = 0;
7b2296afb   Jeff Layton   locks: give the b...
2454
  	spin_lock(&blocked_lock_lock);
5996a298d   J. Bruce Fields   NLM: don't unlock...
2455
  	if (waiter->fl_next)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2456
  		__locks_delete_block(waiter);
64a318ee2   J. Bruce Fields   NLM: Further canc...
2457
2458
  	else
  		status = -ENOENT;
7b2296afb   Jeff Layton   locks: give the b...
2459
  	spin_unlock(&blocked_lock_lock);
64a318ee2   J. Bruce Fields   NLM: Further canc...
2460
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2461
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2462
  EXPORT_SYMBOL(posix_unblock_lock);
9b9d2ab41   Marc Eshel   locks: add lock c...
2463
2464
2465
2466
2467
2468
2469
2470
2471
  /**
   * 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)
  {
c568d6834   Miklos Szeredi   locks: fix file l...
2472
  	if (filp->f_op->lock && is_remote_lock(filp))
9b9d2ab41   Marc Eshel   locks: add lock c...
2473
2474
2475
2476
2477
  		return filp->f_op->lock(filp, F_CANCELLK, fl);
  	return 0;
  }
  
  EXPORT_SYMBOL_GPL(vfs_cancel_lock);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2478
  #ifdef CONFIG_PROC_FS
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2479
  #include <linux/proc_fs.h>
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2480
  #include <linux/seq_file.h>
7012b02a2   Jeff Layton   locks: move file_...
2481
2482
2483
2484
  struct locks_iterator {
  	int	li_cpu;
  	loff_t	li_pos;
  };
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2485
  static void lock_get_status(struct seq_file *f, struct file_lock *fl,
99dc82925   Jerome Marchand   procfs: fix numbe...
2486
  			    loff_t id, char *pfx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2487
2488
  {
  	struct inode *inode = NULL;
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2489
  	unsigned int fl_pid;
d67fd44f6   Nikolay Borisov   locks: Filter /pr...
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
  	if (fl->fl_nspid) {
  		struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
  
  		/* Don't let fl_pid change based on who is reading the file */
  		fl_pid = pid_nr_ns(fl->fl_nspid, proc_pidns);
  
  		/*
  		 * If there isn't a fl_pid don't display who is waiting on
  		 * the lock if we are called from locks_show, or if we are
  		 * called from __show_fd_info - skip lock entirely
  		 */
  		if (fl_pid == 0)
  			return;
  	} else
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2504
  		fl_pid = fl->fl_pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2505
2506
  
  	if (fl->fl_file != NULL)
c568d6834   Miklos Szeredi   locks: fix file l...
2507
  		inode = locks_inode(fl->fl_file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2508

99dc82925   Jerome Marchand   procfs: fix numbe...
2509
  	seq_printf(f, "%lld:%s ", id, pfx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2510
  	if (IS_POSIX(fl)) {
c918d42a2   Jeff Layton   locks: make /proc...
2511
  		if (fl->fl_flags & FL_ACCESS)
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2512
  			seq_puts(f, "ACCESS");
cff2fce58   Jeff Layton   locks: rename FL_...
2513
  		else if (IS_OFDLCK(fl))
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2514
  			seq_puts(f, "OFDLCK");
c918d42a2   Jeff Layton   locks: make /proc...
2515
  		else
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2516
  			seq_puts(f, "POSIX ");
c918d42a2   Jeff Layton   locks: make /proc...
2517
2518
  
  		seq_printf(f, " %s ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2519
  			     (inode == NULL) ? "*NOINODE*" :
a16877ca9   Pavel Emelyanov   Cleanup macros fo...
2520
  			     mandatory_lock(inode) ? "MANDATORY" : "ADVISORY ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2521
2522
  	} else if (IS_FLOCK(fl)) {
  		if (fl->fl_type & LOCK_MAND) {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2523
  			seq_puts(f, "FLOCK  MSNFS     ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524
  		} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2525
  			seq_puts(f, "FLOCK  ADVISORY  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2526
2527
  		}
  	} else if (IS_LEASE(fl)) {
8144f1f69   Jeff Layton   locks: show deleg...
2528
2529
2530
2531
  		if (fl->fl_flags & FL_DELEG)
  			seq_puts(f, "DELEG  ");
  		else
  			seq_puts(f, "LEASE  ");
ab83fa4b4   J. Bruce Fields   locks: minor leas...
2532
  		if (lease_breaking(fl))
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2533
  			seq_puts(f, "BREAKING  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2534
  		else if (fl->fl_file)
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2535
  			seq_puts(f, "ACTIVE    ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2536
  		else
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2537
  			seq_puts(f, "BREAKER   ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2538
  	} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2539
  		seq_puts(f, "UNKNOWN UNKNOWN  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2540
2541
  	}
  	if (fl->fl_type & LOCK_MAND) {
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2542
  		seq_printf(f, "%s ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2543
2544
2545
2546
  			       (fl->fl_type & LOCK_READ)
  			       ? (fl->fl_type & LOCK_WRITE) ? "RW   " : "READ "
  			       : (fl->fl_type & LOCK_WRITE) ? "WRITE" : "NONE ");
  	} else {
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2547
  		seq_printf(f, "%s ",
ab83fa4b4   J. Bruce Fields   locks: minor leas...
2548
  			       (lease_breaking(fl))
0ee5c6d63   Jeff Layton   vfs: don't treat ...
2549
2550
  			       ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
  			       : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2551
2552
  	}
  	if (inode) {
3648888e9   Jeff Layton   locks: get rid of...
2553
  		/* userspace relies on this representation of dev_t */
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2554
  		seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2555
2556
  				MAJOR(inode->i_sb->s_dev),
  				MINOR(inode->i_sb->s_dev), inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2557
  	} else {
ab1f16116   Vitaliy Gusev   pid-namespaces-vs...
2558
  		seq_printf(f, "%d <none>:0 ", fl_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2559
2560
2561
  	}
  	if (IS_POSIX(fl)) {
  		if (fl->fl_end == OFFSET_MAX)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2562
2563
  			seq_printf(f, "%Ld EOF
  ", fl->fl_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2564
  		else
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2565
2566
  			seq_printf(f, "%Ld %Ld
  ", fl->fl_start, fl->fl_end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2567
  	} else {
5315c26a6   Fabian Frederick   fs/locks.c: repla...
2568
2569
  		seq_puts(f, "0 EOF
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2570
2571
  	}
  }
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2572
  static int locks_show(struct seq_file *f, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2573
  {
7012b02a2   Jeff Layton   locks: move file_...
2574
  	struct locks_iterator *iter = f->private;
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2575
  	struct file_lock *fl, *bfl;
d67fd44f6   Nikolay Borisov   locks: Filter /pr...
2576
  	struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2577

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

d67fd44f6   Nikolay Borisov   locks: Filter /pr...
2580
2581
  	if (fl->fl_nspid && !pid_nr_ns(fl->fl_nspid, proc_pidns))
  		return 0;
7012b02a2   Jeff Layton   locks: move file_...
2582
  	lock_get_status(f, fl, iter->li_pos, "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2583

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2584
  	list_for_each_entry(bfl, &fl->fl_block, fl_block)
7012b02a2   Jeff Layton   locks: move file_...
2585
  		lock_get_status(f, bfl, iter->li_pos, " ->");
094f28252   Matthias Kaehlcke   fs/locks.c: use l...
2586

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2587
2588
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589

6c8c90319   Andrey Vagin   proc: show locks ...
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
  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...
2613
  	struct inode *inode = locks_inode(filp);
6c8c90319   Andrey Vagin   proc: show locks ...
2614
2615
  	struct file_lock_context *ctx;
  	int id = 0;
128a37852   Dmitry Vyukov   fs: fix data race...
2616
  	ctx = smp_load_acquire(&inode->i_flctx);
6c8c90319   Andrey Vagin   proc: show locks ...
2617
2618
2619
2620
2621
2622
2623
2624
2625
  	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...
2626
  static void *locks_start(struct seq_file *f, loff_t *pos)
b03dfdec0   Jeff Layton   locks: add __acqu...
2627
  	__acquires(&blocked_lock_lock)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2628
  {
7012b02a2   Jeff Layton   locks: move file_...
2629
  	struct locks_iterator *iter = f->private;
99dc82925   Jerome Marchand   procfs: fix numbe...
2630

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

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2637
2638
  static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
  {
7012b02a2   Jeff Layton   locks: move file_...
2639
2640
2641
  	struct locks_iterator *iter = f->private;
  
  	++iter->li_pos;
7c3f654d8   Peter Zijlstra   fs/locks: Replace...
2642
  	return seq_hlist_next_percpu(v, &file_lock_list.hlist, &iter->li_cpu, pos);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2643
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2644

7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2645
  static void locks_stop(struct seq_file *f, void *v)
b03dfdec0   Jeff Layton   locks: add __acqu...
2646
  	__releases(&blocked_lock_lock)
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2647
  {
7b2296afb   Jeff Layton   locks: give the b...
2648
  	spin_unlock(&blocked_lock_lock);
aba376607   Peter Zijlstra   fs/locks: Replace...
2649
  	percpu_up_write(&file_rwsem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2650
  }
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2651
  static const struct seq_operations locks_seq_operations = {
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2652
2653
2654
2655
2656
  	.start	= locks_start,
  	.next	= locks_next,
  	.stop	= locks_stop,
  	.show	= locks_show,
  };
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2657
2658
2659
  
  static int locks_open(struct inode *inode, struct file *filp)
  {
7012b02a2   Jeff Layton   locks: move file_...
2660
2661
  	return seq_open_private(filp, &locks_seq_operations,
  					sizeof(struct locks_iterator));
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2662
2663
2664
2665
2666
2667
  }
  
  static const struct file_operations proc_locks_operations = {
  	.open		= locks_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
99dc82925   Jerome Marchand   procfs: fix numbe...
2668
  	.release	= seq_release_private,
d8ba7a363   Alexey Dobriyan   proc: move rest o...
2669
2670
2671
2672
2673
2674
2675
  };
  
  static int __init proc_locks_init(void)
  {
  	proc_create("locks", 0, NULL, &proc_locks_operations);
  	return 0;
  }
918992267   Paul Gortmaker   fs: make locks.c ...
2676
  fs_initcall(proc_locks_init);
7f8ada98d   Pavel Emelyanov   Rework /proc/lock...
2677
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2678
2679
  static int __init filelock_init(void)
  {
7012b02a2   Jeff Layton   locks: move file_...
2680
  	int i;
4a075e39c   Jeff Layton   locks: add a new ...
2681
2682
  	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
2683
  	filelock_cache = kmem_cache_create("file_lock_cache",
ee19cc406   Miklos Szeredi   fs: locks: remove...
2684
  			sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
7012b02a2   Jeff Layton   locks: move file_...
2685

7c3f654d8   Peter Zijlstra   fs/locks: Replace...
2686
2687
2688
2689
2690
2691
  	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_...
2692

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2693
2694
2695
2696
  	return 0;
  }
  
  core_initcall(filelock_init);