コード例 #1
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
int
pflnet_getifaddr(const struct ifaddrs *ifa0, const char *ifname,
    union pfl_sockaddr *sa)
{
	const struct ifaddrs *ifa;
	struct ifreq ifr;
	int rc, s;

	if (ifa0) {
		for (ifa = ifa0; ifa; ifa = ifa->ifa_next)
			if (strcmp(ifa->ifa_name, ifname) == 0 &&
			    ifa->ifa_addr->sa_family == AF_INET) {
				memcpy(&sa->sa, ifa->ifa_addr,
				    sizeof(sa->sin));
				return (1);
			}
	} else {
psc_fatalx("broke");
		strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
		s = socket(AF_INET, SOCK_DGRAM, 0);
		if (s == -1)
			psc_fatal("socket");

		rc = ioctl(s, SIOCGIFADDR, &ifr);
		if (rc == -1)
			psc_fatal("ioctl SIOCGIFNAME");
		close(s);

//		memcpy(sap, ifr.ifr_addr, );
	}
	return (0);
}
コード例 #2
0
ファイル: multiwait_test.c プロジェクト: pscedu/slash2-stable
int
main(int argc, char *argv[])
{
	struct thr *t, *threads;
	int rc, c, j;
	long l;

	pfl_init();
	while ((c = getopt(argc, argv, "i:n:")) != -1)
		switch (c) {
		case 'i':
			l = strtol(optarg, NULL, 10);
			if (l < 0 || l > INT_MAX)
				errx(1, "invalid iterations: %s", optarg);
			iterations = (int)l;
			break;
		case 'n':
			l = strtol(optarg, NULL, 10);
			if (l < 0 || l > INT_MAX)
				errx(1, "invalid nthreads: %s", optarg);
			nthreads = (int)l;
			break;
		default:
			usage();
		}
	argc -= optind;
	if (argc)
		usage();

	if ((threads = calloc(nthreads, sizeof(*threads))) == NULL)
		err(1, "calloc");

	pfl_multiwaitcond_init(&mastermlc, NULL, 0, "master");

	for (j = 0, t = threads; j < nthreads; j++, t++) {
		pfl_multiwaitcond_init(&t->t_mlc, NULL, 0, "cond%d", j);

		pfl_multiwait_init(&t->t_ml, "ml%d", j);
		rc = pfl_multiwait_addcond(&t->t_ml, &mastermlc);
		if (rc)
			psc_fatal("addcond");
		rc = pfl_multiwait_addcond(&t->t_ml, &t->t_mlc);
		if (rc)
			psc_fatal("addcond");

		rc = pthread_create(&t->t_pthread, NULL, thr_main, t);
		if (rc)
			errx(1, "pthread_create: %s", strerror(rc));
		sched_yield();
	}

	for (j = 0; j < iterations; j++) {
		pfl_multiwaitcond_wakeup(&mastermlc);
		usleep(100);
	}
	exit(0);
}
コード例 #3
0
ファイル: mdsio_zfs.c プロジェクト: tdestro/slash2
int
zfsslash2_init(void)
{
	struct pscfs_args args = PSCFS_ARGS_INIT(0, NULL);
	extern struct fuse_lowlevel_ops pscfs_fuse_ops;
	extern struct fuse_session *fuse_session;
	extern struct pollfd pflfs_fds[];
	extern int newfs_fd[2], pflfs_nfds;
	extern char *fuse_mount_options;
	int rc;

	if (pfl_systemf("umount %s", _PATH_KSTAT) == -1)
		psclog_warn("umount %s", _PATH_KSTAT);

	if (pipe(newfs_fd) == -1)
		psc_fatal("pipe");

	pflfs_fds[0].fd = newfs_fd[0];
	pflfs_fds[0].events = POLLIN;
	pflfs_nfds = 1;

	fuse_session = fuse_lowlevel_new(&args.pfa_av, &pscfs_fuse_ops,
	    sizeof(pscfs_fuse_ops), NULL);

	pscthr_init(SLMTHRT_ZFS_KSTAT, slmzfskstatmthr_main, 0,
	    "slmzfskstatmthr");

	fuse_mount_options = "";
	rc = libzfs_init_fusesocket();
	if (rc == 0)
		rc = libzfs_init();
	atexit(slm_unmount_kstat);
	return (rc);
}
コード例 #4
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
/**
 * pflnet_getifnfordst - Obtain an interface name (e.g. eth0) for the
 *	given destination address.
 * @ifa0: base of ifaddrs list to directly compare for localhost.
 * @sa: destination address.
 * @ifn: value-result interface name to fill in.
 */
void
pflnet_getifnfordst(const struct ifaddrs *ifa0,
    const struct sockaddr *sa, char ifn[IFNAMSIZ])
{
	const struct sockaddr_in *sin;
	const struct ifaddrs *ifa;

	psc_assert(sa->sa_family == AF_INET);
	sin = (void *)sa;

	/*
	 * Scan interfaces for addr since netlink
	 * will always give us the lo interface.
	 */
	for (ifa = ifa0; ifa; ifa = ifa->ifa_next)
		if (ifa->ifa_addr->sa_family == sa->sa_family &&
		    memcmp(&sin->sin_addr,
		    &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
		    sizeof(sin->sin_addr)) == 0) {
			strlcpy(ifn, ifa->ifa_name, IFNAMSIZ);
			return;
		}

#ifdef HAVE_RTNETLINK
	pflnet_getifnfordst_rtnetlink(sa, ifn);
#elif defined(RTM_GET)
	pflnet_getifnfordst_rtsock(sa, ifn);
#else
	errno = ENOTSUP;
	psc_fatal("getifnfordst");
#endif
}
コード例 #5
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
__static int
pflnet_rtexists_sysctl(const struct sockaddr *sa)
{
	union {
		struct rt_msghdr *rtm;
		char *ch;
		void *p;
	} u;
	union pfl_sockaddr_ptr s, os;
	int rc = 0, mib[6];
	char *buf = NULL;
	size_t len;

	os.cp = sa;

	mib[0] = CTL_NET;
	mib[1] = PF_ROUTE;
	mib[2] = 0;		/* protocol */
	mib[3] = AF_INET;
	mib[4] = NET_RT_DUMP;
	mib[5] = 0;		/* no flags */
	if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
		psc_fatal("route-sysctl-estimate");
	if (len) {
		buf = PSCALLOC(len);
		if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1)
			psc_fatal("actual retrieval of routing table");
	}

	for (u.p = buf; u.ch && u.ch < buf + len;
	    u.ch += u.rtm->rtm_msglen) {
		if (u.rtm->rtm_version != RTM_VERSION)
			continue;
		s.p = u.rtm + 1;

		if (s.s->sin.sin_addr.s_addr ==
		    os.s->sin.sin_addr.s_addr) {
			rc = 1;
			break;
		}
	}

	PSCFREE(buf);

	return (rc);
}
コード例 #6
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
__static void
pflnet_getifname(int ifidx, char ifn[IFNAMSIZ])
{
	struct ifreq ifr;
	int rc, s;

	ifr.ifr_ifindex = ifidx;
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1)
		psc_fatal("socket");

	rc = ioctl(s, SIOCGIFNAME, &ifr);
	if (rc == -1)
		psc_fatal("ioctl SIOCGIFNAME");
	close(s);
	strlcpy(ifn, ifr.ifr_name, IFNAMSIZ);
}
コード例 #7
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
/**
 * pflnet_getifaddrs - Acquire list of network interface addresses.
 * @ifap: value-result base of addresses array, must be when finished.
 */
int
pflnet_getifaddrs(struct ifaddrs **ifap)
{
#ifdef HAVE_GETIFADDRS
	return (getifaddrs(ifap));
#else
	int nifs, rc, s, n;
	struct ifconf ifc;
	struct ifreq *ifr;

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1)
		psc_fatal("socket");

	ifc.ifc_buf = NULL;
	rc = ioctl(s, SIOCGIFCONF, &ifc);
	if (rc == -1)
		psc_fatal("ioctl SIOCGIFCONF");

	/*
	 * If an interface is being added while we are fetching,
	 * there is no way to determine that we didn't get them
	 * all with this API.
	 */
	ifc.ifc_buf = PSCALLOC(ifc.ifc_len);
	rc = ioctl(s, SIOCGIFCONF, &ifc);
	if (rc == -1)
		psc_fatal("ioctl SIOCGIFCONF");

	close(s);

	nifs = ifc.ifc_len / sizeof(*ifr);
	*ifap = PSCALLOC(sizeof(**ifap) * nifs);

	ifr = (void *)ifc.ifc_buf;
	for (n = 0; n < nifs; n+++, ifr++)
		memcpy(*ifap + n, &ifr->ifr_addr, sizeof(**ifap));
