1204076Spjd/*- 2204076Spjd * Copyright (c) 2010 The FreeBSD Foundation 3204076Spjd * All rights reserved. 4204076Spjd * 5204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 6204076Spjd * the FreeBSD Foundation. 7204076Spjd * 8204076Spjd * Redistribution and use in source and binary forms, with or without 9204076Spjd * modification, are permitted provided that the following conditions 10204076Spjd * are met: 11204076Spjd * 1. Redistributions of source code must retain the above copyright 12204076Spjd * notice, this list of conditions and the following disclaimer. 13204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer in the 15204076Spjd * documentation and/or other materials provided with the distribution. 16204076Spjd * 17204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27204076Spjd * SUCH DAMAGE. 28204076Spjd */ 29204076Spjd 30204076Spjd#include <sys/cdefs.h> 31204076Spjd__FBSDID("$FreeBSD$"); 32204076Spjd 33204076Spjd#include <sys/queue.h> 34204076Spjd 35204076Spjd#include <stdbool.h> 36204076Spjd#include <stdlib.h> 37204076Spjd#include <unistd.h> 38204076Spjd 39229509Strociny#include <pjdlog.h> 40229509Strociny 41204076Spjd#include "rangelock.h" 42204076Spjd 43229509Strociny#ifndef PJDLOG_ASSERT 44229509Strociny#include <assert.h> 45229509Strociny#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 46229509Strociny#endif 47229509Strociny 48204076Spjd#define RANGELOCKS_MAGIC 0x94310c 49204076Spjdstruct rangelocks { 50204076Spjd int rls_magic; /* Magic value. */ 51204076Spjd TAILQ_HEAD(, rlock) rls_locks; /* List of locked ranges. */ 52204076Spjd}; 53204076Spjd 54204076Spjdstruct rlock { 55204076Spjd off_t rl_start; 56204076Spjd off_t rl_end; 57204076Spjd TAILQ_ENTRY(rlock) rl_next; 58204076Spjd}; 59204076Spjd 60204076Spjdint 61204076Spjdrangelock_init(struct rangelocks **rlsp) 62204076Spjd{ 63204076Spjd struct rangelocks *rls; 64204076Spjd 65229509Strociny PJDLOG_ASSERT(rlsp != NULL); 66204076Spjd 67204076Spjd rls = malloc(sizeof(*rls)); 68204076Spjd if (rls == NULL) 69204076Spjd return (-1); 70204076Spjd 71204076Spjd TAILQ_INIT(&rls->rls_locks); 72204076Spjd 73204076Spjd rls->rls_magic = RANGELOCKS_MAGIC; 74204076Spjd *rlsp = rls; 75204076Spjd 76204076Spjd return (0); 77204076Spjd} 78204076Spjd 79204076Spjdvoid 80204076Spjdrangelock_free(struct rangelocks *rls) 81204076Spjd{ 82204076Spjd struct rlock *rl; 83204076Spjd 84229509Strociny PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 85204076Spjd 86204076Spjd rls->rls_magic = 0; 87204076Spjd 88204076Spjd while ((rl = TAILQ_FIRST(&rls->rls_locks)) != NULL) { 89204076Spjd TAILQ_REMOVE(&rls->rls_locks, rl, rl_next); 90204076Spjd free(rl); 91204076Spjd } 92204076Spjd free(rls); 93204076Spjd} 94204076Spjd 95204076Spjdint 96204076Spjdrangelock_add(struct rangelocks *rls, off_t offset, off_t length) 97204076Spjd{ 98204076Spjd struct rlock *rl; 99204076Spjd 100229509Strociny PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 101204076Spjd 102204076Spjd rl = malloc(sizeof(*rl)); 103204076Spjd if (rl == NULL) 104204076Spjd return (-1); 105204076Spjd rl->rl_start = offset; 106204076Spjd rl->rl_end = offset + length; 107204076Spjd TAILQ_INSERT_TAIL(&rls->rls_locks, rl, rl_next); 108204076Spjd return (0); 109204076Spjd} 110204076Spjd 111204076Spjdvoid 112204076Spjdrangelock_del(struct rangelocks *rls, off_t offset, off_t length) 113204076Spjd{ 114204076Spjd struct rlock *rl; 115204076Spjd 116229509Strociny PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 117204076Spjd 118204076Spjd TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) { 119204076Spjd if (rl->rl_start == offset && rl->rl_end == offset + length) 120204076Spjd break; 121204076Spjd } 122229509Strociny PJDLOG_ASSERT(rl != NULL); 123204076Spjd TAILQ_REMOVE(&rls->rls_locks, rl, rl_next); 124204076Spjd free(rl); 125204076Spjd} 126204076Spjd 127204076Spjdbool 128204076Spjdrangelock_islocked(struct rangelocks *rls, off_t offset, off_t length) 129204076Spjd{ 130204076Spjd struct rlock *rl; 131231700Strociny off_t end; 132204076Spjd 133229509Strociny PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); 134204076Spjd 135231700Strociny end = offset + length; 136204076Spjd TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) { 137231700Strociny if (rl->rl_start < end && rl->rl_end > offset) 138204076Spjd break; 139204076Spjd } 140204076Spjd return (rl != NULL); 141204076Spjd} 142