]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/hastd/rangelock.c
ping: use the monotonic clock to measure durations
[FreeBSD/FreeBSD.git] / sbin / hastd / rangelock.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010 The FreeBSD Foundation
5  * All rights reserved.
6  *
7  * This software was developed by Pawel Jakub Dawidek under sponsorship from
8  * the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/queue.h>
36
37 #include <stdbool.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40
41 #include <pjdlog.h>
42
43 #include "rangelock.h"
44
45 #ifndef PJDLOG_ASSERT
46 #include <assert.h>
47 #define PJDLOG_ASSERT(...)      assert(__VA_ARGS__)
48 #endif
49
50 #define RANGELOCKS_MAGIC        0x94310c
51 struct rangelocks {
52         int      rls_magic;             /* Magic value. */
53         TAILQ_HEAD(, rlock) rls_locks;  /* List of locked ranges. */
54 };
55
56 struct rlock {
57         off_t   rl_start;
58         off_t   rl_end;
59         TAILQ_ENTRY(rlock) rl_next;
60 };
61
62 int
63 rangelock_init(struct rangelocks **rlsp)
64 {
65         struct rangelocks *rls;
66
67         PJDLOG_ASSERT(rlsp != NULL);
68
69         rls = malloc(sizeof(*rls));
70         if (rls == NULL)
71                 return (-1);
72
73         TAILQ_INIT(&rls->rls_locks);
74
75         rls->rls_magic = RANGELOCKS_MAGIC;
76         *rlsp = rls;
77
78         return (0);
79 }
80
81 void
82 rangelock_free(struct rangelocks *rls)
83 {
84         struct rlock *rl;
85
86         PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC);
87
88         rls->rls_magic = 0;
89
90         while ((rl = TAILQ_FIRST(&rls->rls_locks)) != NULL) {
91                 TAILQ_REMOVE(&rls->rls_locks, rl, rl_next);
92                 free(rl);
93         }
94         free(rls);
95 }
96
97 int
98 rangelock_add(struct rangelocks *rls, off_t offset, off_t length)
99 {
100         struct rlock *rl;
101
102         PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC);
103
104         rl = malloc(sizeof(*rl));
105         if (rl == NULL)
106                 return (-1);
107         rl->rl_start = offset;
108         rl->rl_end = offset + length;
109         TAILQ_INSERT_TAIL(&rls->rls_locks, rl, rl_next);
110         return (0);
111 }
112
113 void
114 rangelock_del(struct rangelocks *rls, off_t offset, off_t length)
115 {
116         struct rlock *rl;
117
118         PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC);
119
120         TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) {
121                 if (rl->rl_start == offset && rl->rl_end == offset + length)
122                         break;
123         }
124         PJDLOG_ASSERT(rl != NULL);
125         TAILQ_REMOVE(&rls->rls_locks, rl, rl_next);
126         free(rl);
127 }
128
129 bool
130 rangelock_islocked(struct rangelocks *rls, off_t offset, off_t length)
131 {
132         struct rlock *rl;
133         off_t end;
134
135         PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC);
136
137         end = offset + length;
138         TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) {
139                 if (rl->rl_start < end && rl->rl_end > offset)
140                         break;
141         }
142         return (rl != NULL);
143 }