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