rangelock.c revision 225787
1178476Sjb/*- 2178476Sjb * Copyright (c) 2010 The FreeBSD Foundation 3178476Sjb * All rights reserved. 4178476Sjb * 5178476Sjb * This software was developed by Pawel Jakub Dawidek under sponsorship from 6178476Sjb * the FreeBSD Foundation. 7178476Sjb * 8178476Sjb * Redistribution and use in source and binary forms, with or without 9178476Sjb * modification, are permitted provided that the following conditions 10178476Sjb * are met: 11178476Sjb * 1. Redistributions of source code must retain the above copyright 12178476Sjb * notice, this list of conditions and the following disclaimer. 13178476Sjb * 2. Redistributions in binary form must reproduce the above copyright 14178476Sjb * notice, this list of conditions and the following disclaimer in the 15178476Sjb * documentation and/or other materials provided with the distribution. 16178476Sjb * 17178476Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18178476Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19178476Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20178476Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21178476Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22178476Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23178476Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24178476Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25267937Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26178476Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27178476Sjb * SUCH DAMAGE. 28178476Sjb */ 29178476Sjb 30178476Sjb#include <sys/cdefs.h> 31178476Sjb__FBSDID("$FreeBSD: head/sbin/hastd/rangelock.c 225787 2011-09-27 08:50:37Z pjd $"); 32178476Sjb 33178476Sjb#include <sys/queue.h> 34178476Sjb 35178476Sjb#include <stdbool.h> 36178476Sjb#include <stdlib.h> 37178476Sjb#include <unistd.h> 38178476Sjb 39178476Sjb#include <pjdlog.h> 40178476Sjb 41178476Sjb#include "rangelock.h" 42178476Sjb 43178476Sjb#ifndef PJDLOG_ASSERT 44178476Sjb#include <assert.h> 45178476Sjb#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 46178476Sjb#endif 47178476Sjb 48178476Sjb#define RANGELOCKS_MAGIC 0x94310c 49178476Sjbstruct rangelocks { 50178476Sjb int rls_magic; /* Magic value. */ 51178476Sjb TAILQ_HEAD(, rlock) rls_locks; /* List of locked ranges. */ 52178476Sjb}; 53178476Sjb 54178476Sjbstruct rlock { 55178476Sjb off_t rl_start; 56178476Sjb off_t rl_end; 57178476Sjb TAILQ_ENTRY(rlock) rl_next; 58178476Sjb}; 59178476Sjb 60178476Sjbint 61178476Sjbrangelock_init(struct rangelocks **rlsp) 62178476Sjb{ 63178476Sjb struct rangelocks *rls; 64178476Sjb 65178476Sjb PJDLOG_ASSERT(rlsp != NULL); 66178476Sjb 67178476Sjb rls = malloc(sizeof(*rls)); 68178476Sjb if (rls == NULL) 69178476Sjb return (-1); 70178476Sjb 71178476Sjb TAILQ_INIT(&rls->rls_locks); 72178476Sjb 73178476Sjb rls->rls_magic = RANGELOCKS_MAGIC; 74178476Sjb *rlsp = rls; 75178476Sjb 76178476Sjb return (0); 77178476Sjb} 78178476Sjb 79178476Sjbvoid 80178476Sjbrangelock_free(struct rangelocks *rls) 81178476Sjb{ 82178476Sjb struct rlock *rl; 83178476Sjb 84178476Sjb PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 85178476Sjb 86178476Sjb rls->rls_magic = 0; 87178476Sjb 88178476Sjb while ((rl = TAILQ_FIRST(&rls->rls_locks)) != NULL) { 89178476Sjb TAILQ_REMOVE(&rls->rls_locks, rl, rl_next); 90178476Sjb free(rl); 91178476Sjb } 92178476Sjb free(rls); 93178476Sjb} 94178476Sjb 95178476Sjbint 96178476Sjbrangelock_add(struct rangelocks *rls, off_t offset, off_t length) 97178476Sjb{ 98178476Sjb struct rlock *rl; 99178476Sjb 100178476Sjb PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 101267929Srpaulo 102267937Srpaulo rl = malloc(sizeof(*rl)); 103267937Srpaulo if (rl == NULL) 104178476Sjb return (-1); 105178476Sjb rl->rl_start = offset; 106178476Sjb rl->rl_end = offset + length; 107178476Sjb TAILQ_INSERT_TAIL(&rls->rls_locks, rl, rl_next); 108178476Sjb return (0); 109178476Sjb} 110178476Sjb 111178476Sjbvoid 112178476Sjbrangelock_del(struct rangelocks *rls, off_t offset, off_t length) 113178476Sjb{ 114178476Sjb struct rlock *rl; 115178476Sjb 116 PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 117 118 TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) { 119 if (rl->rl_start == offset && rl->rl_end == offset + length) 120 break; 121 } 122 PJDLOG_ASSERT(rl != NULL); 123 TAILQ_REMOVE(&rls->rls_locks, rl, rl_next); 124 free(rl); 125} 126 127bool 128rangelock_islocked(struct rangelocks *rls, off_t offset, off_t length) 129{ 130 struct rlock *rl; 131 132 PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 133 134 TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) { 135 if (rl->rl_start >= offset && rl->rl_start < offset + length) 136 break; 137 else if (rl->rl_end > offset && rl->rl_end <= offset + length) 138 break; 139 else if (rl->rl_start < offset && rl->rl_end > offset + length) 140 break; 141 } 142 return (rl != NULL); 143} 144