1 /* We save the locks so we can reaquire them. */
2 #include "private.h" /* For NTDB_HASH_LOCK_START, etc. */
7 #include "tap-interface.h"
8 #include "lock-tracking.h"
16 static struct lock
*locks
;
17 int locking_errors
= 0;
18 bool suppress_lockcheck
= false;
19 bool nonblocking_locks
;
20 int locking_would_block
= 0;
21 void (*unlock_callback
)(int fd
);
23 int fcntl_with_lockcheck(int fd
, int cmd
, ... /* arg */ )
28 bool may_block
= false;
30 if (cmd
!= F_SETLK
&& cmd
!= F_SETLKW
) {
31 /* This may be totally bogus, but we don't know in general. */
33 arg3
= va_arg(ap
, int);
36 return fcntl(fd
, cmd
, arg3
);
40 fl
= va_arg(ap
, struct flock
*);
43 if (cmd
== F_SETLKW
&& nonblocking_locks
) {
47 ret
= fcntl(fd
, cmd
, fl
);
49 /* Detect when we failed, but might have been OK if we waited. */
50 if (may_block
&& ret
== -1 && (errno
== EAGAIN
|| errno
== EACCES
)) {
51 locking_would_block
++;
54 if (fl
->l_type
== F_UNLCK
) {
56 struct lock
*old
= NULL
;
58 for (l
= &locks
; *l
; l
= &(*l
)->next
) {
59 if ((*l
)->off
== fl
->l_start
60 && (*l
)->len
== fl
->l_len
) {
69 if (!old
&& !suppress_lockcheck
) {
70 diag("Unknown unlock %u@%u - %i",
71 (int)fl
->l_len
, (int)fl
->l_start
, ret
);
76 unsigned int fl_end
= fl
->l_start
+ fl
->l_len
;
78 fl_end
= (unsigned int)-1;
80 /* Check for overlaps: we shouldn't do this. */
81 for (i
= locks
; i
; i
= i
->next
) {
82 unsigned int i_end
= i
->off
+ i
->len
;
84 i_end
= (unsigned int)-1;
86 if (fl
->l_start
>= i
->off
&& fl
->l_start
< i_end
)
88 if (fl_end
> i
->off
&& fl_end
< i_end
)
91 /* ntdb_allrecord_lock does this, handle adjacent: */
92 if (fl
->l_start
> NTDB_HASH_LOCK_START
93 && fl
->l_start
== i_end
&& fl
->l_type
== i
->type
) {
103 /* Special case: upgrade of allrecord lock. */
104 if (i
->type
== F_RDLCK
&& fl
->l_type
== F_WRLCK
105 && i
->off
== NTDB_HASH_LOCK_START
106 && fl
->l_start
== NTDB_HASH_LOCK_START
113 if (!suppress_lockcheck
) {
114 diag("%s lock %u@%u overlaps %u@%u",
115 fl
->l_type
== F_WRLCK
? "write" : "read",
116 (int)fl
->l_len
, (int)fl
->l_start
,
117 i
->len
, (int)i
->off
);
123 new = malloc(sizeof *new);
124 new->off
= fl
->l_start
;
125 new->len
= fl
->l_len
;
126 new->type
= fl
->l_type
;
132 if (ret
== 0 && fl
->l_type
== F_UNLCK
&& unlock_callback
)
137 unsigned int forget_locking(void)
139 unsigned int num
= 0;
141 struct lock
*next
= locks
->next
;