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