Plan 9 from Bell Labs’s /usr/web/sources/contrib/blstuart/θfs/util.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * Copyright (c) 2013, Coraid, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Coraid nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL CORAID BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "dat.h"

/*
 * Version of pread that's careful to always work on sector boundaries
 */
long
spread(int fd, void *a, long n, uvlong off)
{
	char *buf;
	uvlong aoff, boff;
	long an, rn;

	boff = off % 512;
	if(n % 512 == 0 && boff == 0)
		return pread(fd, a, n, off);
	aoff = off & ~511;
	an = (n + boff + 511) & ~511;
	buf = θmalloc(an);
	rn = pread(fd, buf, an, aoff);
	if(rn <= 0) {
		free(buf);
		return rn;
	}
	rn -= boff;
	if(rn > n)
		rn = n;
	memmove(a, buf + boff, rn);
	free(buf);
	return rn;
}

long
θpread(int fd, uvlong qpath, void *a, long n, uvlong off)
{
	uvlong fblk, meta, now, len;
	ulong m, tot, boff;

	meta = q2m(fd, qpath, 0);
	if(meta == 0)
		return -1;
	if(getmetaint(fd, meta, "length", &len) == MTnone)
		len = 0;
	if(off >= len)
		n = 0;
	else if(off + n > len)
		n = len - off;
	tot = 0;
	while(n > 0) {
		fblk = locate(fd, meta, off / BlkSize, 0);
		boff = off % BlkSize;
		if(boff + n > BlkSize)
			m = BlkSize - boff;
		else
			m = n;
		if(fblk != 0) {
			if(fd == -1)
				m = cread((char *)a + tot, m, fblk * BlkSize + boff);
			else
				m = spread(fd, (char *)a + tot, m, fblk * BlkSize + boff);
		}
		else
			memset((char *)a + tot, 0, m);
		n -= m;
		off += m;
		tot += m;
	}
	if(fd == -1 && doatimes) {
		now = nsec();
		setmetaint(meta, "atime", nil, now);
	}
	return tot;
}

long
θpwrite(uvlong qpath, void *a, long n, uvlong off, int grow)
{
	uvlong fblk, meta, woff, now, len, qvers;
	ulong m, tot, boff;

	meta = q2m(-1, qpath, 0);
	if(meta == 0)
		return -1;
	if(getmetaint(-1, meta, "length", &len) == MTnone)
		len = 0;
	if(grow == 0) {
		if(off >= len)
			n = 0;
		else if(off + n > len)
			n = len - off;
	}
	else if (grow == 2)
		off = len;
	woff = off;
	tot = 0;
	while(n > 0) {
		fblk = locate(-1, meta, woff / BlkSize, 1);
		if(fblk == 0)
			break;
		boff = woff % BlkSize;
		if(boff + n > BlkSize)
			m = BlkSize - boff;
		else
			m = n;
		m = cwrite((char *)a + tot, m, fblk * BlkSize + boff);
		woff += m;
		n -= m;
		tot += m;
	}
	if(grow) {
		if(off + tot > len)
			setmetaint(meta, "length", nil, off + tot);
	}
	now = nsec();
	setmetaint(meta, "mtime", nil, now);
	setmetaint(meta, "atime", nil, now);
	if(getmetaint(-1, meta, "qvers", &qvers) != MTnone)
		qvers++;
	setmetaint(meta, "qvers", nil, qvers);
	return tot;
}

void
rmdlist(uvlong meta, uvlong myqid)
{
	uvlong sibqid, pqid, predqid;
	uvlong pmeta, qvers;

	getmetaint(-1, meta, "sib", &sibqid);
	getmetaint(-1, meta, "parent", &pqid);
	pmeta = q2m(-1, pqid, 0);
	if(pmeta == 0) {
		fprint(2, "warning: no parent?!?!\n");
		return;
	}
	if(getmetaint(-1, pmeta, "qvers", &qvers) != MTnone)
		setmetaint(pmeta, "qvers", nil, qvers + 1);
	getmetaint(-1, pmeta, "child", &predqid);
	if(predqid == myqid) {
		setmetaint(pmeta, "child", nil, sibqid);
		return;
	}
	do {
		pmeta = q2m(-1, predqid, 0);
		if(pmeta == 0)
			return;
		getmetaint(-1, pmeta, "sib", &predqid);
	} while(predqid != myqid);
	setmetaint(pmeta, "sib", nil, sibqid);
}

void *
θmalloc(ulong x)
{
	if(x > 6553600) {
		fprint(2, "$%p", getcallerpc(&x));
		return nil;
	}
	else
		return emalloc9p(x);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].