#endif
	return (0);
}
コード例 #8
0
int
zfsslash2_init(void)
{
	struct pscfs_args args = PSCFS_ARGS_INIT(0, NULL);
	extern struct fuse_lowlevel_ops pscfs_fuse_ops;
	extern struct fuse_session *fuse_session;
	extern struct pollfd pscfs_fds[];
	extern int newfs_fd[2], pscfs_nfds;
	extern char *fuse_mount_options;
	char buf[BUFSIZ];
	int rc;

	rc = snprintf(buf, sizeof(buf), "umount %s", _PATH_KSTAT);
	if (rc == -1)
		psc_fatal("snprintf: umount %s", _PATH_KSTAT);
	if (rc >= (int)sizeof(buf))
		psc_fatalx("snprintf: umount %s: too long", _PATH_KSTAT);
	if (system(buf) == -1)
		psclog_warn("system(%s)", buf);

	if (pipe(newfs_fd) == -1)
		psc_fatal("pipe");

	pscfs_fds[0].fd = newfs_fd[0];
	pscfs_fds[0].events = POLLIN;
	pscfs_nfds = 1;

	fuse_session = fuse_lowlevel_new(&args.pfa_av, &pscfs_fuse_ops,
	    sizeof(pscfs_fuse_ops), NULL);

	pscthr_init(SLMTHRT_ZFS_KSTAT, slmzfskstatmthr_main, NULL, 0,
	    "slmzfskstatmthr");

	fuse_mount_options = "";
	rc = libzfs_init_fusesocket();
	if (rc == 0)
		rc = libzfs_init();
	atexit(slm_unmount_kstat);
	return (rc);
}
コード例 #9
0
void
slm_unmount_kstat(void)
{
	char buf[BUFSIZ];
	int rc;

	rc = snprintf(buf, sizeof(buf), "umount %s", _PATH_KSTAT);
	if (rc == -1)
		psc_fatal("snprintf: umount %s", _PATH_KSTAT);
	if (rc >= (int)sizeof(buf))
		psc_fatalx("snprintf: umount %s: too long", _PATH_KSTAT);
	if (system(buf) == -1)
		psclog_warn("system(%s)", buf);
}
コード例 #10
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
int
pflnet_rtexists(const struct sockaddr *sa)
{
	int rc;

#ifdef HAVE_RTNETLINK
	rc = pflnet_rtexists_rtnetlink(sa);
#elif HAVE_RT_SYSCTL
	rc = pflnet_rtexists_sysctl(sa);
#else
	(void)sa;
	errno = ENOTSUP;
	psc_fatal("rtexists");
#endif
	return (rc);
}
コード例 #11
0
ファイル: opstats.c プロジェクト: pscedu/pfl
void
pfl_opstats_grad_init(struct pfl_opstats_grad *og, int flags,
    int64_t *buckets, int nbuckets, const char *fmt, ...)
{
	const char *lower_suffix = "", *upper_suffix = "";
	int64_t lower_bound, upper_bound;
	struct pfl_opstat_bucket *ob;
	char label[16];
	int rc, i;

	og->og_buckets = PSCALLOC(nbuckets * sizeof(og->og_buckets[0]));
	og->og_nbuckets = nbuckets;

	for (i = 0, ob = og->og_buckets; i < nbuckets; i++, ob++) {
		if (i)
			pfl_assert(buckets[i - 1] < buckets[i]);
		else
			pfl_assert(buckets[i] == 0);

		lower_bound = buckets[i];
		if (!(flags & OPSTF_BASE10))
			lower_suffix = _pfl_opstats_base2_suffix(
			    &lower_bound);

		if (i == nbuckets - 1) {
			rc = snprintf(label, sizeof(label),
			    "%d:>=%"PRId64"%.1s", i, lower_bound,
			    lower_suffix);
		} else {
			upper_bound = buckets[i + 1];
			if (!(flags & OPSTF_BASE10))
				upper_suffix =
				    _pfl_opstats_base2_suffix(
					&upper_bound);

			rc = snprintf(label, sizeof(label),
			    "%d:%"PRId64"%.1s-<%"PRId64"%.1s", i,
			    lower_bound, lower_suffix,
			    upper_bound, upper_suffix);
		}
		if (rc == -1)
			psc_fatal("snprintf");
		ob->ob_lower_bound = buckets[i];
		ob->ob_opst = pfl_opstat_initf(flags | OPSTF_BASE10,
		    fmt, label);
	}
}
コード例 #12
0
ファイル: main.c プロジェクト: pscedu/slash2-stable
void
unmount(const char *mp)
{
	char buf[BUFSIZ];
	int rc;

	/* XXX do not let this hang */
	rc = snprintf(buf, sizeof(buf),
	    "umount '%s' || umount -f '%s' || umount -l '%s'",
	    mp, mp, mp);
	if (rc == -1)
		psc_fatal("snprintf: umount %s", mp);
	if ((size_t)rc >= sizeof(buf))
		psc_fatalx("snprintf: umount %s: too long", mp);
	if (system(buf) == -1)
		psclog_warn("system(%s)", buf);
}
コード例 #13
0
ファイル: rsx.c プロジェクト: zhihui-slash2/slash2-stable
/**
 * rsx_bulkclient - Setup a source or sink for a client.
 * @type: GET_SOURCE lets server to pull our buffer,
 *	PUT_SINK sets up a buffer filled in by the server
 * @rq: RPC request.
 * @descp: pointer to bulk xfer descriptor.
 * @ptl: portal to issue bulk xfer across.
 * @iov: iovec array of receive buffer.
 * @n: #iovecs.
 * Returns: 0 or negative errno on error.
 */
int
rsx_bulkclient(struct pscrpc_request *rq, int type, int ptl,
    struct iovec *iov, int n)
{
	struct pscrpc_bulk_desc *desc;
	int i;

	psc_assert(type == BULK_GET_SOURCE || type == BULK_PUT_SINK);

	desc = pscrpc_prep_bulk_imp(rq, n, type, ptl);
	if (desc == NULL)
		psc_fatal("NULL bulk descriptor");
	desc->bd_nob = 0;
	desc->bd_iov_count = n;
	memcpy(desc->bd_iov, iov, n * sizeof(*iov));
	for (i = 0; i < n; i++)
		desc->bd_nob += iov[i].iov_len;
	return (0);
}
コード例 #14
0
ファイル: wipedir.c プロジェクト: jasons-psc/slash2
int
wipefs_fidns(FTSENT *f, __unusedx void *arg)
{
	int rc = 0, skiplevel = ion ? 7 : 6;
	const char *fn;

	fn = f->fts_path;
	if (f->fts_level < 1)
		return (0);
	if (f->fts_info == FTS_D || f->fts_info == FTS_DP) {
		if (f->fts_info == FTS_DP && rmdir(fn) == -1)
			psc_fatal("rmdir %s", fn);

		/*
		 * Do not descend into hardlinked directories.
		 *
		 * MDS:
		 *	0 -> dir
		 *	1 -> dir/.slmd
		 *	2 -> dir/.slmd/fidns
		 *	3 -> dir/.slmd/fidns/0
		 *	4 -> dir/.slmd/fidns/0/1
		 *	5 -> dir/.slmd/fidns/0/1/2
		 *	6 -> dir/.slmd/fidns/0/1/2/3
		 *	7 -> dir/.slmd/fidns/0/1/2/3/file
		 *
		 * IO:
		 *	0 -> dir
		 *	1 -> dir/.slmd
		 *	2 -> dir/.slmd/fsuuid
		 *	3 -> dir/.slmd/fsuuid/fidns
		 *	4 -> dir/.slmd/fsuuid/fidns/0
		 *	5 -> dir/.slmd/fsuuid/fidns/0/1
		 *	6 -> dir/.slmd/fsuuid/fidns/0/1/2
		 *	7 -> dir/.slmd/fsuuid/fidns/0/1/2/3
		 *	8 -> dir/.slmd/fsuuid/fidns/0/1/2/3/file
		 */
		else if (f->fts_level > skiplevel)
			pfl_fts_set(f, FTS_SKIP);
	} else if (unlink(fn) == -1)
		psclog_error("unlink %s", fn);
	return (rc);
}
コード例 #15
0
ファイル: listcache.c プロジェクト: pscedu/pfl
/*
 * Register a list cache for external access.
 * @plc: the list cache to register.
 * @name: printf(3) format of name for list.
 * @ap: variable argument list for printf(3) name argument.
 */
