diff options
author | grog <grog@FreeBSD.org> | 1999-08-07 08:11:22 +0000 |
---|---|---|
committer | grog <grog@FreeBSD.org> | 1999-08-07 08:11:22 +0000 |
commit | 1068a4df87234f0f1203dfa8a37ce355fe656ec9 (patch) | |
tree | 845ed9a26acd293392d0166147aaa0f8567c9e88 /sys/dev/vinum/vinumlock.c | |
parent | 8b624b0301181444da4c23345f9e8a153b2776b5 (diff) | |
download | FreeBSD-src-1068a4df87234f0f1203dfa8a37ce355fe656ec9.zip FreeBSD-src-1068a4df87234f0f1203dfa8a37ce355fe656ec9.tar.gz |
Import RAID-5 code.
Add Cybernet copyright.
OK'd-by: Chuck Jacobus <chuck@cybernet.com>
Diffstat (limited to 'sys/dev/vinum/vinumlock.c')
-rw-r--r-- | sys/dev/vinum/vinumlock.c | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/sys/dev/vinum/vinumlock.c b/sys/dev/vinum/vinumlock.c index 01e9812..fe03157 100644 --- a/sys/dev/vinum/vinumlock.c +++ b/sys/dev/vinum/vinumlock.c @@ -2,6 +2,10 @@ * Copyright (c) 1997, 1998 * Nan Yang Computer Services Limited. All rights reserved. * + * Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project. + * + * Written by Greg Lehey + * * This software is distributed under the so-called ``Berkeley * License'': * @@ -33,7 +37,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * - * $Id: vinumlock.c,v 1.9 1999/03/13 03:26:00 grog Exp grog $ + * $Id: vinumlock.c,v 1.10 1999/05/15 03:47:45 grog Exp grog $ */ #include <dev/vinum/vinumhdr.h> @@ -176,6 +180,68 @@ unlockplex(struct plex *plex) } } +#define LOCK_UNALLOC -1 /* mark unused lock entries */ + +/* Lock an address range in a plex, wait if it's in use */ +int +lockrange(struct plex *plex, off_t first, off_t last) +{ + int lock; + int pos = -1; /* place to insert */ + + lockplex(plex); /* diddle one at a time */ + if (plex->locks >= plex->alloclocks) + EXPAND(plex->lock, struct rangelock, plex->alloclocks, INITIAL_LOCKS) + unlockplex(plex); + for (;;) { + lockplex(plex); + for (lock = 0; lock < plex->locks; lock++) { + if (plex->lock[lock].first == LOCK_UNALLOC) /* empty place */ + pos = lock; /* a place to put this one */ + else if ((plex->lock[lock].first < last) + && (plex->lock[lock].last > first)) { /* overlap, */ + unlockplex(plex); + tsleep(((caddr_t *) & lockrange) + plex->sdnos[0], PRIBIO | PCATCH, "vrlock", 0); + break; /* out of the inner level loop */ + } + } + if (lock == plex->locks) /* made it to the end, */ + break; + } + + /* + * The address range is free, and the plex is locked. + * Add our lock entry + */ + if (pos == -1) { /* no free space, */ + pos = lock; /* put it at the end */ + plex->locks++; + } + plex->lock[pos].first = first; + plex->lock[pos].last = last; + unlockplex(plex); + return 0; +} + +/* Unlock a volume and let the next one at it */ +void +unlockrange(struct plex *plex, off_t first, off_t last) +{ + int lock; + + lockplex(plex); + for (lock = 0; lock < plex->locks; lock++) { + if ((plex->lock[lock].first == first) + && (plex->lock[lock].last == last)) { /* found our lock */ + plex->lock[lock].first = LOCK_UNALLOC; /* not used */ + break; /* out of the inner level loop */ + } + } + if (lock == plex->locks) /* made it to the end, */ + panic("vinum: unlock without lock"); + + unlockplex(plex); +} /* Get a lock for the global config, wait if it's not available */ int |