aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 528fedfda15e..653faabb07f4 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -203,11 +203,11 @@ static struct kmem_cache *flctx_cache __read_mostly;
203static struct kmem_cache *filelock_cache __read_mostly; 203static struct kmem_cache *filelock_cache __read_mostly;
204 204
205static struct file_lock_context * 205static struct file_lock_context *
206locks_get_lock_context(struct inode *inode) 206locks_get_lock_context(struct inode *inode, int type)
207{ 207{
208 struct file_lock_context *new; 208 struct file_lock_context *new;
209 209
210 if (likely(inode->i_flctx)) 210 if (likely(inode->i_flctx) || type == F_UNLCK)
211 goto out; 211 goto out;
212 212
213 new = kmem_cache_alloc(flctx_cache, GFP_KERNEL); 213 new = kmem_cache_alloc(flctx_cache, GFP_KERNEL);
@@ -223,14 +223,7 @@ locks_get_lock_context(struct inode *inode)
223 * Assign the pointer if it's not already assigned. If it is, then 223 * Assign the pointer if it's not already assigned. If it is, then
224 * free the context we just allocated. 224 * free the context we just allocated.
225 */ 225 */
226 spin_lock(&inode->i_lock); 226 if (cmpxchg(&inode->i_flctx, NULL, new))
227 if (likely(!inode->i_flctx)) {
228 inode->i_flctx = new;
229 new = NULL;
230 }
231 spin_unlock(&inode->i_lock);
232
233 if (new)
234 kmem_cache_free(flctx_cache, new); 227 kmem_cache_free(flctx_cache, new);
235out: 228out:
236 return inode->i_flctx; 229 return inode->i_flctx;
@@ -276,8 +269,10 @@ void locks_release_private(struct file_lock *fl)
276 } 269 }
277 270
278 if (fl->fl_lmops) { 271 if (fl->fl_lmops) {
279 if (fl->fl_lmops->lm_put_owner) 272 if (fl->fl_lmops->lm_put_owner) {
280 fl->fl_lmops->lm_put_owner(fl); 273 fl->fl_lmops->lm_put_owner(fl->fl_owner);
274 fl->fl_owner = NULL;
275 }
281 fl->fl_lmops = NULL; 276 fl->fl_lmops = NULL;
282 } 277 }
283} 278}
@@ -333,7 +328,7 @@ void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)
333 328
334 if (fl->fl_lmops) { 329 if (fl->fl_lmops) {
335 if (fl->fl_lmops->lm_get_owner) 330 if (fl->fl_lmops->lm_get_owner)
336 fl->fl_lmops->lm_get_owner(new, fl); 331 fl->fl_lmops->lm_get_owner(fl->fl_owner);
337 } 332 }
338} 333}
339EXPORT_SYMBOL(locks_copy_conflock); 334EXPORT_SYMBOL(locks_copy_conflock);
@@ -592,11 +587,15 @@ posix_owner_key(struct file_lock *fl)
592 587
593static void locks_insert_global_blocked(struct file_lock *waiter) 588static void locks_insert_global_blocked(struct file_lock *waiter)
594{ 589{
590 lockdep_assert_held(&blocked_lock_lock);
591
595 hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter)); 592 hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter));
596} 593}
597 594
598static void locks_delete_global_blocked(struct file_lock *waiter) 595static void locks_delete_global_blocked(struct file_lock *waiter)
599{ 596{
597 lockdep_assert_held(&blocked_lock_lock);
598
600 hash_del(&waiter->fl_link); 599 hash_del(&waiter->fl_link);
601} 600}
602 601
@@ -730,7 +729,7 @@ static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *s
730 /* POSIX locks owned by the same process do not conflict with 729 /* POSIX locks owned by the same process do not conflict with
731 * each other. 730 * each other.
732 */ 731 */
733 if (!IS_POSIX(sys_fl) || posix_same_owner(caller_fl, sys_fl)) 732 if (posix_same_owner(caller_fl, sys_fl))
734 return (0); 733 return (0);
735 734
736 /* Check whether they overlap */ 735 /* Check whether they overlap */
@@ -748,7 +747,7 @@ static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *s
748 /* FLOCK locks referring to the same filp do not conflict with 747 /* FLOCK locks referring to the same filp do not conflict with
749 * each other. 748 * each other.
750 */ 749 */
751 if (!IS_FLOCK(sys_fl) || (caller_fl->fl_file == sys_fl->fl_file)) 750 if (caller_fl->fl_file == sys_fl->fl_file)
752 return (0); 751 return (0);
753 if ((caller_fl->fl_type & LOCK_MAND) || (sys_fl->fl_type & LOCK_MAND)) 752 if ((caller_fl->fl_type & LOCK_MAND) || (sys_fl->fl_type & LOCK_MAND))
754 return 0; 753 return 0;
@@ -838,6 +837,8 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
838{ 837{
839 int i = 0; 838 int i = 0;
840 839
840 lockdep_assert_held(&blocked_lock_lock);
841
841 /* 842 /*
842 * This deadlock detector can't reasonably detect deadlocks with 843 * This deadlock detector can't reasonably detect deadlocks with
843 * FL_OFDLCK locks, since they aren't owned by a process, per-se. 844 * FL_OFDLCK locks, since they aren't owned by a process, per-se.
@@ -871,9 +872,12 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
871 bool found = false; 872 bool found = false;
872 LIST_HEAD(dispose); 873 LIST_HEAD(dispose);
873 874
874 ctx = locks_get_lock_context(inode); 875 ctx = locks_get_lock_context(inode, request->fl_type);
875 if (!ctx) 876 if (!ctx) {
876 return -ENOMEM; 877 if (request->fl_type != F_UNLCK)
878 return -ENOMEM;
879 return (request->fl_flags & FL_EXISTS) ? -ENOENT : 0;
880 }
877 881
878 if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { 882 if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
879 new_fl = locks_alloc_lock(); 883 new_fl = locks_alloc_lock();
@@ -939,9 +943,9 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
939 bool added = false; 943 bool added = false;
940 LIST_HEAD(dispose); 944 LIST_HEAD(dispose);
941 945
942 ctx = locks_get_lock_context(inode); 946 ctx = locks_get_lock_context(inode, request->fl_type);
943 if (!ctx) 947 if (!ctx)
944 return -ENOMEM; 948 return (request->fl_type == F_UNLCK) ? 0 : -ENOMEM;
945 949
946 /* 950 /*
947 * We may need two file_lock structures for this operation, 951 * We may need two file_lock structures for this operation,
@@ -964,8 +968,6 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
964 */ 968 */
965 if (request->fl_type != F_UNLCK) { 969 if (request->fl_type != F_UNLCK) {
966 list_for_each_entry(fl, &ctx->flc_posix, fl_list) { 970 list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
967 if (!IS_POSIX(fl))
968 continue;
969 if (!posix_locks_conflict(request, fl)) 971 if (!posix_locks_conflict(request, fl))
970 continue; 972 continue;
971 if (conflock) 973 if (conflock)
@@ -1388,9 +1390,8 @@ any_leases_conflict(struct inode *inode, struct file_lock *breaker)
1388int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) 1390int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1389{ 1391{
1390 int error = 0; 1392 int error = 0;
1391 struct file_lock *new_fl;
1392 struct file_lock_context *ctx = inode->i_flctx; 1393 struct file_lock_context *ctx = inode->i_flctx;
1393 struct file_lock *fl; 1394 struct file_lock *new_fl, *fl, *tmp;
1394 unsigned long break_time; 1395 unsigned long break_time;
1395 int want_write = (mode & O_ACCMODE) != O_RDONLY; 1396 int want_write = (mode & O_ACCMODE) != O_RDONLY;
1396 LIST_HEAD(dispose); 1397 LIST_HEAD(dispose);
@@ -1420,7 +1421,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1420 break_time++; /* so that 0 means no break time */ 1421 break_time++; /* so that 0 means no break time */
1421 } 1422 }
1422 1423
1423 list_for_each_entry(fl, &ctx->flc_lease, fl_list) { 1424 list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
1424 if (!leases_conflict(fl, new_fl)) 1425 if (!leases_conflict(fl, new_fl))
1425 continue; 1426 continue;
1426 if (want_write) { 1427 if (want_write) {
@@ -1606,7 +1607,8 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1606 lease = *flp; 1607 lease = *flp;
1607 trace_generic_add_lease(inode, lease); 1608 trace_generic_add_lease(inode, lease);
1608 1609
1609 ctx = locks_get_lock_context(inode); 1610 /* Note that arg is never F_UNLCK here */
1611 ctx = locks_get_lock_context(inode, arg);
1610 if (!ctx) 1612 if (!ctx)
1611 return -ENOMEM; 1613 return -ENOMEM;
1612 1614
@@ -2556,15 +2558,10 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2556 : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ "); 2558 : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
2557 } 2559 }
2558 if (inode) { 2560 if (inode) {
2559#ifdef WE_CAN_BREAK_LSLK_NOW 2561 /* userspace relies on this representation of dev_t */
2560 seq_printf(f, "%d %s:%ld ", fl_pid,
2561 inode->i_sb->s_id, inode->i_ino);
2562#else
2563 /* userspace relies on this representation of dev_t ;-( */
2564 seq_printf(f, "%d %02x:%02x:%ld ", fl_pid, 2562 seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
2565 MAJOR(inode->i_sb->s_dev), 2563 MAJOR(inode->i_sb->s_dev),
2566 MINOR(inode->i_sb->s_dev), inode->i_ino); 2564 MINOR(inode->i_sb->s_dev), inode->i_ino);
2567#endif
2568 } else { 2565 } else {
2569 seq_printf(f, "%d <none>:0 ", fl_pid); 2566 seq_printf(f, "%d <none>:0 ", fl_pid);
2570 } 2567 }
@@ -2593,6 +2590,44 @@ static int locks_show(struct seq_file *f, void *v)
2593 return 0; 2590 return 0;
2594} 2591}
2595 2592
2593static void __show_fd_locks(struct seq_file *f,
2594 struct list_head *head, int *id,
2595 struct file *filp, struct files_struct *files)
2596{
2597 struct file_lock *fl;
2598
2599 list_for_each_entry(fl, head, fl_list) {
2600
2601 if (filp != fl->fl_file)
2602 continue;
2603 if (fl->fl_owner != files &&
2604 fl->fl_owner != filp)
2605 continue;
2606
2607 (*id)++;
2608 seq_puts(f, "lock:\t");
2609 lock_get_status(f, fl, *id, "");
2610 }
2611}
2612
2613void show_fd_locks(struct seq_file *f,
2614 struct file *filp, struct files_struct *files)
2615{
2616 struct inode *inode = file_inode(filp);
2617 struct file_lock_context *ctx;
2618 int id = 0;
2619
2620 ctx = inode->i_flctx;
2621 if (!ctx)
2622 return;
2623
2624 spin_lock(&ctx->flc_lock);
2625 __show_fd_locks(f, &ctx->flc_flock, &id, filp, files);
2626 __show_fd_locks(f, &ctx->flc_posix, &id, filp, files);
2627 __show_fd_locks(f, &ctx->flc_lease, &id, filp, files);
2628 spin_unlock(&ctx->flc_lock);
2629}
2630
2596static void *locks_start(struct seq_file *f, loff_t *pos) 2631static void *locks_start(struct seq_file *f, loff_t *pos)
2597 __acquires(&blocked_lock_lock) 2632 __acquires(&blocked_lock_lock)
2598{ 2633{