This source file includes following definitions.
- locks_free_lock
- locks_insert_block
- locks_delete_block
- sys_flock
- fcntl_getlk
- fcntl_setlk
- locks_remove_locks
- locks_verify
- locks_locked_mandatory
- posix_make_lock
- flock_make_lock
- posix_locks_conflict
- flock_locks_conflict
- locks_conflict
- locks_overlap
- posix_locks_deadlock
- flock_lock_file
- posix_lock_file
- locks_alloc_lock
- locks_insert_lock
- locks_delete_lock
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
63
64
65
66
67
68
69
70
71
72 #include <linux/malloc.h>
73 #include <linux/sched.h>
74 #include <linux/kernel.h>
75 #include <linux/errno.h>
76 #include <linux/stat.h>
77 #include <linux/fcntl.h>
78
79 #include <asm/segment.h>
80
81 #define OFFSET_MAX ((off_t)0x7fffffff)
82
83 static int flock_make_lock(struct file *filp, struct file_lock *fl,
84 unsigned int cmd);
85 static int posix_make_lock(struct file *filp, struct file_lock *fl,
86 struct flock *l);
87 static int flock_locks_conflict(struct file_lock *caller_fl,
88 struct file_lock *sys_fl);
89 static int posix_locks_conflict(struct file_lock *caller_fl,
90 struct file_lock *sys_fl);
91 static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl);
92 static int flock_lock_file(struct file *filp, struct file_lock *caller,
93 unsigned int wait);
94 static int posix_lock_file(struct file *filp, struct file_lock *caller,
95 unsigned int wait);
96 static int posix_locks_deadlock(struct task_struct *my_task,
97 struct task_struct *blocked_task);
98 static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2);
99
100 static struct file_lock *locks_alloc_lock(struct file_lock *fl);
101 static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl);
102 static void locks_delete_lock(struct file_lock **fl, unsigned int wait);
103
104 static struct file_lock *file_lock_table = NULL;
105
106
107 static inline void locks_free_lock(struct file_lock **fl)
108 {
109 kfree(*fl);
110 *fl = NULL;
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 static inline void locks_insert_block(struct file_lock **block,
128 struct file_lock *fl)
129 {
130 struct file_lock *bfl;
131
132 while ((bfl = *block) != NULL) {
133 block = &bfl->fl_block;
134 }
135
136 *block = fl;
137 fl->fl_block = NULL;
138
139 return;
140 }
141
142 static inline void locks_delete_block(struct file_lock **block,
143 struct file_lock *fl)
144 {
145 struct file_lock *bfl;
146
147 while ((bfl = *block) != NULL) {
148 if (bfl == fl) {
149 *block = fl->fl_block;
150 fl->fl_block = NULL;
151 return;
152 }
153 block = &bfl->fl_block;
154 }
155 }
156
157
158
159
160 asmlinkage int sys_flock(unsigned int fd, unsigned int cmd)
161 {
162 struct file_lock file_lock;
163 struct file *filp;
164
165 if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
166 return (-EBADF);
167
168 if (!flock_make_lock(filp, &file_lock, cmd))
169 return (-EINVAL);
170
171 if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3))
172 return (-EBADF);
173
174 return (flock_lock_file(filp, &file_lock, cmd & LOCK_UN ? 0 : cmd & LOCK_NB ? 0 : 1));
175 }
176
177
178
179
180 int fcntl_getlk(unsigned int fd, struct flock *l)
181 {
182 int error;
183 struct flock flock;
184 struct file *filp;
185 struct file_lock *fl,file_lock;
186
187 if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
188 return (-EBADF);
189 error = verify_area(VERIFY_WRITE, l, sizeof(*l));
190 if (error)
191 return (error);
192
193 memcpy_fromfs(&flock, l, sizeof(flock));
194 if ((flock.l_type == F_UNLCK) || (flock.l_type == F_EXLCK) ||
195 (flock.l_type == F_SHLCK))
196 return (-EINVAL);
197
198 if (!posix_make_lock(filp, &file_lock, &flock))
199 return (-EINVAL);
200
201 for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
202 if (posix_locks_conflict(&file_lock, fl)) {
203 flock.l_pid = fl->fl_owner->pid;
204 flock.l_start = fl->fl_start;
205 flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
206 fl->fl_end - fl->fl_start + 1;
207 flock.l_whence = 0;
208 flock.l_type = fl->fl_type;
209 memcpy_tofs(l, &flock, sizeof(flock));
210 return (0);
211 }
212 }
213
214 flock.l_type = F_UNLCK;
215 memcpy_tofs(l, &flock, sizeof(flock));
216 return (0);
217 }
218
219
220
221
222
223
224 int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
225 {
226 int error;
227 struct file *filp;
228 struct file_lock file_lock;
229 struct flock flock;
230
231
232
233
234
235 if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
236 return (-EBADF);
237
238 error = verify_area(VERIFY_READ, l, sizeof(*l));
239 if (error)
240 return (error);
241
242 memcpy_fromfs(&flock, l, sizeof(flock));
243 if (!posix_make_lock(filp, &file_lock, &flock))
244 return (-EINVAL);
245
246 switch (flock.l_type) {
247 case F_RDLCK :
248 if (!(filp->f_mode & 1))
249 return -EBADF;
250 break;
251 case F_WRLCK :
252 if (!(filp->f_mode & 2))
253 return -EBADF;
254 break;
255 case F_SHLCK :
256 case F_EXLCK :
257 if (!(filp->f_mode & 3))
258 return -EBADF;
259 break;
260 case F_UNLCK :
261 break;
262 }
263
264 return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW));
265 }
266
267
268
269 void locks_remove_locks(struct task_struct *task, struct file *filp)
270 {
271 struct file_lock *fl;
272 struct file_lock **before;
273
274
275
276
277
278 before = &filp->f_inode->i_flock;
279 while ((fl = *before) != NULL) {
280 if (((fl->fl_flags == F_POSIX) && (fl->fl_owner == task)) ||
281 ((fl->fl_flags == F_FLOCK) && (fl->fl_file == filp) &&
282 (filp->f_count == 1)))
283 locks_delete_lock(before, 0);
284 else
285 before = &fl->fl_next;
286 }
287
288 return;
289 }
290
291 int locks_verify(int read_write, struct inode *inode, struct file *filp,
292 unsigned int offset, unsigned int count)
293 {
294
295
296
297 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
298 return (locks_locked_mandatory(read_write, inode, filp,
299 offset, count));
300 return (0);
301 }
302
303 int locks_locked_mandatory(int read_write, struct inode *inode,
304 struct file *filp, unsigned int offset,
305 unsigned int count)
306 {
307 struct file_lock *fl;
308
309 repeat:
310
311
312
313
314 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
315 if (fl->fl_flags == F_FLOCK ||
316 (fl->fl_flags == F_POSIX && fl->fl_owner == current))
317 continue;
318 if (fl->fl_end < offset ||
319 fl->fl_start >= offset + count)
320 continue;
321
322
323
324
325 if (read_write == FLOCK_VERIFY_WRITE ||
326 fl->fl_type == F_WRLCK) {
327 if (filp && (filp->f_flags & O_NONBLOCK))
328 return (-EAGAIN);
329 if (current->signal & ~current->blocked)
330 return (-ERESTARTSYS);
331 if (posix_locks_deadlock(current, fl->fl_owner))
332 return (-EDEADLOCK);
333 interruptible_sleep_on(&fl->fl_wait);
334 if (current->signal & ~current->blocked)
335 return (-ERESTARTSYS);
336
337
338
339
340 if ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID)
341 break;
342 goto repeat;
343 }
344 }
345 return (0);
346 }
347
348
349
350
351 static int posix_make_lock(struct file *filp, struct file_lock *fl,
352 struct flock *l)
353 {
354 off_t start;
355
356 if (!filp->f_inode)
357 return (0);
358
359 switch (l->l_type) {
360 case F_RDLCK :
361 case F_WRLCK :
362 case F_UNLCK :
363 fl->fl_type = l->l_type;
364 break;
365 case F_SHLCK :
366 fl->fl_type = F_RDLCK;
367 break;
368 case F_EXLCK :
369 fl->fl_type = F_WRLCK;
370 break;
371 default :
372 return (0);
373 }
374
375 switch (l->l_whence) {
376 case 0 :
377 start = 0;
378 break;
379 case 1 :
380 start = filp->f_pos;
381 break;
382 case 2 :
383 start = filp->f_inode->i_size;
384 break;
385 default :
386 return (0);
387 }
388
389 if (((start += l->l_start) < 0) || (l->l_len < 0))
390 return (0);
391 fl->fl_start = start;
392 if ((l->l_len == 0) || ((fl->fl_end = start + l->l_len - 1) < 0))
393 fl->fl_end = OFFSET_MAX;
394
395 fl->fl_flags = F_POSIX;
396 fl->fl_file = filp;
397 fl->fl_owner = current;
398 fl->fl_wait = NULL;
399
400 return (1);
401 }
402
403
404
405
406 static int flock_make_lock(struct file *filp, struct file_lock *fl,
407 unsigned int cmd)
408 {
409 if (!filp->f_inode)
410 return (0);
411
412 switch (cmd & ~LOCK_NB) {
413 case LOCK_SH :
414 fl->fl_type = F_RDLCK;
415 break;
416 case LOCK_EX :
417 fl->fl_type = F_WRLCK;
418 break;
419 case LOCK_UN :
420 fl->fl_type = F_UNLCK;
421 break;
422 default :
423 return (0);
424 }
425
426 fl->fl_flags = F_FLOCK;
427 fl->fl_start = 0;
428 fl->fl_end = OFFSET_MAX;
429 fl->fl_file = filp;
430 fl->fl_owner = current;
431 fl->fl_wait = NULL;
432
433 return (1);
434 }
435
436
437
438
439 static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
440 {
441
442
443
444 if ((sys_fl->fl_flags == F_POSIX) &&
445 (caller_fl->fl_owner == sys_fl->fl_owner))
446 return (0);
447
448 return (locks_conflict(caller_fl, sys_fl));
449 }
450
451
452
453
454 static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
455 {
456
457
458
459 if ((sys_fl->fl_flags == F_FLOCK) &&
460 (caller_fl->fl_file == sys_fl->fl_file))
461 return (0);
462
463 return (locks_conflict(caller_fl, sys_fl));
464 }
465
466
467
468
469 static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
470 {
471 if (!locks_overlap(caller_fl, sys_fl))
472 return (0);
473
474 switch (caller_fl->fl_type) {
475 case F_RDLCK :
476 return (sys_fl->fl_type == F_WRLCK);
477
478 case F_WRLCK :
479 return (1);
480
481 default:
482 printk("locks_conflict(): impossible lock type - %d\n",
483 caller_fl->fl_type);
484 break;
485 }
486 return (0);
487 }
488
489
490
491 static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
492 {
493 return ((fl1->fl_end >= fl2->fl_start) &&
494 (fl2->fl_end >= fl1->fl_start));
495 }
496
497
498
499
500
501
502
503
504
505
506
507 static int posix_locks_deadlock(struct task_struct *my_task,
508 struct task_struct *blocked_task)
509 {
510 struct wait_queue *dlock_wait;
511 struct file_lock *fl;
512
513 next_task:
514 for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) {
515 if (fl->fl_owner == NULL || fl->fl_wait == NULL)
516 continue;
517 dlock_wait = fl->fl_wait;
518 do {
519 if (dlock_wait->task == blocked_task) {
520 if (fl->fl_owner == my_task) {
521 return(-EDEADLOCK);
522 }
523 blocked_task = fl->fl_owner;
524 goto next_task;
525 }
526 dlock_wait = dlock_wait->next;
527 } while (dlock_wait != fl->fl_wait);
528 }
529 return (0);
530 }
531
532
533
534
535
536 static int flock_lock_file(struct file *filp, struct file_lock *caller,
537 unsigned int wait)
538 {
539 struct file_lock *fl;
540 struct file_lock *new_fl;
541 struct file_lock **before;
542 int change = 0;
543
544
545
546
547 before = &filp->f_inode->i_flock;
548 while ((fl = *before) && (fl->fl_flags == F_FLOCK)) {
549 if (caller->fl_file == fl->fl_file) {
550 if (caller->fl_type == fl->fl_type)
551 return (0);
552 change = 1;
553 break;
554 }
555 before = &fl->fl_next;
556 }
557
558
559
560 if (change)
561 locks_delete_lock(before, caller->fl_type != F_UNLCK);
562 if (caller->fl_type == F_UNLCK)
563 return (0);
564 if ((new_fl = locks_alloc_lock(caller)) == NULL)
565 return (-ENOLCK);
566 repeat:
567 for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
568 if (!flock_locks_conflict(new_fl, fl))
569 continue;
570
571 if (wait) {
572 if (current->signal & ~current->blocked) {
573
574
575
576
577
578 locks_free_lock(&new_fl);
579 return (-ERESTARTSYS);
580 }
581 locks_insert_block(&fl->fl_block, new_fl);
582 interruptible_sleep_on(&new_fl->fl_wait);
583 wake_up(&new_fl->fl_wait);
584 if (current->signal & ~current->blocked) {
585
586
587
588
589
590
591
592 locks_delete_block(&fl->fl_block, new_fl);
593 locks_free_lock(&new_fl);
594 return (-ERESTARTSYS);
595 }
596 goto repeat;
597 }
598
599 locks_free_lock(&new_fl);
600 return (-EAGAIN);
601 }
602 locks_insert_lock(&filp->f_inode->i_flock, new_fl);
603 return (0);
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618 static int posix_lock_file(struct file *filp, struct file_lock *caller,
619 unsigned int wait)
620 {
621 struct file_lock *fl;
622 struct file_lock *new_fl;
623 struct file_lock *left = NULL;
624 struct file_lock *right = NULL;
625 struct file_lock **before;
626 int added = 0;
627
628 if (caller->fl_type != F_UNLCK) {
629 repeat:
630 for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
631 if (!posix_locks_conflict(caller, fl))
632 continue;
633 if (wait) {
634 if (current->signal & ~current->blocked)
635 return (-ERESTARTSYS);
636 if (fl->fl_flags == F_POSIX)
637 if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner))
638 return (-EDEADLOCK);
639 interruptible_sleep_on(&fl->fl_wait);
640 if (current->signal & ~current->blocked)
641 return (-ERESTARTSYS);
642 goto repeat;
643 }
644 return (-EAGAIN);
645 }
646 }
647
648
649
650
651 before = &filp->f_inode->i_flock;
652
653
654
655 while ((fl = *before) && ((fl->fl_flags == F_FLOCK) ||
656 (caller->fl_owner != fl->fl_owner))) {
657 before = &fl->fl_next;
658 }
659
660
661
662
663 while ((fl = *before) && (caller->fl_owner == fl->fl_owner)) {
664
665
666 if (caller->fl_type == fl->fl_type) {
667 if (fl->fl_end < caller->fl_start - 1)
668 goto next_lock;
669
670
671
672 if (fl->fl_start > caller->fl_end + 1)
673 break;
674
675
676
677
678
679
680 if (fl->fl_start > caller->fl_start)
681 fl->fl_start = caller->fl_start;
682 else
683 caller->fl_start = fl->fl_start;
684 if (fl->fl_end < caller->fl_end)
685 fl->fl_end = caller->fl_end;
686 else
687 caller->fl_end = fl->fl_end;
688 if (added) {
689 locks_delete_lock(before, 0);
690 continue;
691 }
692 caller = fl;
693 added = 1;
694 }
695 else {
696
697
698
699 if (fl->fl_end < caller->fl_start)
700 goto next_lock;
701 if (fl->fl_start > caller->fl_end)
702 break;
703 if (caller->fl_type == F_UNLCK)
704 added = 1;
705 if (fl->fl_start < caller->fl_start)
706 left = fl;
707
708
709
710 if (fl->fl_end > caller->fl_end) {
711 right = fl;
712 break;
713 }
714 if (fl->fl_start >= caller->fl_start) {
715
716
717
718 if (added) {
719 locks_delete_lock(before, 0);
720 continue;
721 }
722
723
724
725
726
727 wake_up(&fl->fl_wait);
728 fl->fl_start = caller->fl_start;
729 fl->fl_end = caller->fl_end;
730 fl->fl_type = caller->fl_type;
731 caller = fl;
732 added = 1;
733 }
734 }
735
736
737 next_lock:
738 before = &(*before)->fl_next;
739 }
740
741 if (!added) {
742 if (caller->fl_type == F_UNLCK)
743 return (0);
744 if ((new_fl = locks_alloc_lock(caller)) == NULL)
745 return (-ENOLCK);
746 locks_insert_lock(before, new_fl);
747
748 }
749 if (right) {
750 if (left == right) {
751
752
753
754
755 if ((left = locks_alloc_lock(right)) == NULL) {
756 if (!added)
757 locks_delete_lock(before, 0);
758 return (-ENOLCK);
759 }
760 locks_insert_lock(before, left);
761 }
762 right->fl_start = caller->fl_end + 1;
763 }
764 if (left)
765 left->fl_end = caller->fl_start - 1;
766 return (0);
767 }
768
769
770
771
772
773
774 static struct file_lock *locks_alloc_lock(struct file_lock *fl)
775 {
776 struct file_lock *tmp;
777
778
779 if ((tmp = (struct file_lock *)kmalloc(sizeof(struct file_lock),
780 GFP_ATOMIC)) == NULL)
781 return (tmp);
782
783 tmp->fl_nextlink = NULL;
784 tmp->fl_prevlink = NULL;
785 tmp->fl_next = NULL;
786 tmp->fl_block = NULL;
787 tmp->fl_flags = fl->fl_flags;
788 tmp->fl_owner = fl->fl_owner;
789 tmp->fl_file = fl->fl_file;
790 tmp->fl_wait = NULL;
791 tmp->fl_type = fl->fl_type;
792 tmp->fl_start = fl->fl_start;
793 tmp->fl_end = fl->fl_end;
794
795 return (tmp);
796 }
797
798
799
800
801
802 static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
803 {
804 fl->fl_nextlink = file_lock_table;
805 fl->fl_prevlink = NULL;
806 if (file_lock_table != NULL)
807 file_lock_table->fl_prevlink = fl;
808 file_lock_table = fl;
809 fl->fl_next = *pos;
810 *pos = fl;
811
812 return;
813 }
814
815
816
817
818
819
820
821
822
823
824 static void locks_delete_lock(struct file_lock **fl_p, unsigned int wait)
825 {
826 struct file_lock *fl;
827 struct file_lock *bfl;
828
829 fl = *fl_p;
830 *fl_p = (*fl_p)->fl_next;
831
832 if (fl->fl_nextlink != NULL)
833 fl->fl_nextlink->fl_prevlink = fl->fl_prevlink;
834
835 if (fl->fl_prevlink != NULL)
836 fl->fl_prevlink->fl_nextlink = fl->fl_nextlink;
837 else {
838 file_lock_table = fl->fl_nextlink;
839 }
840
841 while ((bfl = fl->fl_block) != NULL) {
842 fl->fl_block = bfl->fl_block;
843 bfl->fl_block = NULL;
844 wake_up(&bfl->fl_wait);
845 if (wait)
846 sleep_on(&bfl->fl_wait);
847 }
848
849 wake_up(&fl->fl_wait);
850 kfree(fl);
851
852 return;
853 }