1 /* We save the locks so we can reaquire them. */
2 #include "../common/tdb_private.h"
7 #include "tap-interface.h"
8 #include "lock-tracking.h"
11 struct testlock
*next
;
16 static struct testlock
*testlocks
;
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 testlock
*old
= NULL
;
58 for (l
= &testlocks
; *l
; l
= &(*l
)->next
) {
59 if ((*l
)->off
== fl
->l_start
60 && (*l
)->len
== fl
->l_len
) {
68 if (((*l
)->off
== fl
->l_start
)
72 * Remove a piece from the start of the
76 (*l
)->off
+= fl
->l_len
;
80 if (!old
&& !suppress_lockcheck
) {
81 diag("Unknown unlock %u@%u - %i",
82 (int)fl
->l_len
, (int)fl
->l_start
, ret
);
86 struct testlock
*new, *i
;
87 unsigned int fl_end
= fl
->l_start
+ fl
->l_len
;
89 fl_end
= (unsigned int)-1;
91 /* Check for overlaps: we shouldn't do this. */
92 for (i
= testlocks
; i
; i
= i
->next
) {
93 unsigned int i_end
= i
->off
+ i
->len
;
95 i_end
= (unsigned int)-1;
97 if (fl
->l_start
>= i
->off
&& fl
->l_start
< i_end
)
99 if (fl_end
>= i
->off
&& fl_end
< i_end
)
102 /* tdb_allrecord_lock does this, handle adjacent: */
103 if (fl
->l_start
== i_end
&& fl
->l_type
== i
->type
) {
113 /* Special case: upgrade of allrecord lock. */
114 if (i
->type
== F_RDLCK
&& fl
->l_type
== F_WRLCK
115 && i
->off
== FREELIST_TOP
116 && fl
->l_start
== FREELIST_TOP
123 if (!suppress_lockcheck
) {
124 diag("%s testlock %u@%u overlaps %u@%u",
125 fl
->l_type
== F_WRLCK
? "write" : "read",
126 (int)fl
->l_len
, (int)fl
->l_start
,
127 i
->len
, (int)i
->off
);
133 new = malloc(sizeof *new);
134 new->off
= fl
->l_start
;
135 new->len
= fl
->l_len
;
136 new->type
= fl
->l_type
;
137 new->next
= testlocks
;
142 if (ret
== 0 && fl
->l_type
== F_UNLCK
&& unlock_callback
)
147 unsigned int forget_locking(void)
149 unsigned int num
= 0;
151 struct testlock
*next
= testlocks
->next
;