rangelock.c revision 225736
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 2010 The FreeBSD Foundation
31556Srgrimes * All rights reserved.
4207944Sjilles *
5207944Sjilles * This software was developed by Pawel Jakub Dawidek under sponsorship from
61556Srgrimes * the FreeBSD Foundation.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes *
171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271556Srgrimes * SUCH DAMAGE.
281556Srgrimes */
291556Srgrimes
301556Srgrimes#include <sys/cdefs.h>
311556Srgrimes__FBSDID("$FreeBSD: stable/9/sbin/hastd/rangelock.c 204076 2010-02-18 23:16:19Z pjd $");
321556Srgrimes
331556Srgrimes#include <sys/queue.h>
341556Srgrimes
351556Srgrimes#include <assert.h>
3636150Scharnier#include <stdbool.h>
3736150Scharnier#include <stdlib.h>
3836150Scharnier#include <unistd.h>
391556Srgrimes
4099110Sobrien#include "rangelock.h"
4199110Sobrien
421556Srgrimes#define	RANGELOCKS_MAGIC	0x94310c
4317987Speterstruct rangelocks {
4417987Speter	int	 rls_magic;		/* Magic value. */
4517987Speter	TAILQ_HEAD(, rlock) rls_locks;	/* List of locked ranges. */
46213775Sjhb};
4717987Speter
48213775Sjhbstruct rlock {
49213775Sjhb	off_t	rl_start;
5017987Speter	off_t	rl_end;
51213775Sjhb	TAILQ_ENTRY(rlock) rl_next;
5217987Speter};
53108286Stjr
54213775Sjhbint
5517987Speterrangelock_init(struct rangelocks **rlsp)
561556Srgrimes{
571556Srgrimes	struct rangelocks *rls;
581556Srgrimes
591556Srgrimes	assert(rlsp != NULL);
601556Srgrimes
611556Srgrimes	rls = malloc(sizeof(*rls));
621556Srgrimes	if (rls == NULL)
631556Srgrimes		return (-1);
641556Srgrimes
651556Srgrimes	TAILQ_INIT(&rls->rls_locks);
661556Srgrimes
671556Srgrimes	rls->rls_magic = RANGELOCKS_MAGIC;
681556Srgrimes	*rlsp = rls;
691556Srgrimes
701556Srgrimes	return (0);
711556Srgrimes}
721556Srgrimes
731556Srgrimesvoid
741556Srgrimesrangelock_free(struct rangelocks *rls)
751556Srgrimes{
7617987Speter	struct rlock *rl;
7717987Speter
781556Srgrimes	assert(rls->rls_magic == RANGELOCKS_MAGIC);
791556Srgrimes
801556Srgrimes	rls->rls_magic = 0;
811556Srgrimes
821556Srgrimes	while ((rl = TAILQ_FIRST(&rls->rls_locks)) != NULL) {
831556Srgrimes		TAILQ_REMOVE(&rls->rls_locks, rl, rl_next);
841556Srgrimes		free(rl);
851556Srgrimes	}
861556Srgrimes	free(rls);
871556Srgrimes}
88194975Sjilles
891556Srgrimesint
901556Srgrimesrangelock_add(struct rangelocks *rls, off_t offset, off_t length)
911556Srgrimes{
92213760Sobrien	struct rlock *rl;
93213760Sobrien
94213760Sobrien	assert(rls->rls_magic == RANGELOCKS_MAGIC);
95213760Sobrien
96213760Sobrien	rl = malloc(sizeof(*rl));
971556Srgrimes	if (rl == NULL)
98213811Sobrien		return (-1);
99213811Sobrien	rl->rl_start = offset;
100213811Sobrien	rl->rl_end = offset + length;
101213811Sobrien	TAILQ_INSERT_TAIL(&rls->rls_locks, rl, rl_next);
102213811Sobrien	return (0);
103213811Sobrien}
104213811Sobrien
105213811Sobrienvoid
106213811Sobrienrangelock_del(struct rangelocks *rls, off_t offset, off_t length)
107213811Sobrien{
108213811Sobrien	struct rlock *rl;
109213811Sobrien
110213811Sobrien	assert(rls->rls_magic == RANGELOCKS_MAGIC);
111213811Sobrien
112213811Sobrien	TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) {
113213811Sobrien		if (rl->rl_start == offset && rl->rl_end == offset + length)
114213811Sobrien			break;
1151556Srgrimes	}
116213811Sobrien	assert(rl != NULL);
117118374Sache	TAILQ_REMOVE(&rls->rls_locks, rl, rl_next);
11819281Sache	free(rl);
11919281Sache}
12019281Sache
12119281Sachebool
12219281Sacherangelock_islocked(struct rangelocks *rls, off_t offset, off_t length)
123118374Sache{
12419281Sache	struct rlock *rl;
12519281Sache
1261556Srgrimes	assert(rls->rls_magic == RANGELOCKS_MAGIC);
1271556Srgrimes
12890111Simp	TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) {
12990111Simp		if (rl->rl_start >= offset && rl->rl_start < offset + length)
1301556Srgrimes			break;
1311556Srgrimes		else if (rl->rl_end > offset && rl->rl_end <= offset + length)
1321556Srgrimes			break;
13390111Simp		else if (rl->rl_start < offset && rl->rl_end > offset + length)
13490111Simp			break;
1351556Srgrimes	}
1361556Srgrimes	return (rl != NULL);
13739137Stegge}
1381556Srgrimes