void
lc_vregister(struct psc_listcache *plc, const char *name, va_list ap)
{
	int rc;

	PLL_LOCK(&psc_listcaches);
	LIST_CACHE_LOCK(plc);

	rc = vsnprintf(plc->plc_name, sizeof(plc->plc_name), name, ap);
	if (rc == -1)
		psc_fatal("vsnprintf");
	if (rc > (int)sizeof(plc->plc_name))
		psc_fatalx("plc_name is too large (%s)", name);

	plc->plc_nseen = pfl_opstat_initf(OPSTF_BASE10,
	    "listcache.%s.adds", plc->plc_name);
	plc->plc_st_removes = pfl_opstat_initf(OPSTF_BASE10,
	    "listcache.%s.removes", plc->plc_name);
	pll_add_sorted(&psc_listcaches, plc, lc_cmp);

	LIST_CACHE_ULOCK(plc);
	PLL_ULOCK(&psc_listcaches);
}
コード例 #16
0
ファイル: wipedir.c プロジェクト: jasons-psc/slash2
int
wipefs_user(FTSENT *f, __unusedx void *arg)
{
	const char *p, *fn;
	int rc = 0;

	fn = f->fts_path;
	if (f->fts_level < 1)
		return (0);
	if (f->fts_info == FTS_D || f->fts_info == FTS_DP) {
		/* skip SLASH2 internal metadata */
		p = strrchr(fn, '/');
		if (p)
			p++;
		else
			p = fn;
		if (strcmp(p, SL_RPATH_META_DIR) == 0)
			pfl_fts_set(f, FTS_SKIP);
		else if (f->fts_info == FTS_DP && rmdir(fn) == -1)
			psc_fatal("rmdir %s", fn);
	} else if (unlink(fn) == -1)
		psclog_error("unlink %s", fn);
	return (rc);
}
コード例 #17
0
ファイル: timecrc.c プロジェクト: pscedu/slash2-stable
int
main(int argc, char *argv[])
{
	struct timeval tm0, tm1, tmd, tm_total, tm_last;
	struct stat stb;
	char buf[BUFSIZ];
	uint64_t crc;
	const char *fn;
	int fd, pad;
	size_t acsz;
	ssize_t rc;

	progname = argv[0];
	if (getopt(argc, argv, "") != -1)
		usage();
	argc -= optind;
	argv += optind;
	if (argc != 1)
		usage();
	fn = argv[0];

	fd = open(fn, O_RDONLY);
	if (fd == -1)
		psc_fatal("%s", fn);
	if (fstat(fd, &stb) == -1)
		psc_fatal("fstat %s", fn);

	pad = snprintf(NULL, 0, "%"PSCPRIdOFFT, stb.st_size);

	acsz = 0;
	psc_crc64_init(&crc);
	memset(&tm_total, 0, sizeof(tm_total));
	memset(&tm_last, 0, sizeof(tm_last));
	for (;;) {
		rc = read(fd, buf, sizeof(buf));
		if (rc == -1)
			psc_fatal("read %s", fn);
		if (rc == 0)
			break;
		acsz += rc;

		PFL_GETTIMEVAL(&tm0);
		psc_crc64_add(&crc, buf, rc);
		PFL_GETTIMEVAL(&tm1);
		timersub(&tm1, &tm0, &tmd);

		memcpy(&tm0, &tm_total, sizeof(tm0));
		timeradd(&tmd, &tm0, &tm_total);

		timersub(&tm1, &tm_last, &tmd);
		if (tmd.tv_usec > 1000000 / 32) { /* 32 fps */
			memcpy(&tm_last, &tm1, sizeof(tm_last));
			printf("\r%*zd/%"PSCPRIdOFFT, pad, acsz,
			    stb.st_size);
			fflush(stdout);
		}
	}
	close(fd);

	psc_crc64_fini(&crc);
	printf("\rcrc %"PSCPRIxCRC64" size %"PSCPRIdOFFT" time %.3fs\n",
	    crc, stb.st_size, tm_total.tv_sec + tm_total.tv_usec * 1e-6);
	exit(0);
}
コード例 #18
0
int
main(int argc, char *argv[])
{
	struct psc_vbitmap *vb, vba = VBITMAP_INIT_AUTO;
	int i, c, u, t;
	size_t elem, j;

	pfl_init();
	progname = argv[0];
	while ((c = getopt(argc, argv, "")) != -1)
		switch (c) {
		default:
			usage();
		}

	argc -= optind;
	if (argc)
		usage();

	for (i = 0; i < 79; i++)
		if (psc_vbitmap_next(&vba, &j) != 1)
			psc_fatalx("psc_vbitmap_next failed with auto");
		else if (j != (size_t)i)
			psc_fatalx("elem %d is not supposed to be %zu", i, j);

	if ((vb = psc_vbitmap_new(213)) == NULL)
		psc_fatal("psc_vbitmap_new");

	psc_vbitmap_setrange(vb, 13, 9);
	psc_vbitmap_printbin1(vb);
	for (i = 0; i < 13; i++)
		psc_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 9; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 25; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_clearall(vb);
	for (i = 0; i < 213; i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_setrange(vb, 25, 3);
	for (i = 0; i < 25; i++)
		psc_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 3; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 25; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_clearall(vb);
	for (i = 0; i < 213; i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 0);

	for (i = 0; i < 213; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements at pos %d", i);

	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	psc_vbitmap_getstats(vb, &u, &t);
	if (u != 213 || t != 213)
		psc_fatalx("wrong size, got %d,%d want %d", u, t, 213);

	psc_vbitmap_unsetrange(vb, 13, 2);
	for (i = 0; i < 13; i++)
		psc_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 2; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 25; j++, i++)
	    psc_assert(psc_vbitmap_get(vb, i) == 1);

	if (psc_vbitmap_resize(vb, NELEM) == -1)
		psc_fatal("psc_vbitmap_new");

	psc_assert(psc_vbitmap_getsize(vb) == NELEM);

	/* fill up bitmap */
	for (i = 0; i < NELEM - 211; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements at iter %d", i);

	/* try one past end of filled bitmap */
	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	/* free some slots */
	for (i = 0, elem = 0; elem < NELEM; i++, elem += NELEM / 10)
		psc_vbitmap_unset(vb, elem);

	t = psc_vbitmap_nfree(vb);
	if (t != i)
		psc_fatalx("wrong number of free elements; has=%d want=%d", t, i);
	psc_vbitmap_invert(vb);
	t = psc_vbitmap_nfree(vb);
	if (t != NELEM - i)
		psc_fatalx("wrong number of inverted elements; has=%d want=%d",
		    t, NELEM - i);
	psc_vbitmap_invert(vb);
	t = psc_vbitmap_nfree(vb);
	if (t != i)
		psc_fatalx("wrong number of original elements; has=%d want=%d", t, i);

	/* try to re-grab the freed slots */
	for (i = 0; i <= 10; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements, request %d/%d", i, 10);

	/* try one past end of filled bitmap */
	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	psc_vbitmap_setval_range(vb, 0, NELEM, 0);
	psc_assert(pfl_vbitmap_israngeset(vb, 0, 581, 371));
	psc_assert(pfl_vbitmap_israngeset(vb, 1, 581, 371) == 0);
	psc_assert(pfl_vbitmap_israngeset(vb, 0, 581, 1));
	psc_assert(pfl_vbitmap_israngeset(vb, 1, 581, 1) == 0);
	psc_assert(pfl_vbitmap_isempty(vb));

	psc_vbitmap_setval_range(vb, 0, NELEM, 1);
	psc_assert(pfl_vbitmap_israngeset(vb, 1, 581, 371));
	psc_assert(pfl_vbitmap_israngeset(vb, 0, 581, 371) == 0);
	psc_assert(pfl_vbitmap_israngeset(vb, 1, 581, 1));
	psc_assert(pfl_vbitmap_israngeset(vb, 0, 581, 1) == 0);
	psc_assert(psc_vbitmap_isfull(vb));

	psc_vbitmap_free(vb);

	vb = psc_vbitmap_new(0);
	for (i = 1; i < 101; i++) {
		if (psc_vbitmap_resize(vb, i) == -1)
			psc_fatal("psc_vbitmap_new");
		psc_vbitmap_setval(vb, i - 1, i % 2);
		psc_assert(psc_vbitmap_get(vb, i - 1) == i % 2);
	}

	exit(0);
}
コード例 #19
0
ファイル: slmkjrnl.c プロジェクト: pscedu/slash2-stable
/*
 * Initialize an on-disk journal.
 * @fn: file path to store journal.
 * @nents: number of entries journal may contain if non-zero.
 * @entsz: size of a journal entry.
 * @rs: read size.
 * Returns the number of entries created.
 */
uint32_t
sl_journal_format(const char *fn, uint32_t nents, uint32_t entsz,
    uint32_t rs, uint64_t uuid, int block_dev)
{
	uint32_t i, slot, max_nents;
	struct psc_journal_enthdr *pje;
	struct psc_journal pj;
	struct stat stb;
	unsigned char *jbuf;
	size_t numblocks;
	ssize_t nb;
	int fd;

	memset(&pj, 0, sizeof(pj));

	fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
	if (fd == -1)
		psc_fatal("%s", fn);

	if (fstat(fd, &stb) == -1)
		psc_fatal("stat %s", fn);

	/*
	 * If the user does not specify nents, either use default or
	 * based on the block device size.
	 */
	if (nents == 0 && !block_dev)
		nents = SLJ_MDS_JNENTS;

	if (block_dev) {
		if (ioctl(fd, BLKGETSIZE, &numblocks) == -1)
			err(1, "BLKGETSIZE: %s", fn);

		/* show progress, it is going to be a while */
		verbose = 1;

		/* deal with large disks */
		max_nents = MIN(numblocks, SLJ_MDS_MAX_JNENTS);

		/* leave room on both ends */
		max_nents -= stb.st_blksize / SLJ_MDS_ENTSIZE + 16;

		/* efficiency */
		max_nents = (max_nents / rs) * rs;
		if (nents)
			nents = MIN(nents, max_nents);
		else
			nents = max_nents;
	}

	if (nents % rs)
		psc_fatalx("number of slots (%u) should be a multiple of "
		    "readsize (%u)", nents, rs);

	pj.pj_fd = fd;
	pj.pj_hdr = PSCALLOC(PSC_ALIGN(sizeof(struct psc_journal_hdr),
	    stb.st_blksize));

	pj.pj_hdr->pjh_entsz = entsz;
	pj.pj_hdr->pjh_nents = nents;
	pj.pj_hdr->pjh_version = PJH_VERSION;
	pj.pj_hdr->pjh_readsize = rs;
	pj.pj_hdr->pjh_iolen = PSC_ALIGN(sizeof(struct psc_journal_hdr),
	    stb.st_blksize);
	pj.pj_hdr->pjh_magic = PJH_MAGIC;
	pj.pj_hdr->pjh_timestamp = time(NULL);
	pj.pj_hdr->pjh_fsuuid = uuid;

	psc_crc64_init(&pj.pj_hdr->pjh_chksum);
	psc_crc64_add(&pj.pj_hdr->pjh_chksum, pj.pj_hdr,
	    offsetof(struct psc_journal_hdr, pjh_chksum));
	psc_crc64_fini(&pj.pj_hdr->pjh_chksum);

	nb = pwrite(pj.pj_fd, pj.pj_hdr, pj.pj_hdr->pjh_iolen, 0);
	if ((size_t)nb != pj.pj_hdr->pjh_iolen)
		psc_fatalx("failed to write journal header: %s",
		    nb == -1 ? strerror(errno) : "short write");

	nb = PJ_PJESZ(&pj) * pj.pj_hdr->pjh_readsize;
	jbuf = psc_alloc(nb, PAF_PAGEALIGN);
	for (i = 0; i < rs; i++) {
		pje = PSC_AGP(jbuf, PJ_PJESZ(&pj) * i);
		pje->pje_magic = PJE_MAGIC;
		pje->pje_type = PJE_FORMAT;
		pje->pje_xid = PJE_XID_NONE;
		pje->pje_len = 0;

		psc_crc64_init(&pje->pje_chksum);
		psc_crc64_add(&pje->pje_chksum, pje,
		    offsetof(struct psc_journal_enthdr, pje_chksum));
		psc_crc64_add(&pje->pje_chksum, pje->pje_data,
		    pje->pje_len);
		psc_crc64_fini(&pje->pje_chksum);
	}

	i = 0;
	/* XXX use an option to write only one entry in fast create mode */
	for (slot = 0; slot < pj.pj_hdr->pjh_nents; slot += rs) {
		nb = pwrite(pj.pj_fd, jbuf, PJ_PJESZ(&pj) * rs,
		    PJ_GETENTOFF(&pj, slot));
		if ((size_t)nb != PJ_PJESZ(&pj) * rs)
			psc_fatal("failed to write slot %u (%zd)",
			    slot, nb);
		if (verbose && slot % 262144 == 0) {
			printf(".");
			fflush(stdout);
			fsync(pj.pj_fd);
			if (++i == 80) {
				printf("\n");
				i = 0;
			}
		}
	}
	if (verbose && i)
		printf("\n");
	if (close(fd) == -1)
		psc_fatal("failed to close journal");
	psc_free(jbuf, PAF_PAGEALIGN, PJ_PJESZ(&pj) * rs);

	return (nents);
}
コード例 #20
0
ファイル: walk.c プロジェクト: pscedu/pfl
/*
 * Traverse a file hierarchy and perform an operation on each file
 * system entry.
 * @fn: file root.
 * @flags: behavorial flags.
 * @cmpf: optional dirent comparator for ordering.
 * @cbf: callback to invoke on each file.
 * @arg: optional argument to supply to callback.
 * Notes: the callback will be invoked with a fully resolved absolute
 *	path name unless the file in question is a symbolic link.
 */
int
pfl_filewalk(const char *fn, int flags, void *cmpf, int (*cbf)(FTSENT *,
    void *), void *arg)
{
	char * const pathv[] = { (char *)fn, NULL };
	int rc = 0, f_flags = 0;
	struct stat stb;
	FTSENT *f;
	FTS *fp;

	if (flags & PFL_FILEWALKF_RECURSIVE) {
		if (flags & PFL_FILEWALKF_NOSTAT)
			f_flags |= FTS_NOSTAT;
		if (flags & PFL_FILEWALKF_NOCHDIR)
			f_flags |= FTS_NOCHDIR;
		fp = pfl_fts_open(pathv, f_flags | FTS_COMFOLLOW |
		    FTS_PHYSICAL, cmpf);
		if (fp == NULL)
			psc_fatal("fts_open %s", fn);
		while ((f = pfl_fts_read(fp)) != NULL) {
			switch (f->fts_info) {
			case FTS_NS:
				psclog_warnx("%s: %s", f->fts_path,
				    strerror(f->fts_errno));
				break;
			case FTS_F:
			case FTS_D:
			case FTS_SL:
				if (flags & PFL_FILEWALKF_VERBOSE)
					warnx("processing %s%s",
					    fn, f->fts_info == FTS_D ?
					    "/" : "");
			case FTS_DP:
				rc = cbf(f, arg);
				if (rc) {
					pfl_fts_close(fp);
					return (rc);
				}
				break;
			default:
				if (f->fts_errno == 0)
					f->fts_errno = EOPNOTSUPP;
				psclog_warnx("%s: %s", f->fts_path,
				    strerror(f->fts_errno));
				break;
			}
		}
		pfl_fts_close(fp);
	} else {
		const char *basefn;
		size_t baselen;

		if (lstat(fn, &stb) == -1)
			err(1, "%s", fn);
		basefn = pfl_basename(fn);
		baselen = strlen(basefn);

		f = PSCALLOC(sizeof(*f) + baselen);
		f->fts_accpath = (char *)fn;
		f->fts_path = (char *)fn;
		f->fts_pathlen = strlen(fn);
		strlcpy(f->fts_name, basefn, baselen + 1);
		f->fts_namelen = baselen;
		f->fts_ino = stb.st_ino;
		f->fts_statp = &stb;
		switch (stb.st_mode & S_IFMT) {
		case S_IFDIR: f->fts_info = FTS_D; break;
		case S_IFREG: f->fts_info = FTS_F; break;
		case S_IFLNK: f->fts_info = FTS_SL; break;
		case S_IFBLK: f->fts_info = FTS_DEFAULT; break;
		default:
			psclog_warnx("%s: %s", fn,
			    strerror(EOPNOTSUPP));
			break;
		}
		rc = cbf(f, arg);
		PSCFREE(f);
	}
	return (rc);
}
コード例 #21
0
ファイル: main.c プロジェクト: pscedu/slash2-stable
int
main(int argc, char *argv[])
{
	char c, *p, *noncanon_mp, *cmd, *path_env, dir[PATH_MAX];
	struct pscfs_args args = PSCFS_ARGS_INIT(0, NULL);
	struct psc_dynarray startup_cmds = DYNARRAY_INIT;
	const char *progpath = argv[0];
	int rc, i, unmount_first = 0;

	pfl_init();

	pscfs_addarg(&args, "");		/* progname/argv[0] */
	pscfs_addarg(&args, "-o");
	pscfs_addarg(&args, STD_MOUNT_OPTIONS);

	p = getenv("CTL_SOCK_FILE");
	if (p)
		ctlsockfn = p;

	while ((c = getopt(argc, argv, "dL:o:S:U")) != -1)
		switch (c) {
		case 'd':
			pscfs_addarg(&args, "-odebug");
			break;
		case 'L':
			psc_dynarray_add(&startup_cmds, optarg);
			break;
		case 'o':
			if (!opt_lookup(optarg)) {
				pscfs_addarg(&args, "-o");
				pscfs_addarg(&args, optarg);
			}
			break;
		case 'S':
			ctlsockfn = optarg;
			break;
		case 'U':
			unmount_first = 1;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;
	if (argc != 1)
		usage();

	pscthr_init(PFL_THRT_FSMGR, NULL, 0, "fsmgrthr");

	noncanon_mp = argv[0];
	if (unmount_first)
		unmount(noncanon_mp);

	/* canonicalize mount path */
	if (realpath(noncanon_mp, mountpoint) == NULL)
		psc_fatal("realpath %s", noncanon_mp);

	pscfs_mount(mountpoint, &args);
	pscfs_freeargs(&args);

	ctlthr_spawn();

	pfl_opstimerthr_spawn(PFL_THRT_OPSTIMER, "opstimerthr");
	pfl_workq_init(128, 1024, 1024);
	pfl_wkthr_spawn(PFL_THRT_WORKER, 4, 0, "wkthr%d");

	pscfs_entry_timeout = 8.;
	pscfs_attr_timeout = 8.;

	/*
	 * Here, $p = (directory this daemon binary resides in).
	 * Now we add the following to $PATH:
	 *
	 *   1) $p
	 *   2) $p/../wokctl (for developers)
	 */
	pfl_dirname(progpath, dir);
	p = getenv("PATH");
	rc = pfl_asprintf(&path_env, "%s:%s/../wokctl%s%s", dir, dir,
	    p ? ":" : "", p ? p : "");
	psc_assert(rc != -1);
	setenv("PATH", path_env, 1);

	/*
 	 * If wokctl (see file wokctl.c) misbehaves because it is given 
 	 * a wrong arugment, it is hard to debug from our end because 
 	 * we won't be receiving anything useful via the socket. This 
 	 * should be changed to a native call someday.
 	 *
 	 * If the client does not come up, double/triple checkout 
 	 * the name of your slash2 shared library. I wish I can
 	 * add more verbose debugging information.
 	 */
	DYNARRAY_FOREACH(cmd, i, &startup_cmds)
		pfl_systemf("wokctl -S %s %s", ctlsockfn, cmd);

	exit(pscfs_main(32, ""));
}
コード例 #22
0
ファイル: vbitmap_test.c プロジェクト: pscedu/pfl
int
main(int argc, char *argv[])
{
	struct psc_vbitmap *vb, vba = VBITMAP_INIT_AUTO;
	size_t elem, j, cap, len, off;
	int i, c, u, t;

	pfl_init();
	while ((c = getopt(argc, argv, "")) != -1)
		switch (c) {
		default:
			usage();
		}

	argc -= optind;
	if (argc)
		usage();

	for (i = 0; i < 79; i++)
		if (psc_vbitmap_next(&vba, &j) != 1)
			psc_fatalx("psc_vbitmap_next failed with auto");
		else if (j != (size_t)i)
			psc_fatalx("elem %d is not supposed to be %zu", i, j);

	if ((vb = psc_vbitmap_new(213)) == NULL)
		psc_fatal("psc_vbitmap_new");

	psc_vbitmap_setrange(vb, 13, 9);
	psc_vbitmap_printbin1(vb);
	for (i = 0; i < 13; i++)
		pfl_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 9; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 25; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_clearall(vb);
	for (i = 0; i < 213; i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_setrange(vb, 25, 3);
	for (i = 0; i < 25; i++)
		pfl_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 3; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 25; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 0);

	psc_vbitmap_clearall(vb);
	for (i = 0; i < 213; i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 0);

	for (i = 0; i < 213; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements at pos %d", i);

	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	psc_vbitmap_getstats(vb, &u, &t);
	if (u != 213 || t != 213)
		psc_fatalx("wrong size, got %d,%d want %d", u, t, 213);

	psc_vbitmap_unsetrange(vb, 13, 2);
	for (i = 0; i < 13; i++)
		pfl_assert(psc_vbitmap_get(vb, i) == 1);
	for (j = 0; j < 2; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 0);
	for (j = 0; j < 25; j++, i++)
	    pfl_assert(psc_vbitmap_get(vb, i) == 1);

	if (psc_vbitmap_resize(vb, NELEM) == -1)
		psc_fatal("psc_vbitmap_resize");

	pfl_assert(psc_vbitmap_getsize(vb) == NELEM);

	/* fill up bitmap */
	for (i = 0; i < NELEM - 211; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements at iter %d", i);

	/* try one past end of filled bitmap */
	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	/* free some slots */
	for (i = 0, elem = 0; elem < NELEM; i++, elem += NELEM / 10)
		psc_vbitmap_unset(vb, elem);

	t = psc_vbitmap_nfree(vb);
	if (t != i)
		psc_fatalx("wrong number of free elements; has=%d want=%d", t, i);
	psc_vbitmap_invert(vb);
	t = psc_vbitmap_nfree(vb);
	if (t != NELEM - i)
		psc_fatalx("wrong number of inverted elements; has=%d want=%d",
		    t, NELEM - i);
	psc_vbitmap_invert(vb);
	t = psc_vbitmap_nfree(vb);
	if (t != i)
		psc_fatalx("wrong number of original elements; has=%d want=%d", t, i);

	/* try to re-grab the freed slots */
	for (i = 0; i <= 10; i++)
		if (!psc_vbitmap_next(vb, &elem))
			psc_fatalx("out of elements, request %d/%d", i, 10);

	/* try one past end of filled bitmap */
	if (psc_vbitmap_next(vb, &elem))
		psc_fatalx("an unexpected extra unused elem was found; pos=%zu", elem);

	psc_vbitmap_setval_range(vb, 0, NELEM, 0);
	CHECK_RANGE(vb, 0, 581, 371);
	CHECK_RANGE(vb, 0, 581, 1);
	pfl_assert(pfl_vbitmap_isempty(vb));

	psc_vbitmap_setval_range(vb, 0, NELEM, 1);
	CHECK_RANGE(vb, 1, 581, 371);
	CHECK_RANGE(vb, 1, 581, 1);
	pfl_assert(psc_vbitmap_isfull(vb));

	psc_vbitmap_free(vb);

	vb = psc_vbitmap_newf(0, PVBF_AUTO);
	pfl_assert(vb);
	pfl_assert(pfl_vbitmap_isempty(vb));
	pfl_assert(psc_vbitmap_getsize(vb) == 0);
	pfl_assert(psc_vbitmap_resize(vb, 6) == 0);
	pfl_assert(psc_vbitmap_getsize(vb) == 6);
	pfl_assert(pfl_vbitmap_isempty(vb));
	psc_vbitmap_free(vb);

	vb = psc_vbitmap_newf(0, PVBF_AUTO);
	cap = psc_vbitmap_getsize(vb);
	off = 0;
	len = 6;
	if (off + len > cap)
		psc_vbitmap_resize(vb, off + len);
	psc_vbitmap_setrange(vb, off, len);
	ENSURE(vb, "111111");
	CHECK_RANGE(vb, 1, 2, 4);

	psc_vbitmap_clearall(vb);
	pfl_assert(psc_vbitmap_setval_range(vb, 2, 4, 1) == 0);
	CHECK_RANGE(vb, 1, 2, 4);
	ENSURE(vb, "001111");
	psc_vbitmap_free(vb);

	vb = psc_vbitmap_new(0);
	for (i = 1; i < 101; i++) {
		if (psc_vbitmap_resize(vb, i) == -1)
			psc_fatal("psc_vbitmap_new");
		psc_vbitmap_setval(vb, i - 1, i % 2);
		pfl_assert(psc_vbitmap_get(vb, i - 1) == i % 2);
	}
	psc_vbitmap_free(vb);

	for (cap = 0; cap < 100; cap++) {
		for (off = 1; off < cap; off++) {
			for (len = 1; off + len < cap; len++) {
				size_t last;

				last = cap - off - len;
				vb = psc_vbitmap_new(cap);
				psc_vbitmap_setrange(vb, off, len);
				ENSURE(vb, "%0*d%*d%0*d", (int)off, 0,
				    (int)len, 1, (int)last, 0);
				CHECK_RANGE(vb, 0, 0, off);
				CHECK_RANGE(vb, 1, off, len);
				CHECK_RANGE(vb, 0, off+len, last);
				psc_vbitmap_free(vb);
			}
		}
	}

	vb = psc_vbitmap_new(8200);
	pfl_assert(pfl_vbitmap_isempty(vb));
	CHECK_RANGE(vb, 0, 8, 8192);
	psc_vbitmap_free(vb);

	vb = psc_vbitmap_new(16);
	ENSURE_ABBR(vb, "0:8,00000000");
	psc_vbitmap_free(vb);

	vb = psc_vbitmap_new(40);
	psc_vbitmap_setval_range(vb, 0, 10, 0);
	psc_vbitmap_setval_range(vb, 10, 10, 1);
	ENSURE(vb, "0000000000111111111100000000000000000000");
	ENSURE_ABBR(vb, "0:10,1:10,0:12,00000000");
	psc_vbitmap_free(vb);

	vb = psc_vbitmap_new(16);
	ENSURE(vb, "0000000000000000");
	pfl_assert(pfl_vbitmap_isempty(vb));
	CHECK_RANGE(vb, 0, 8, 8);
	CHECK_RANGE(vb, 0, 9, 7);
	psc_vbitmap_setval(vb, 15, 1);
	ENSURE(vb, "0000000000000001");
	CHECK_RANGE(vb, 0, 9, 6);
	CHECK_RANGE(vb, 1, 15, 1);
	pfl_assert(pfl_vbitmap_israngeset(vb, 0, 8, 8) == 0);
	pfl_assert(pfl_vbitmap_israngeset(vb, 1, 8, 8) == 0);
	psc_vbitmap_clearall(vb);
	pfl_assert(pfl_vbitmap_isempty(vb));
	psc_vbitmap_free(vb);

	exit(0);
}
コード例 #23
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
__static void
pflnet_getifnfordst_rtnetlink(const struct sockaddr *sa,
    char ifn[IFNAMSIZ])
{
	struct {
		struct nlmsghdr	nmh;
		struct rtmsg	rtm;
#define RT_SPACE 8192
		unsigned char	buf[RT_SPACE];
	} rq;
	const struct sockaddr_in *sin;
	struct nlmsghdr *nmh;
	struct rtattr *rta;
	struct rtmsg *rtm;
	ssize_t rc, rca;
	int s, ifidx;
	size_t nb;

	sin = (void *)sa;

	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (s == -1)
		psc_fatal("socket");

	memset(&rq, 0, sizeof(rq));
	rq.nmh.nlmsg_len = NLMSG_SPACE(sizeof(rq.rtm)) +
	    RTA_LENGTH(sizeof(sin->sin_addr));
	rq.nmh.nlmsg_flags = NLM_F_REQUEST;
	rq.nmh.nlmsg_type = RTM_GETROUTE;

	rq.rtm.rtm_family = sa->sa_family;
	rq.rtm.rtm_protocol = RTPROT_UNSPEC;
	rq.rtm.rtm_table = RT_TABLE_MAIN;
	/* # bits filled in target addr */
	rq.rtm.rtm_dst_len = sizeof(sin->sin_addr) * NBBY;
	rq.rtm.rtm_scope = RT_SCOPE_LINK;

	rta = (void *)((char *)&rq + NLMSG_SPACE(sizeof(rq.rtm)));
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(sizeof(sin->sin_addr));
	memcpy(RTA_DATA(rta), &sin->sin_addr,
	    sizeof(sin->sin_addr));

	errno = 0;
	rc = write(s, &rq, rq.nmh.nlmsg_len);
	if (rc != (ssize_t)rq.nmh.nlmsg_len)
		psc_fatal("routing socket length mismatch");

	rc = read(s, &rq, sizeof(rq));
	if (rc == -1)
		psc_fatal("routing socket read");
	close(s);

	switch (rq.nmh.nlmsg_type) {
	case NLMSG_ERROR: {
		struct nlmsgerr *nlerr;

		nlerr = NLMSG_DATA(&rq.nmh);
		psc_fatalx("netlink: %s", strerror(nlerr->error));
	    }
	case NLMSG_DONE:
		psc_fatalx("netlink: unexpected EOF");
	}

	nmh = &rq.nmh;
	nb = rc;
	for (; NLMSG_OK(nmh, nb); nmh = NLMSG_NEXT(nmh, nb)) {
		rtm = NLMSG_DATA(nmh);

		if (rtm->rtm_table != RT_TABLE_MAIN)
			continue;

		rta = RTM_RTA(rtm);
		rca = RTM_PAYLOAD(nmh);

		for (; RTA_OK(rta, rca); rta = RTA_NEXT(rta, rca)) {
			switch (rta->rta_type) {
			case RTA_OIF:
				memcpy(&ifidx, RTA_DATA(rta),
				    sizeof(ifidx));
				pflnet_getifname(ifidx, ifn);
				return;
			}
		}
	}
	psc_fatalx("no route for addr");
}
コード例 #24
0
ファイル: slmkjrnl.c プロジェクト: jasons-psc/slash2
/**
 * pjournal_format - Initialize an on-disk journal.
 * @fn: file path to store journal.
 * @nents: number of entries journal may contain.
 * @entsz: size of a journal entry.
 * Returns 0 on success, errno on error.
 */
void
pjournal_format(const char *fn, uint32_t nents, uint32_t entsz,
    uint32_t rs, uint64_t uuid)
{
	struct psc_journal_enthdr *pje;
	struct psc_journal pj;
	struct stat stb;
	unsigned char *jbuf;
	uint32_t i, j, slot;
	int rc, fd;
	ssize_t nb;

	if (nents % rs)
		psc_fatalx("number of slots (%u) should be a multiple of "
		    "readsize (%u)", nents, rs);

	memset(&pj, 0, sizeof(struct psc_journal));

	rc = 0;
	fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
	if (fd == -1)
		psc_fatal("%s", fn);

	if (fstat(fd, &stb) == -1)
		psc_fatal("stat %s", fn);

	pj.pj_fd = fd;
	pj.pj_hdr = PSCALLOC(PSC_ALIGN(sizeof(struct psc_journal_hdr),
	    stb.st_blksize));

	pj.pj_hdr->pjh_entsz = entsz;
	pj.pj_hdr->pjh_nents = nents;
	pj.pj_hdr->pjh_version = PJH_VERSION;
	pj.pj_hdr->pjh_readsize = rs;
	pj.pj_hdr->pjh_iolen = PSC_ALIGN(sizeof(struct psc_journal_hdr),
	    stb.st_blksize);
	pj.pj_hdr->pjh_magic = PJH_MAGIC;
	pj.pj_hdr->pjh_timestamp = time(NULL);
	pj.pj_hdr->pjh_fsuuid = uuid;

	psc_crc64_init(&pj.pj_hdr->pjh_chksum);
	psc_crc64_add(&pj.pj_hdr->pjh_chksum, pj.pj_hdr,
	    offsetof(struct psc_journal_hdr, pjh_chksum));
	psc_crc64_fini(&pj.pj_hdr->pjh_chksum);

	nb = pwrite(pj.pj_fd, pj.pj_hdr, pj.pj_hdr->pjh_iolen, 0);
	if ((size_t)nb != pj.pj_hdr->pjh_iolen)
		psc_fatalx("failed to write journal header: %s",
		    nb == -1 ? strerror(errno) : "short write");

	nb = PJ_PJESZ(&pj) * pj.pj_hdr->pjh_readsize;
	jbuf = psc_alloc(nb, PAF_PAGEALIGN);
	for (i = 0; i < rs; i++) {
		pje = PSC_AGP(jbuf, PJ_PJESZ(&pj) * i);
		pje->pje_magic = PJE_MAGIC;
		pje->pje_type = PJE_FORMAT;
		pje->pje_xid = PJE_XID_NONE;
		pje->pje_len = 0;

		psc_crc64_init(&pje->pje_chksum);
		psc_crc64_add(&pje->pje_chksum, pje,
		    offsetof(struct psc_journal_enthdr, pje_chksum));
		psc_crc64_add(&pje->pje_chksum, pje->pje_data,
		    pje->pje_len);
		psc_crc64_fini(&pje->pje_chksum);
	}

	j = 0;
	/* XXX use an option to write only one entry in fast create mode */
	for (slot = 0; slot < pj.pj_hdr->pjh_nents; slot += rs) {
		nb = pwrite(pj.pj_fd, jbuf, PJ_PJESZ(&pj) * rs,
		    PJ_GETENTOFF(&pj, slot));
		if ((size_t)nb != PJ_PJESZ(&pj) * rs)
			psc_fatal("failed to write slot %u (%zd)",
			    slot, nb);
		if (verbose && slot % 262144 == 0) {
			printf(".");
			fflush(stdout);
			fsync(pj.pj_fd);
			if (++j == 80) {
				printf("\n");
				j = 0;
			}
		}
	}
	if (verbose && j)
		printf("\n");
	if (close(fd) == -1)
		psc_fatal("failed to close journal");
	psc_free(jbuf, PAF_PAGEALIGN, PJ_PJESZ(&pj) * rs);
	psclog_info("journal %s formatted: %d slots, %d readsize, error=%d",
	    fn, nents, rs, rc);
}
コード例 #25
0
ファイル: slmkjrnl.c プロジェクト: jasons-psc/slash2
/**
 * pjournal_dump - Dump the contents of a journal file.
 * @fn: journal filename to query.
 * @verbose: whether to report stats summary or full dump.
 *
 * Each time mds restarts, it writes log entries starting from the very
 * first slot of the log.  Anyway, the function dumps all log entries,
 * some of them may be from previous incarnations of the MDS.
 */
void
pjournal_dump(const char *fn)
{
	int i, ntotal, nmagic, nchksum, nformat, ndump, first = 1;
	uint32_t slot, highest_slot = -1, lowest_slot = -1;
	uint64_t chksum, highest_xid = 0, lowest_xid = 0;
	struct psc_journal_enthdr *pje;
	struct psc_journal_hdr *pjh;
	struct psc_journal *pj;
	struct stat statbuf;
	unsigned char *jbuf;
	ssize_t nb, pjhlen;
	time_t ts;

	ntotal = nmagic = nchksum = nformat = ndump = 0;

	pj = PSCALLOC(sizeof(*pj));

	strlcpy(pj->pj_name, pfl_basename(fn), sizeof(pj->pj_name));

	pj->pj_fd = open(fn, O_RDWR | O_DIRECT);
	if (pj->pj_fd == -1)
		psc_fatal("failed to open journal %s", fn);
	if (fstat(pj->pj_fd, &statbuf) == -1)
		psc_fatal("failed to stat journal %s", fn);

	/*
	 * O_DIRECT may impose alignment restrictions so align the
	 * buffer and perform I/O in multiples of file system block
	 * size.
	 */
	pjhlen = PSC_ALIGN(sizeof(*pjh), statbuf.st_blksize);
	pjh = psc_alloc(pjhlen, PAF_PAGEALIGN);
	nb = pread(pj->pj_fd, pjh, pjhlen, 0);
	if (nb != pjhlen)
		psc_fatal("failed to read journal header");

	pj->pj_hdr = pjh;
	if (pjh->pjh_magic != PJH_MAGIC)
		psc_fatalx("journal header has a bad magic number "
		    "%#"PRIx64, pjh->pjh_magic);

	if (pjh->pjh_version != PJH_VERSION)
		psc_fatalx("journal header has an invalid version "
		    "number %d", pjh->pjh_version);

	psc_crc64_init(&chksum);
	psc_crc64_add(&chksum, pjh, offsetof(struct psc_journal_hdr,
	    pjh_chksum));
	psc_crc64_fini(&chksum);

	if (pjh->pjh_chksum != chksum)
		psc_fatalx("journal header has an invalid checksum "
		    "value %"PSCPRIxCRC64" vs %"PSCPRIxCRC64,
		    pjh->pjh_chksum, chksum);

	if (S_ISREG(statbuf.st_mode) && statbuf.st_size !=
	    (off_t)(pjhlen + pjh->pjh_nents * PJ_PJESZ(pj)))
		psc_fatalx("size of the journal log %"PSCPRIdOFFT"d does "
		    "not match specs in its header", statbuf.st_size);

	if (pjh->pjh_nents % pjh->pjh_readsize)
		psc_fatalx("number of entries %d is not a multiple of the "
		    "readsize %d", pjh->pjh_nents, pjh->pjh_readsize);

	ts = pjh->pjh_timestamp;

	printf("%s:\n"
	    "  version: %u\n"
	    "  entry size: %u\n"
	    "  number of entries: %u\n"
	    "  batch read size: %u\n"
	    "  entry start offset: %"PRId64"\n"
	    "  format time: %s"
	    "  uuid: %"PRIx64"\n"
	    "  %4s  %3s %4s %4s %s\n",
	    fn, pjh->pjh_version, PJ_PJESZ(pj), pjh->pjh_nents,
	    pjh->pjh_readsize, pjh->pjh_start_off,
	    ctime(&ts), pjh->pjh_fsuuid,
	    "idx", "typ", "xid", "txg", "details");

	jbuf = psc_alloc(PJ_PJESZ(pj) * pj->pj_hdr->pjh_readsize,
	    PAF_PAGEALIGN);
	for (slot = 0; slot < pjh->pjh_nents;
	    slot += pjh->pjh_readsize) {
		nb = pread(pj->pj_fd, jbuf, PJ_PJESZ(pj) *
		    pjh->pjh_readsize, PJ_GETENTOFF(pj, slot));
		if (nb != PJ_PJESZ(pj) * pjh->pjh_readsize)
			warn("failed to read %d log entries at slot %d",
			    pjh->pjh_readsize, slot);

		for (i = 0; i < pjh->pjh_readsize; i++) {
			ntotal++;
			pje = (void *)&jbuf[PJ_PJESZ(pj) * i];
			if (pje->pje_magic != PJE_MAGIC) {
				nmagic++;
				warnx("journal slot %d has a bad magic"
				    "number", slot + i);
				continue;
			}

			/*
			 * If we hit a new entry that is never used, we
			 * assume that the rest of the journal is never
			 * used.
			 */
			if (pje->pje_type == PJE_FORMAT) {
				nformat = nformat + pjh->pjh_nents -
				    (slot + i);
				goto done;
			}

			psc_crc64_init(&chksum);
			psc_crc64_add(&chksum, pje, offsetof(
			    struct psc_journal_enthdr, pje_chksum));
			psc_crc64_add(&chksum, pje->pje_data,
			    pje->pje_len);
			psc_crc64_fini(&chksum);

			if (pje->pje_chksum != chksum) {
				nchksum++;
				warnx("journal slot %d has a corrupt "
				    "checksum", slot + i);
				goto done;
			}
			ndump++;
			if (verbose)
				pjournal_dump_entry(slot + i, pje);
			if (first) {
				first = 0;
				highest_xid = lowest_xid = pje->pje_xid;
				highest_slot = lowest_slot = slot + i;
				continue;
			}
			if (highest_xid < pje->pje_xid) {
				highest_xid = pje->pje_xid;
				highest_slot = slot + i;
			}
			if (lowest_xid > pje->pje_xid) {
				lowest_xid = pje->pje_xid;
				lowest_slot = slot + i;
			}
		}

	}

 done:
	if (close(pj->pj_fd) == -1)
		printf("failed closing journal %s", fn);

	psc_free(jbuf, PAF_PAGEALIGN, PJ_PJESZ(pj));
	PSCFREE(pj);

	printf("----------------------------------------------\n"
	    "%8d slot(s) scanned\n"
	    "%8d in use\n"
	    "%8d formatted\n"
	    "%8d bad magic\n"
	    "%8d bad checksum(s)\n"
	    "lowest transaction ID=%#"PRIx64" (slot=%d)\n"
	    "highest transaction ID=%#"PRIx64" (slot=%d)\n",
	    ntotal, ndump, nformat, nmagic, nchksum,
	    lowest_xid, lowest_slot,
	    highest_xid, highest_slot);
}
コード例 #26
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
__static int
pflnet_rtexists_rtnetlink(const struct sockaddr *sa)
{
	struct {
		struct nlmsghdr	nmh;
		struct rtmsg	rtm;
#define RT_SPACE 8192
		unsigned char	buf[RT_SPACE];
		struct rtattr	rta;
		struct nlmsgerr	nlerr;
	} rq;
	struct sockaddr_in *sin = (void *)sa;
	in_addr_t cmpaddr, zero = 0;
	struct nlmsghdr *nmh;
	struct rtattr *rta;
	struct rtmsg *rtm;
	ssize_t rc, rca;
	int rv = 0, s;
	size_t nb;

	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (s == -1)
		psc_fatal("socket");

	memset(&rq, 0, sizeof(rq));
	rq.nmh.nlmsg_len = NLMSG_SPACE(sizeof(rq.rtm));
	rq.nmh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
	rq.nmh.nlmsg_type = RTM_GETROUTE;

	rq.rtm.rtm_family = sa->sa_family;
	rq.rtm.rtm_protocol = RTPROT_UNSPEC;
	rq.rtm.rtm_table = RT_TABLE_MAIN;
	rq.rtm.rtm_scope = RT_SCOPE_LINK;

	rta = (void *)((char *)&rq.rta + NLMSG_SPACE(sizeof(rq.rtm)));
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(sizeof(sin->sin_addr));
	memcpy(RTA_DATA(rta), &sin->sin_addr,
	    sizeof(sin->sin_addr));

	errno = 0;
	rc = write(s, &rq, rq.nmh.nlmsg_len);
	if (rc != (ssize_t)rq.nmh.nlmsg_len)
		psc_fatal("routing socket length mismatch");

	for (;;) {
		rc = read(s, &rq, sizeof(rq));
		if (rc == -1)
			psc_fatal("routing socket read");

		switch (rq.nmh.nlmsg_type) {
		case NLMSG_ERROR: {
			struct nlmsgerr *nlerr;

			nlerr = NLMSG_DATA(&rq.nlerr);
			psc_fatalx("netlink: %s", strerror(nlerr->error));
		    }
		case NLMSG_DONE:
			goto out;
		}

		nmh = &rq.nmh;
		nb = rc;
		for (; NLMSG_OK(nmh, nb); nmh = NLMSG_NEXT(nmh, nb)) {
			rtm = NLMSG_DATA(nmh);

			if (rtm->rtm_table != RT_TABLE_MAIN)
				continue;

			rta = RTM_RTA(rtm);
			rca = RTM_PAYLOAD(nmh);

			for (; RTA_OK(rta, rca);
			    rta = RTA_NEXT(rta, rca)) {
				switch (rta->rta_type) {
				case RTA_GATEWAY:
					cmpaddr = sin->sin_addr.s_addr;
					if (zero == cmpaddr) {
						rv = 1;
						goto out;
					}
					break;
				case RTA_DST:
					cmpaddr = sin->sin_addr.s_addr;

					pfl_bitstr_copy(&cmpaddr,
					    rtm->rtm_dst_len, &zero, 0,
					    sizeof(zero) * NBBY -
					    rtm->rtm_dst_len);

					if (cmpaddr == *(in_addr_t *)
					    RTA_DATA(rta)) {
						rv = 1;
						goto out;
					}
					break;
				}
			}
		}
	}
 out:
	close(s);
	return (rv);
}
コード例 #27
0
ファイル: netutil.c プロジェクト: zhihui-slash2/slash2-stable
__static void
pflnet_getifnfordst_rtsock(const struct sockaddr *sa, char ifn[IFNAMSIZ])
{
	struct {
		struct rt_msghdr	rtm;
#define RT_SPACE 512
		unsigned char		buf[RT_SPACE];
	} m;
	struct rt_msghdr *rtm = &m.rtm;
	union pfl_sockaddr psa, *psap;
	unsigned char *p = m.buf;
	ssize_t len, rc;
	pid_t pid;
	int j, s;

	memset(&m, 0, sizeof(m));

#ifdef HAVE_SA_LEN
#define ADDSOCKADDR(p, sa)						\
	do {								\
		memcpy((p), (sa), (sa)->sa_len);			\
		(p) += SOCKADDR_GETLEN(sa);					\
	} while (0)
#else
#define ADDSOCKADDR(p, sa)						\
	do {								\
		memcpy((p), (sa), sizeof(*(sa)));			\
		(p) += SOCKADDR_GETLEN(sa);					\
	} while (0)
#endif

	ADDSOCKADDR(p, sa);

	memset(&psa, 0, sizeof(psa));
	psa.sdl.sdl_family = AF_LINK;
#ifdef HAVE_SA_LEN
	psa.sdl.sdl_len = sizeof(psa.sdl);
#endif
	ADDSOCKADDR(p, &psa.sa);

	rtm->rtm_type = RTM_GET;
	rtm->rtm_flags = RTF_STATIC | RTF_UP | RTF_HOST | RTF_GATEWAY;
	rtm->rtm_version = RTM_VERSION;
	rtm->rtm_addrs = RTA_DST | RTA_IFP;
#ifdef HAVE_RTM_HDRLEN
	rtm->rtm_hdrlen = sizeof(m.rtm);
#endif
	rtm->rtm_msglen = len = p - (unsigned char *)&m;

	s = socket(PF_ROUTE, SOCK_RAW, 0);
	if (s == -1)
		psc_fatal("socket");

	rc = write(s, &m, len);
	if (rc == -1)
		psc_fatal("writing to routing socket");
	if (rc != len)
		psc_fatalx("writing to routing socket: short write");

	pid = getpid();
	do {
		rc = read(s, &m, sizeof(m));
	} while (rc > 0 && (rtm->rtm_version != RTM_VERSION ||
	    rtm->rtm_seq || rtm->rtm_pid != pid));

	if (rc == -1)
		psc_fatal("read from routing socket");

	if (rtm->rtm_version != RTM_VERSION)
		psc_fatalx("routing message version mismatch; has=%d got=%d",
		    RTM_VERSION, rtm->rtm_version);
	if (rtm->rtm_errno)
		psc_fatalx("routing error: %s", strerror(rtm->rtm_errno));
	if (rtm->rtm_msglen > rc)
		psc_fatalx("routing message too large");

	close(s);

	p = m.buf;
	for (; rtm->rtm_addrs; rtm->rtm_addrs &= ~(1 << j),
	    p += SOCKADDR_GETLEN(&psap->sa)) {
		j = ffs(rtm->rtm_addrs) - 1;
		psap = (void *)p;
		switch (1 << j) {
		case RTA_IFP:
			if (psap->sdl.sdl_family == AF_LINK &&
			    psap->sdl.sdl_nlen) {
				strncpy(ifn, psap->sdl.sdl_data, IFNAMSIZ - 1);
				ifn[IFNAMSIZ - 1] = '\0';
				return;
			}
			break;
		}
	}

	psc_fatalx("interface message not received");
}
コード例 #28
0
ファイル: rmm.c プロジェクト: jasons-psc/slash2
int
slm_rmm_apply_update(__unusedx struct srt_update_entry *entryp)
{
	psc_fatal("obsolete code path");
}