Merge ^/head r286697 through r286857.
This commit is contained in:
commit
6fdf637e23
@ -220,7 +220,7 @@ INSTALLTMP!= /usr/bin/mktemp -d -u -t install
|
||||
# This stage is responsible for creating the object
|
||||
# tree and building any tools that are needed during
|
||||
# the build process. Some programs are listed during
|
||||
# this phase because they build binaires to generate
|
||||
# this phase because they build binaries to generate
|
||||
# files needed to build these programs. This stage also
|
||||
# builds the 'build-tools' target rather than 'all'.
|
||||
# 3. cross-tools stage [XMAKE]
|
||||
@ -1494,7 +1494,7 @@ _btxld= usr.sbin/btxld
|
||||
.if ${MK_BINUTILS_BOOTSTRAP} != "no"
|
||||
_binutils= gnu/usr.bin/binutils
|
||||
.endif
|
||||
.if ${MK_ELFTOOLCHAIN_TOOLS} != "no"
|
||||
.if ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no"
|
||||
_elftctools= lib/libelftc \
|
||||
usr.bin/elfcopy \
|
||||
usr.bin/nm \
|
||||
@ -1504,7 +1504,7 @@ _elftctools= lib/libelftc \
|
||||
# cross-build on a FreeBSD 10 host:
|
||||
_elftctools+= usr.bin/addr2line
|
||||
.endif
|
||||
.elif ${TARGET_ARCH} != ${MACHINE_ARCH} && ${MK_ELFTOOLCHAIN_TOOLS} != "no"
|
||||
.elif ${TARGET_ARCH} != ${MACHINE_ARCH} && ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no"
|
||||
# If cross-building with an external binutils we still need to build strip for
|
||||
# the target (for at least crunchide).
|
||||
_elftctools= lib/libelftc \
|
||||
|
20
UPDATING
20
UPDATING
@ -36,6 +36,26 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
|
||||
20141231 entry below for information about prerequisites and upgrading,
|
||||
if you are not already using 3.5.0 or higher.
|
||||
|
||||
20150817:
|
||||
Kernel-loadable modules for the random(4) device are back. To use
|
||||
them, the kernel must have
|
||||
|
||||
device random
|
||||
options RANDOM_LOADABLE
|
||||
|
||||
kldload(8) can then be used to load random_fortuna.ko
|
||||
or random_yarrow.ko. Please note that due to the indirect
|
||||
function calls that the loadable modules need to provide,
|
||||
the build-in variants will be slightly more efficient.
|
||||
|
||||
The random(4) kernel option RANDOM_DUMMY has been retired due to
|
||||
unpopularity. It was not all that useful anyway.
|
||||
|
||||
20150813:
|
||||
The WITHOUT_ELFTOOLCHAIN_TOOLS src.conf(5) knob has been retired.
|
||||
Control over building the ELF Tool Chain tools is now provided by
|
||||
the WITHOUT_TOOLCHAIN knob.
|
||||
|
||||
20150810:
|
||||
The polarity of Pulse Per Second (PPS) capture events with the
|
||||
uart(4) driver has been corrected. Prior to this change the PPS
|
||||
|
@ -191,9 +191,10 @@ readcmd(int argc __unused, char **argv __unused)
|
||||
CHECKSTRSPACE(1, p);
|
||||
if (backslash) {
|
||||
backslash = 0;
|
||||
startword = 0;
|
||||
if (c != '\n')
|
||||
if (c != '\n') {
|
||||
startword = 0;
|
||||
USTPUTC(c, p);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!rflag && c == '\\') {
|
||||
|
@ -73,6 +73,7 @@ char *minusc; /* argument to -c option */
|
||||
static void options(int);
|
||||
static void minus_o(char *, int);
|
||||
static void setoption(int, int);
|
||||
static void setoptionbyindex(int, int);
|
||||
static int getopts(char *, char *, char **, char ***, char **);
|
||||
|
||||
|
||||
@ -269,7 +270,7 @@ minus_o(char *name, int val)
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
setoption(optlist[i].letter, val);
|
||||
setoptionbyindex(i, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -o %s", name);
|
||||
@ -278,26 +279,32 @@ minus_o(char *name, int val)
|
||||
|
||||
|
||||
static void
|
||||
setoption(int flag, int val)
|
||||
setoptionbyindex(int idx, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (flag == 'p' && !val && privileged) {
|
||||
if (optlist[idx].letter == 'p' && !val && privileged) {
|
||||
if (setgid(getgid()) == -1)
|
||||
error("setgid");
|
||||
if (setuid(getuid()) == -1)
|
||||
error("setuid");
|
||||
}
|
||||
optlist[idx].val = val;
|
||||
if (val) {
|
||||
/* #%$ hack for ksh semantics */
|
||||
if (optlist[idx].letter == 'V')
|
||||
Eflag = 0;
|
||||
else if (optlist[idx].letter == 'E')
|
||||
Vflag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setoption(int flag, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].letter == flag) {
|
||||
optlist[i].val = val;
|
||||
if (val) {
|
||||
/* #%$ hack for ksh semantics */
|
||||
if (flag == 'V')
|
||||
Eflag = 0;
|
||||
else if (flag == 'E')
|
||||
Vflag = 0;
|
||||
}
|
||||
setoptionbyindex(i, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -%c", flag);
|
||||
|
@ -121,6 +121,7 @@ FILES+= read4.0 read4.0.stdout
|
||||
FILES+= read5.0
|
||||
FILES+= read6.0
|
||||
FILES+= read7.0
|
||||
FILES+= read8.0
|
||||
FILES+= return1.0
|
||||
FILES+= return2.1
|
||||
FILES+= return3.1
|
||||
|
17
bin/sh/tests/builtins/read8.0
Normal file
17
bin/sh/tests/builtins/read8.0
Normal file
@ -0,0 +1,17 @@
|
||||
# $FreeBSD$
|
||||
|
||||
read a b c <<\EOF
|
||||
\
|
||||
A\
|
||||
\
|
||||
\
|
||||
\
|
||||
B\
|
||||
\
|
||||
\
|
||||
C\
|
||||
\
|
||||
\
|
||||
\
|
||||
EOF
|
||||
[ "$a.$b.$c" = "A.B.C" ]
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -2221,7 +2221,7 @@ dump_label(const char *dev)
|
||||
(void) close(fd);
|
||||
}
|
||||
|
||||
static uint64_t num_large_blocks;
|
||||
static uint64_t dataset_feature_count[SPA_FEATURES];
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
@ -2235,8 +2235,15 @@ dump_one_dir(const char *dsname, void *arg)
|
||||
(void) printf("Could not open %s, error %d\n", dsname, error);
|
||||
return (0);
|
||||
}
|
||||
if (dmu_objset_ds(os)->ds_large_blocks)
|
||||
num_large_blocks++;
|
||||
|
||||
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
|
||||
if (!dmu_objset_ds(os)->ds_feature_inuse[f])
|
||||
continue;
|
||||
ASSERT(spa_feature_table[f].fi_flags &
|
||||
ZFEATURE_FLAG_PER_DATASET);
|
||||
dataset_feature_count[f]++;
|
||||
}
|
||||
|
||||
dump_dir(os);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
fuid_table_destroy();
|
||||
@ -2428,6 +2435,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
dmu_object_type_t type;
|
||||
boolean_t is_metadata;
|
||||
|
||||
if (bp == NULL)
|
||||
return (0);
|
||||
|
||||
if (dump_opt['b'] >= 5 && bp->blk_birth > 0) {
|
||||
char blkbuf[BP_SPRINTF_LEN];
|
||||
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
|
||||
@ -2917,7 +2927,7 @@ zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
avl_index_t where;
|
||||
zdb_ddt_entry_t *zdde, zdde_search;
|
||||
|
||||
if (BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
|
||||
if (bp == NULL || BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
|
||||
return (0);
|
||||
|
||||
if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
|
||||
@ -3032,7 +3042,6 @@ dump_zpool(spa_t *spa)
|
||||
dump_metaslab_groups(spa);
|
||||
|
||||
if (dump_opt['d'] || dump_opt['i']) {
|
||||
uint64_t refcount;
|
||||
dump_dir(dp->dp_meta_objset);
|
||||
if (dump_opt['d'] >= 3) {
|
||||
dump_full_bpobj(&spa->spa_deferred_bpobj,
|
||||
@ -3054,17 +3063,29 @@ dump_zpool(spa_t *spa)
|
||||
(void) dmu_objset_find(spa_name(spa), dump_one_dir,
|
||||
NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
|
||||
|
||||
(void) feature_get_refcount(spa,
|
||||
&spa_feature_table[SPA_FEATURE_LARGE_BLOCKS], &refcount);
|
||||
if (num_large_blocks != refcount) {
|
||||
(void) printf("large_blocks feature refcount mismatch: "
|
||||
"expected %lld != actual %lld\n",
|
||||
(longlong_t)num_large_blocks,
|
||||
(longlong_t)refcount);
|
||||
rc = 2;
|
||||
} else {
|
||||
(void) printf("Verified large_blocks feature refcount "
|
||||
"is correct (%llu)\n", (longlong_t)refcount);
|
||||
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
|
||||
uint64_t refcount;
|
||||
|
||||
if (!(spa_feature_table[f].fi_flags &
|
||||
ZFEATURE_FLAG_PER_DATASET)) {
|
||||
ASSERT0(dataset_feature_count[f]);
|
||||
continue;
|
||||
}
|
||||
(void) feature_get_refcount(spa,
|
||||
&spa_feature_table[f], &refcount);
|
||||
if (dataset_feature_count[f] != refcount) {
|
||||
(void) printf("%s feature refcount mismatch: "
|
||||
"%lld datasets != %lld refcount\n",
|
||||
spa_feature_table[f].fi_uname,
|
||||
(longlong_t)dataset_feature_count[f],
|
||||
(longlong_t)refcount);
|
||||
rc = 2;
|
||||
} else {
|
||||
(void) printf("Verified %s feature refcount "
|
||||
"of %llu is correct\n",
|
||||
spa_feature_table[f].fi_uname,
|
||||
(longlong_t)refcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rc == 0 && (dump_opt['b'] || dump_opt['c']))
|
||||
|
@ -191,11 +191,13 @@
|
||||
.Nm
|
||||
.Cm receive Ns | Ns Cm recv
|
||||
.Op Fl vnFu
|
||||
.Op Fl o Sy origin Ns = Ns Ar snapshot
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||
.Nm
|
||||
.Cm receive Ns | Ns Cm recv
|
||||
.Op Fl vnFu
|
||||
.Op Fl d | e
|
||||
.Op Fl o Sy origin Ns = Ns Ar snapshot
|
||||
.Ar filesystem
|
||||
.Nm
|
||||
.Cm allow
|
||||
@ -2705,6 +2707,7 @@ feature.
|
||||
.Nm
|
||||
.Cm receive Ns | Ns Cm recv
|
||||
.Op Fl vnFu
|
||||
.Op Fl o Sy origin Ns = Ns Ar snapshot
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||
.Xc
|
||||
.It Xo
|
||||
@ -2712,6 +2715,7 @@ feature.
|
||||
.Cm receive Ns | Ns Cm recv
|
||||
.Op Fl vnFu
|
||||
.Op Fl d | e
|
||||
.Op Fl o Sy origin Ns = Ns Ar snapshot
|
||||
.Ar filesystem
|
||||
.Xc
|
||||
.Pp
|
||||
@ -2796,6 +2800,10 @@ receive operation.
|
||||
Do not actually receive the stream. This can be useful in conjunction with the
|
||||
.Fl v
|
||||
option to verify the name the receive operation would use.
|
||||
.It Fl o Sy origin Ns = Ns Ar snapshot
|
||||
Forces the stream to be received as a clone of the given snapshot.
|
||||
This is only valid if the stream is an incremental stream whose source
|
||||
is the same as the provided origin.
|
||||
.It Fl F
|
||||
Force a rollback of the file system to the most recent snapshot before
|
||||
performing the receive operation. If receiving an incremental replication
|
||||
|
@ -264,8 +264,9 @@ get_usage(zfs_help_t idx)
|
||||
return (gettext("\tpromote <clone-filesystem>\n"));
|
||||
case HELP_RECEIVE:
|
||||
return (gettext("\treceive|recv [-vnFu] <filesystem|volume|"
|
||||
"snapshot>\n"
|
||||
"\treceive|recv [-vnFu] [-d | -e] <filesystem>\n"));
|
||||
"snapshot>\n"
|
||||
"\treceive|recv [-vnFu] [-o origin=<snapshot>] [-d | -e] "
|
||||
"<filesystem>\n"));
|
||||
case HELP_RENAME:
|
||||
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
|
||||
"<filesystem|volume|snapshot>\n"
|
||||
@ -791,7 +792,7 @@ zfs_do_create(int argc, char **argv)
|
||||
nomem();
|
||||
break;
|
||||
case 'o':
|
||||
if (parseprop(props, optarg))
|
||||
if (parseprop(props, optarg) != 0)
|
||||
goto error;
|
||||
break;
|
||||
case 's':
|
||||
@ -3659,7 +3660,7 @@ zfs_do_snapshot(int argc, char **argv)
|
||||
while ((c = getopt(argc, argv, "ro:")) != -1) {
|
||||
switch (c) {
|
||||
case 'o':
|
||||
if (parseprop(props, optarg))
|
||||
if (parseprop(props, optarg) != 0)
|
||||
return (1);
|
||||
break;
|
||||
case 'r':
|
||||
@ -3918,10 +3919,19 @@ zfs_do_receive(int argc, char **argv)
|
||||
{
|
||||
int c, err;
|
||||
recvflags_t flags = { 0 };
|
||||
nvlist_t *props;
|
||||
nvpair_t *nvp = NULL;
|
||||
|
||||
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
||||
nomem();
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, ":denuvF")) != -1) {
|
||||
while ((c = getopt(argc, argv, ":o:denuvF")) != -1) {
|
||||
switch (c) {
|
||||
case 'o':
|
||||
if (parseprop(props, optarg) != 0)
|
||||
return (1);
|
||||
break;
|
||||
case 'd':
|
||||
flags.isprefix = B_TRUE;
|
||||
break;
|
||||
@ -3966,6 +3976,13 @@ zfs_do_receive(int argc, char **argv)
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
while ((nvp = nvlist_next_nvpair(props, nvp))) {
|
||||
if (strcmp(nvpair_name(nvp), "origin") != 0) {
|
||||
(void) fprintf(stderr, gettext("invalid option"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("Error: Backup stream can not be read "
|
||||
@ -3974,7 +3991,7 @@ zfs_do_receive(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, NULL);
|
||||
err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
|
||||
|
||||
return (err != 0);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -294,8 +294,8 @@ zhack_feature_enable_sync(void *arg, dmu_tx_t *tx)
|
||||
feature_enable_sync(spa, feature, tx);
|
||||
|
||||
spa_history_log_internal(spa, "zhack enable feature", tx,
|
||||
"name=%s can_readonly=%u",
|
||||
feature->fi_guid, feature->fi_can_readonly);
|
||||
"guid=%s flags=%x",
|
||||
feature->fi_guid, feature->fi_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -314,9 +314,7 @@ zhack_do_feature_enable(int argc, char **argv)
|
||||
*/
|
||||
desc = NULL;
|
||||
feature.fi_uname = "zhack";
|
||||
feature.fi_mos = B_FALSE;
|
||||
feature.fi_can_readonly = B_FALSE;
|
||||
feature.fi_activate_on_enable = B_FALSE;
|
||||
feature.fi_flags = 0;
|
||||
feature.fi_depends = nodeps;
|
||||
feature.fi_feature = SPA_FEATURE_NONE;
|
||||
|
||||
@ -324,7 +322,7 @@ zhack_do_feature_enable(int argc, char **argv)
|
||||
while ((c = getopt(argc, argv, "rmd:")) != -1) {
|
||||
switch (c) {
|
||||
case 'r':
|
||||
feature.fi_can_readonly = B_TRUE;
|
||||
feature.fi_flags |= ZFEATURE_FLAG_READONLY_COMPAT;
|
||||
break;
|
||||
case 'd':
|
||||
desc = strdup(optarg);
|
||||
@ -413,7 +411,7 @@ zhack_do_feature_ref(int argc, char **argv)
|
||||
* disk later.
|
||||
*/
|
||||
feature.fi_uname = "zhack";
|
||||
feature.fi_mos = B_FALSE;
|
||||
feature.fi_flags = 0;
|
||||
feature.fi_desc = NULL;
|
||||
feature.fi_depends = nodeps;
|
||||
feature.fi_feature = SPA_FEATURE_NONE;
|
||||
@ -422,7 +420,7 @@ zhack_do_feature_ref(int argc, char **argv)
|
||||
while ((c = getopt(argc, argv, "md")) != -1) {
|
||||
switch (c) {
|
||||
case 'm':
|
||||
feature.fi_mos = B_TRUE;
|
||||
feature.fi_flags |= ZFEATURE_FLAG_MOS;
|
||||
break;
|
||||
case 'd':
|
||||
decr = B_TRUE;
|
||||
@ -455,10 +453,10 @@ zhack_do_feature_ref(int argc, char **argv)
|
||||
|
||||
if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
|
||||
feature.fi_guid)) {
|
||||
feature.fi_can_readonly = B_FALSE;
|
||||
feature.fi_flags &= ~ZFEATURE_FLAG_READONLY_COMPAT;
|
||||
} else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
|
||||
feature.fi_guid)) {
|
||||
feature.fi_can_readonly = B_TRUE;
|
||||
feature.fi_flags |= ZFEATURE_FLAG_READONLY_COMPAT;
|
||||
} else {
|
||||
fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
|
||||
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
|
||||
@ -4986,7 +4986,8 @@ zpool_do_upgrade(int argc, char **argv)
|
||||
"---------------\n");
|
||||
for (i = 0; i < SPA_FEATURES; i++) {
|
||||
zfeature_info_t *fi = &spa_feature_table[i];
|
||||
const char *ro = fi->fi_can_readonly ?
|
||||
const char *ro =
|
||||
(fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
|
||||
" (read-only compatible)" : "";
|
||||
|
||||
(void) printf("%-37s%s\n", fi->fi_uname, ro);
|
||||
|
@ -3586,7 +3586,8 @@ ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id)
|
||||
*/
|
||||
n = ztest_random(regions) * stride + ztest_random(width);
|
||||
s = 1 + ztest_random(2 * width - 1);
|
||||
dmu_prefetch(os, bigobj, n * chunksize, s * chunksize);
|
||||
dmu_prefetch(os, bigobj, 0, n * chunksize, s * chunksize,
|
||||
ZIO_PRIORITY_SYNC_READ);
|
||||
|
||||
/*
|
||||
* Pick a random index and compute the offsets into packobj and bigobj.
|
||||
@ -5705,8 +5706,10 @@ ztest_run(ztest_shared_t *zs)
|
||||
* Right before closing the pool, kick off a bunch of async I/O;
|
||||
* spa_close() should wait for it to complete.
|
||||
*/
|
||||
for (uint64_t object = 1; object < 50; object++)
|
||||
dmu_prefetch(spa->spa_meta_objset, object, 0, 1ULL << 20);
|
||||
for (uint64_t object = 1; object < 50; object++) {
|
||||
dmu_prefetch(spa->spa_meta_objset, object, 0, 0, 1ULL << 20,
|
||||
ZIO_PRIORITY_SYNC_READ);
|
||||
}
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
@ -5905,6 +5908,7 @@ ztest_init(ztest_shared_t *zs)
|
||||
}
|
||||
VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props, NULL));
|
||||
nvlist_free(nvroot);
|
||||
nvlist_free(props);
|
||||
|
||||
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
|
||||
zs->zs_metaslab_sz =
|
||||
|
@ -668,8 +668,8 @@ typedef struct recvflags {
|
||||
boolean_t nomount;
|
||||
} recvflags_t;
|
||||
|
||||
extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t *,
|
||||
int, avl_tree_t *);
|
||||
extern int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *,
|
||||
recvflags_t *, int, avl_tree_t *);
|
||||
|
||||
typedef enum diff_flags {
|
||||
ZFS_DIFF_PARSEABLE = 0x1,
|
||||
|
@ -3535,7 +3535,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
|
||||
}
|
||||
|
||||
static int
|
||||
zbookmark_compare(const void *a, const void *b)
|
||||
zbookmark_mem_compare(const void *a, const void *b)
|
||||
{
|
||||
return (memcmp(a, b, sizeof (zbookmark_phys_t)));
|
||||
}
|
||||
@ -3598,7 +3598,7 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
|
||||
zc.zc_nvlist_dst_size;
|
||||
count -= zc.zc_nvlist_dst_size;
|
||||
|
||||
qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_compare);
|
||||
qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
|
||||
|
||||
verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
|
||||
|
||||
|
@ -64,8 +64,9 @@ extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
|
||||
/* We need to use something for ENODATA. */
|
||||
#define ENODATA EIDRM
|
||||
|
||||
static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t *,
|
||||
int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *);
|
||||
static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
|
||||
recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
|
||||
uint64_t *);
|
||||
|
||||
static const zio_cksum_t zero_cksum = { 0 };
|
||||
|
||||
@ -2498,7 +2499,7 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
|
||||
* zfs_receive_one() will take care of it (ie,
|
||||
* recv_skip() and return 0).
|
||||
*/
|
||||
error = zfs_receive_impl(hdl, destname, flags, fd,
|
||||
error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
|
||||
sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
|
||||
action_handlep);
|
||||
if (error == ENODATA) {
|
||||
@ -2631,9 +2632,9 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
|
||||
*/
|
||||
static int
|
||||
zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
recvflags_t *flags, dmu_replay_record_t *drr,
|
||||
dmu_replay_record_t *drr_noswap, const char *sendfs,
|
||||
nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
|
||||
const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
|
||||
dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
|
||||
avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
|
||||
uint64_t *action_handlep)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
@ -2798,10 +2799,15 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
}
|
||||
if (flags->verbose)
|
||||
(void) printf("found clone origin %s\n", zc.zc_string);
|
||||
} else if (originsnap) {
|
||||
(void) strncpy(zc.zc_string, originsnap, ZFS_MAXNAMELEN);
|
||||
if (flags->verbose)
|
||||
(void) printf("using provided clone origin %s\n",
|
||||
zc.zc_string);
|
||||
}
|
||||
|
||||
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
|
||||
(drrb->drr_flags & DRR_FLAG_CLONE));
|
||||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap);
|
||||
|
||||
if (stream_wantsnewfs) {
|
||||
/*
|
||||
@ -3179,9 +3185,10 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
|
||||
int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl,
|
||||
char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
|
||||
zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
|
||||
const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
|
||||
nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
|
||||
uint64_t *action_handlep)
|
||||
{
|
||||
int err;
|
||||
dmu_replay_record_t drr, drr_noswap;
|
||||
@ -3200,6 +3207,12 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
|
||||
"(%s) does not exist"), tosnap);
|
||||
return (zfs_error(hdl, EZFS_NOENT, errbuf));
|
||||
}
|
||||
if (originsnap &&
|
||||
!zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified origin fs "
|
||||
"(%s) does not exist"), originsnap);
|
||||
return (zfs_error(hdl, EZFS_NOENT, errbuf));
|
||||
}
|
||||
|
||||
/* read in the BEGIN record */
|
||||
if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
|
||||
@ -3272,14 +3285,14 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
|
||||
*cp = '\0';
|
||||
sendfs = nonpackage_sendfs;
|
||||
}
|
||||
return (zfs_receive_one(hdl, infd, tosnap, flags,
|
||||
&drr, &drr_noswap, sendfs, stream_nv, stream_avl,
|
||||
top_zfs, cleanup_fd, action_handlep));
|
||||
return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
|
||||
&drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
|
||||
cleanup_fd, action_handlep));
|
||||
} else {
|
||||
assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
|
||||
DMU_COMPOUNDSTREAM);
|
||||
return (zfs_receive_package(hdl, infd, tosnap, flags,
|
||||
&drr, &zcksum, top_zfs, cleanup_fd, action_handlep));
|
||||
return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
|
||||
&zcksum, top_zfs, cleanup_fd, action_handlep));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3290,18 +3303,24 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
|
||||
* (-1 will override -2).
|
||||
*/
|
||||
int
|
||||
zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags,
|
||||
int infd, avl_tree_t *stream_avl)
|
||||
zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
|
||||
recvflags_t *flags, int infd, avl_tree_t *stream_avl)
|
||||
{
|
||||
char *top_zfs = NULL;
|
||||
int err;
|
||||
int cleanup_fd;
|
||||
uint64_t action_handle = 0;
|
||||
char *originsnap = NULL;
|
||||
if (props) {
|
||||
err = nvlist_lookup_string(props, "origin", &originsnap);
|
||||
if (err && err != ENOENT)
|
||||
return (err);
|
||||
}
|
||||
|
||||
cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
|
||||
VERIFY(cleanup_fd >= 0);
|
||||
|
||||
err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL,
|
||||
err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
|
||||
stream_avl, &top_zfs, cleanup_fd, &action_handle);
|
||||
|
||||
VERIFY(0 == close(cleanup_fd));
|
||||
|
@ -135,8 +135,18 @@ extern int aok;
|
||||
|
||||
/*
|
||||
* DTrace SDT probes have different signatures in userland than they do in
|
||||
* kernel. If they're being used in kernel code, re-define them out of
|
||||
* the kernel. If they're being used in kernel code, re-define them out of
|
||||
* existence for their counterparts in libzpool.
|
||||
*
|
||||
* Here's an example of how to use the set-error probes in userland:
|
||||
* zfs$target:::set-error /arg0 == EBUSY/ {stack();}
|
||||
*
|
||||
* Here's an example of how to use DTRACE_PROBE probes in userland:
|
||||
* If there is a probe declared as follows:
|
||||
* DTRACE_PROBE2(zfs__probe_name, uint64_t, blkid, dnode_t *, dn);
|
||||
* Then you can use it as follows:
|
||||
* zfs$target:::probe2 /copyinstr(arg0) == "zfs__probe_name"/
|
||||
* {printf("%u %p\n", arg1, arg2);}
|
||||
*/
|
||||
|
||||
#ifdef DTRACE_PROBE
|
||||
|
@ -34,7 +34,7 @@ COMPILER_RT_ABI fp_t __floatditf(di_int a) {
|
||||
}
|
||||
|
||||
// Exponent of (fp_t)a is the width of abs(a).
|
||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||
const int exponent = (aWidth - 1) - __builtin_clzll(a);
|
||||
rep_t result;
|
||||
|
||||
// Shift a into the significand field and clear the implicit bit. Extra
|
||||
|
@ -25,7 +25,7 @@ COMPILER_RT_ABI fp_t __floatunditf(du_int a) {
|
||||
if (a == 0) return fromRep(0);
|
||||
|
||||
// Exponent of (fp_t)a is the width of abs(a).
|
||||
const int exponent = (aWidth - 1) - __builtin_clz(a);
|
||||
const int exponent = (aWidth - 1) - __builtin_clzll(a);
|
||||
rep_t result;
|
||||
|
||||
// Shift a into the significand field and clear the implicit bit.
|
||||
|
@ -567,7 +567,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
|
||||
SSIZE_MAX to be much smaller than the actual range of the
|
||||
type. Use INTTYPE_MAXIMUM unconditionally to ensure this
|
||||
does not bite us. */
|
||||
if (file->st.st_size > INTTYPE_MAXIMUM (ssize_t))
|
||||
if (file->st.st_size > SSIZE_MAX)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, "%s is too large", file->path);
|
||||
return false;
|
||||
@ -581,7 +581,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
|
||||
file->path);
|
||||
return false;
|
||||
}
|
||||
else if (offset > INTTYPE_MAXIMUM (ssize_t) || (ssize_t)offset > size)
|
||||
else if (offset > SSIZE_MAX || (ssize_t)offset > size)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR, "current position of %s is too large",
|
||||
file->path);
|
||||
|
@ -538,7 +538,7 @@ Zone Africa/Tripoli 0:52:44 - LMT 1920
|
||||
|
||||
# From Alex Krivenyshev (2008-07-11):
|
||||
# Seems that English language article "The revival of daylight saving
|
||||
# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
|
||||
# time: Energy conservation?"- No. 16578 (07/11/2008) was originally
|
||||
# published on Monday, June 30, 2008...
|
||||
#
|
||||
# I guess that article in French "Le gouvernement avance l'introduction
|
||||
@ -670,7 +670,7 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
|
||||
# Here is a link to official document from Royaume du Maroc Premier Ministre,
|
||||
# Ministère de la Modernisation des Secteurs Publics
|
||||
#
|
||||
# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
|
||||
# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 June 1967)
|
||||
# concerning the amendment of the legal time, the Ministry of Modernization of
|
||||
# Public Sectors announced that the official time in the Kingdom will be
|
||||
# advanced 60 minutes from Sunday 31 May 2009 at midnight.
|
||||
|
@ -6,7 +6,7 @@
|
||||
# tz@iana.org for general use in the future). For more, please see
|
||||
# the file CONTRIBUTING in the tz distribution.
|
||||
|
||||
# From Paul Eggert (2014-10-31):
|
||||
# From Paul Eggert (2015-08-08):
|
||||
#
|
||||
# Unless otherwise specified, the source for data through 1990 is:
|
||||
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
|
||||
@ -43,7 +43,7 @@
|
||||
# 2:00 EET EEST Eastern European Time
|
||||
# 2:00 IST IDT Israel
|
||||
# 3:00 AST ADT Arabia*
|
||||
# 3:30 IRST IRDT Iran
|
||||
# 3:30 IRST IRDT Iran*
|
||||
# 4:00 GST Gulf*
|
||||
# 5:30 IST India
|
||||
# 7:00 ICT Indochina, most times and locations*
|
||||
@ -52,10 +52,11 @@
|
||||
# 8:00 CST China
|
||||
# 8:00 IDT Indochina, 1943-45, 1947-55, 1960-75 (some locations)*
|
||||
# 8:00 JWST Western Standard Time (Japan, 1896/1937)*
|
||||
# 8:30 KST KDT Korea when at +0830*
|
||||
# 9:00 JCST Central Standard Time (Japan, 1896/1937)
|
||||
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
|
||||
# 9:00 JST JDT Japan
|
||||
# 9:00 KST KDT Korea
|
||||
# 9:00 KST KDT Korea when at +09
|
||||
# 9:30 ACST Australian Central Standard Time
|
||||
#
|
||||
# See the 'europe' file for Russia and Turkey in Asia.
|
||||
@ -1027,7 +1028,7 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
|
||||
#
|
||||
# From Roozbeh Pournader (2007-11-05):
|
||||
# This is quoted from Official Gazette of the Islamic Republic of
|
||||
# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
|
||||
# Iran, Volume 63, No. 18242, dated Tuesday 1386/6/24
|
||||
# [2007-10-16]. I am doing the best translation I can:...
|
||||
# The official time of the country will be moved forward for one hour
|
||||
# on the 24 hours of the first day of the month of Farvardin and will
|
||||
@ -1557,7 +1558,7 @@ Zone Asia/Amman 2:23:44 - LMT 1931
|
||||
# - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
|
||||
# - Oral switched from +5:00 to +4:00 in spring 1989.
|
||||
|
||||
# From Kazakhstan Embassy's News Bulletin #11
|
||||
# From Kazakhstan Embassy's News Bulletin No. 11
|
||||
# <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
|
||||
# The Government of Kazakhstan passed a resolution March 15 abolishing
|
||||
# daylight saving time citing lack of economic benefits and health
|
||||
@ -1711,6 +1712,17 @@ Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
|
||||
#
|
||||
# For Pyongyang we have no information; guess no changes since World War II.
|
||||
|
||||
# From Steffen Thorsen (2015-08-07):
|
||||
# According to many news sources, North Korea is going to change to
|
||||
# the 8:30 time zone on August 15, one example:
|
||||
# http://www.bbc.com/news/world-asia-33815049
|
||||
#
|
||||
# From Paul Eggert (2015-08-07):
|
||||
# No transition time is specified; assume 00:00.
|
||||
# There is no common English-language abbreviation for this time zone.
|
||||
# Use %z rather than invent one. We can't assume %z works everywhere yet,
|
||||
# so for now substitute its output manually.
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
|
||||
8:30 - KST 1912 Jan 1
|
||||
@ -1723,7 +1735,8 @@ Zone Asia/Pyongyang 8:23:00 - LMT 1908 Apr 1
|
||||
8:30 - KST 1912 Jan 1
|
||||
9:00 - JCST 1937 Oct 1
|
||||
9:00 - JST 1945 Aug 24
|
||||
9:00 - KST
|
||||
9:00 - KST 2015 Aug 15
|
||||
8:30 - KST
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
@ -193,11 +193,14 @@
|
||||
# republished in Finest Hour (Spring 2002) 1(114):26
|
||||
# http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
|
||||
|
||||
# From Paul Eggert (1996-09-03):
|
||||
# From Paul Eggert (2015-08-08):
|
||||
# The OED Supplement says that the English originally said "Daylight Saving"
|
||||
# when they were debating the adoption of DST in 1908; but by 1916 this
|
||||
# term appears only in quotes taken from DST's opponents, whereas the
|
||||
# proponents (who eventually won the argument) are quoted as using "Summer".
|
||||
# The term "Summer Time" was introduced by Herbert Samuel, Home Secretary; see:
|
||||
# Viscount Samuel. Leisure in a Democracy. Cambridge University Press
|
||||
# ISBN 978-1-107-49471-8 (1949, reissued 2015), p 8.
|
||||
|
||||
# From Arthur David Olson (1989-01-19):
|
||||
# A source at the British Information Office in New York avers that it's
|
||||
@ -343,7 +346,7 @@
|
||||
|
||||
# From an anonymous contributor (1996-06-02):
|
||||
# The law governing time in Ireland is under Statutory Instrument SI 395/94,
|
||||
# which gives force to European Union 7th Council Directive # 94/21/EC.
|
||||
# which gives force to European Union 7th Council Directive No. 94/21/EC.
|
||||
# Under this directive, the Minister for Justice in Ireland makes appropriate
|
||||
# regulations. I spoke this morning with the Secretary of the Department of
|
||||
# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
|
||||
@ -592,11 +595,11 @@ Rule Russia 1921 only - Feb 14 23:00 1:00 MSD
|
||||
Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer
|
||||
Rule Russia 1921 only - Sep 1 0:00 1:00 MSD
|
||||
Rule Russia 1921 only - Oct 1 0:00 0 -
|
||||
# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
|
||||
# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
|
||||
Rule Russia 1981 1984 - Apr 1 0:00 1:00 S
|
||||
Rule Russia 1981 1983 - Oct 1 0:00 0 -
|
||||
# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
|
||||
# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
|
||||
# Act No. 967 of the Council of Ministers of the USSR (1984-09-13), repeated in
|
||||
# Act No. 227 of the Council of Ministers of the USSR (1989-03-14):
|
||||
Rule Russia 1984 1991 - Sep lastSun 2:00s 0 -
|
||||
Rule Russia 1985 1991 - Mar lastSun 2:00s 1:00 S
|
||||
#
|
||||
@ -828,7 +831,7 @@ Zone Europe/Brussels 0:17:30 - LMT 1880
|
||||
# Bulgaria
|
||||
#
|
||||
# From Plamen Simenov via Steffen Thorsen (1999-09-09):
|
||||
# A document of Government of Bulgaria (No.94/1997) says:
|
||||
# A document of Government of Bulgaria (No. 94/1997) says:
|
||||
# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
|
||||
# EETDST -> EET is in 04:00 Local time in last Sunday of October
|
||||
#
|
||||
@ -845,7 +848,7 @@ Zone Europe/Sofia 1:33:16 - LMT 1880
|
||||
1:00 C-Eur CE%sT 1945
|
||||
1:00 - CET 1945 Apr 2 3:00
|
||||
2:00 - EET 1979 Mar 31 23:00
|
||||
2:00 Bulg EE%sT 1982 Sep 26 2:00
|
||||
2:00 Bulg EE%sT 1982 Sep 26 3:00
|
||||
2:00 C-Eur EE%sT 1991
|
||||
2:00 E-Eur EE%sT 1997
|
||||
2:00 EU EE%sT
|
||||
@ -1062,8 +1065,8 @@ Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik air base
|
||||
# after that.
|
||||
|
||||
# From Mart Oruaas (2000-01-29):
|
||||
# Regulation no. 301 (1999-10-12) obsoletes previous regulation
|
||||
# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
|
||||
# Regulation No. 301 (1999-10-12) obsoletes previous regulation
|
||||
# No. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
|
||||
# the year round. The regulation is effective 1999-11-01.
|
||||
|
||||
# From Toomas Soome (2002-02-21):
|
||||
@ -1084,7 +1087,7 @@ Zone Europe/Tallinn 1:39:00 - LMT 1880
|
||||
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
|
||||
2:00 1:00 EEST 1989 Sep 24 2:00s
|
||||
2:00 C-Eur EE%sT 1998 Sep 22
|
||||
2:00 EU EE%sT 1999 Nov 1
|
||||
2:00 EU EE%sT 1999 Oct 31 4:00
|
||||
2:00 - EET 2002 Feb 21
|
||||
2:00 EU EE%sT
|
||||
|
||||
@ -1527,21 +1530,21 @@ Link Europe/Rome Europe/San_Marino
|
||||
# correct data in juridical acts and I found some juridical documents about
|
||||
# changes in the counting of time in Latvia from 1981....
|
||||
#
|
||||
# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
|
||||
# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
|
||||
# Act No. 35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
|
||||
# according to the Act No. 925 of the Council of Ministers of USSR of 1980-10-24
|
||||
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
|
||||
# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
|
||||
# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
|
||||
#
|
||||
# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
|
||||
# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
|
||||
# Act No. 592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
|
||||
# according to the Act No. 967 of the Council of Ministers of USSR of 1984-09-13
|
||||
# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
|
||||
# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
|
||||
# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
|
||||
# September at 03:00 (GMT 23:00 on the previous day).
|
||||
#
|
||||
# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
|
||||
# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
|
||||
# Act No. 81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
|
||||
# according to the Act No. 227 of the Council of Ministers of USSR of 1989-03-14
|
||||
# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
|
||||
# Estonian SSR and Kaliningrad region of Russian Federation all year round the
|
||||
# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
|
||||
@ -1558,7 +1561,7 @@ Link Europe/Rome Europe/San_Marino
|
||||
# From Andrei Ivanov (2000-03-06):
|
||||
# This year Latvia will not switch to Daylight Savings Time (as specified in
|
||||
# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
|
||||
# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
|
||||
# 29-Feb-2000 (No. 79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
|
||||
# in Latvian for subscribers only).
|
||||
|
||||
# From RFE/RL Newsline
|
||||
@ -1763,6 +1766,18 @@ Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
|
||||
# News from Moldova (in russian):
|
||||
# http://ru.publika.md/link_317061.html
|
||||
|
||||
# From Roman Tudos (2015-07-02):
|
||||
# http://lex.justice.md/index.php?action=view&view=doc&lang=1&id=355077
|
||||
# From Paul Eggert (2015-07-01):
|
||||
# The abovementioned official link to IGO1445-868/2014 states that
|
||||
# 2014-10-26's fallback transition occurred at 03:00 local time. Also,
|
||||
# http://www.trm.md/en/social/la-30-martie-vom-trece-la-ora-de-vara
|
||||
# says the 2014-03-30 spring-forward transition was at 02:00 local time.
|
||||
# Guess that since 1997 Moldova has switched one hour before the EU.
|
||||
|
||||
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
|
||||
Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S
|
||||
Rule Moldova 1997 max - Oct lastSun 3:00 0 -
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Europe/Chisinau 1:55:20 - LMT 1880
|
||||
@ -1777,7 +1792,7 @@ Zone Europe/Chisinau 1:55:20 - LMT 1880
|
||||
2:00 Russia EE%sT 1992
|
||||
2:00 E-Eur EE%sT 1997
|
||||
# See Romania commentary for the guessed 1997 transition to EU rules.
|
||||
2:00 EU EE%sT
|
||||
2:00 Moldova EE%sT
|
||||
|
||||
# Monaco
|
||||
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
|
||||
@ -2123,7 +2138,7 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
|
||||
# Russia
|
||||
|
||||
# From Alexander Krivenyshev (2011-09-15):
|
||||
# Based on last Russian Government Decree # 725 on August 31, 2011
|
||||
# Based on last Russian Government Decree No. 725 on August 31, 2011
|
||||
# (Government document
|
||||
# http://www.government.ru/gov/results/16355/print/
|
||||
# in Russian)
|
||||
@ -2133,7 +2148,7 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
|
||||
# http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
|
||||
|
||||
# From Sanjeev Gupta (2011-09-27):
|
||||
# Scans of [Decree #23 of January 8, 1992] are available at:
|
||||
# Scans of [Decree No. 23 of January 8, 1992] are available at:
|
||||
# http://government.consultant.ru/page.aspx?1223966
|
||||
# They are in Cyrillic letters (presumably Russian).
|
||||
|
||||
@ -2144,19 +2159,19 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
|
||||
# One source is
|
||||
# http://government.ru/gov/results/16355/
|
||||
# which, according to translate.google.com, begins "Decree of August 31,
|
||||
# 2011 No 725" and contains no other dates or "effective date" information.
|
||||
# 2011 No. 725" and contains no other dates or "effective date" information.
|
||||
#
|
||||
# Another source is
|
||||
# http://www.rg.ru/2011/09/06/chas-zona-dok.html
|
||||
# which, according to translate.google.com, begins "Resolution of the
|
||||
# Government of the Russian Federation on August 31, 2011 N 725" and also
|
||||
# contains "Date first official publication: September 6, 2011 Posted on:
|
||||
# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
|
||||
# in the 'RG' - Federal Issue No. 5573 September 6, 2011" but which
|
||||
# does not contain any "effective date" information.
|
||||
#
|
||||
# Another source is
|
||||
# http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
|
||||
# which, in note 8, contains "Resolution #725 of August 31, 2011...
|
||||
# which, in note 8, contains "Resolution No. 725 of August 31, 2011...
|
||||
# Effective as of after 7 days following the day of the official publication"
|
||||
# but which does not contain any reference to September 6, 2011.
|
||||
#
|
||||
@ -2364,7 +2379,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880
|
||||
# changed in May.
|
||||
2:00 E-Eur EE%sT 1994 May
|
||||
# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
|
||||
3:00 E-Eur MSK/MSD 1996 Mar 31 3:00s
|
||||
3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s
|
||||
3:00 1:00 MSD 1996 Oct 27 3:00s
|
||||
# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
|
||||
# Assume it happened in March by not changing the clocks.
|
||||
@ -2499,7 +2514,7 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
|
||||
# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
|
||||
# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
|
||||
#
|
||||
# This is according to Government of Russia decree # 740, on September
|
||||
# This is according to Government of Russia decree No. 740, on September
|
||||
# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
|
||||
# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
|
||||
#
|
||||
@ -2922,7 +2937,7 @@ Zone Africa/Ceuta -0:21:16 - LMT 1901
|
||||
Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
|
||||
-1:00 - CANT 1946 Sep 30 1:00 # Canaries T
|
||||
0:00 - WET 1980 Apr 6 0:00s
|
||||
0:00 1:00 WEST 1980 Sep 28 0:00s
|
||||
0:00 1:00 WEST 1980 Sep 28 1:00u
|
||||
0:00 EU WE%sT
|
||||
# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
|
||||
# Ignore this for now, as the Canaries are part of the EU.
|
||||
@ -3212,7 +3227,7 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
|
||||
# From Igor Karpov, who works for the Ukrainian Ministry of Justice,
|
||||
# via Garrett Wollman (2003-01-27):
|
||||
# BTW, I've found the official document on this matter. It's government
|
||||
# regulations number 509, May 13, 1996. In my poor translation it says:
|
||||
# regulations No. 509, May 13, 1996. In my poor translation it says:
|
||||
# "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
|
||||
# of March at 3am the time is changing to 4am and each last Sunday of
|
||||
# October the time at 4am is changing to 3am"
|
||||
@ -3221,7 +3236,7 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
|
||||
# On September 20, 2011 the deputies of the Verkhovna Rada agreed to
|
||||
# abolish the transfer clock to winter time.
|
||||
#
|
||||
# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
|
||||
# Bill No. 8330 of MP from the Party of Regions Oleg Nadoshi got
|
||||
# approval from 266 deputies.
|
||||
#
|
||||
# Ukraine abolishes transfer back to the winter time (in Russian)
|
||||
|
@ -199,10 +199,10 @@
|
||||
# current -- the update time stamp, the data and the name of the file
|
||||
# will not change.
|
||||
#
|
||||
# Updated through IERS Bulletin C49
|
||||
# File expires on: 28 December 2015
|
||||
# Updated through IERS Bulletin C50
|
||||
# File expires on: 28 June 2016
|
||||
#
|
||||
#@ 3660249600
|
||||
#@ 3676060800
|
||||
#
|
||||
2272060800 10 # 1 Jan 1972
|
||||
2287785600 11 # 1 Jul 1972
|
||||
@ -246,4 +246,4 @@
|
||||
# the hash line is also ignored in the
|
||||
# computation.
|
||||
#
|
||||
#h 45e70fa7 a9df2033 f4a49ab0 ec648273 7b6c22c
|
||||
#h 3d037453 3acade76 570bd8f8 be2b8bc9 55ec6fe8
|
||||
|
@ -1235,10 +1235,19 @@ Zone America/Goose_Bay -4:01:40 - LMT 1884 # Happy Valley-Goose Bay
|
||||
|
||||
# west Labrador, Nova Scotia, Prince Edward I
|
||||
|
||||
# From Paul Eggert (2006-03-22):
|
||||
# From Brian Inglis (2015-07-20):
|
||||
# From the historical weather station records available at:
|
||||
# https://weatherspark.com/history/28351/1971/Sydney-Nova-Scotia-Canada
|
||||
# Sydney shares the same time history as Glace Bay, so was
|
||||
# likely to be the same across the island....
|
||||
# Sydney, as the capital and most populous location, or Cape Breton, would
|
||||
# have been better names for the zone had we known this in 1996.
|
||||
|
||||
# From Paul Eggert (2015-07-20):
|
||||
# Shanks & Pottenger write that since 1970 most of this region has been like
|
||||
# Halifax. Many locales did not observe peacetime DST until 1972;
|
||||
# Glace Bay, NS is the largest that we know of.
|
||||
# the Cape Breton area, represented by Glace Bay, is the largest we know of
|
||||
# (Glace Bay was perhaps not the best name choice but no point changing now).
|
||||
# Shanks & Pottenger also write that Liverpool, NS was the only town
|
||||
# in Canada to observe DST in 1971 but not 1970; for now we'll assume
|
||||
# this is a typo.
|
||||
@ -1796,13 +1805,13 @@ Zone America/Edmonton -7:33:52 - LMT 1906 Sep
|
||||
# Exact date in October unknown; Sunday October 1 is a reasonable guess.
|
||||
# 3. June 1918: switch to Pacific Daylight Time (GMT-7)
|
||||
# Exact date in June unknown; Sunday June 2 is a reasonable guess.
|
||||
# note#1:
|
||||
# note 1:
|
||||
# On Oct 27/1918 when daylight saving ended in the rest of Canada,
|
||||
# Creston did not change its clocks.
|
||||
# note#2:
|
||||
# note 2:
|
||||
# During WWII when the Federal Government legislated a mandatory clock change,
|
||||
# Creston did not oblige.
|
||||
# note#3:
|
||||
# note 3:
|
||||
# There is no guarantee that Creston will remain on Mountain Standard Time
|
||||
# (UTC-7) forever.
|
||||
# The subject was debated at least once this year by the town Council.
|
||||
|
@ -131,7 +131,7 @@ Rule Arg 2000 only - Mar 3 0:00 0 -
|
||||
# Timezone Law (which never was effectively applied) will (would?) be
|
||||
# in effect.... The article is at
|
||||
# http://ar.clarin.com/diario/2001-06-06/e-01701.htm
|
||||
# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
|
||||
# ... The Law itself is "Ley No. 25155", sanctioned on 1999-08-25, enacted
|
||||
# 1999-09-17, and published 1999-09-21. The official publication is at:
|
||||
# http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
|
||||
# Regretfully, you have to subscribe (and pay) for the on-line version....
|
||||
@ -175,15 +175,11 @@ Rule Arg 2000 only - Mar 3 0:00 0 -
|
||||
# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
|
||||
# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
|
||||
|
||||
# From Rodrigo Severo (2008-10-06):
|
||||
# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
|
||||
# ...
|
||||
# ------- Comment #1 from [jmdocile] 2008-10-06 16:28 0000 -------
|
||||
# Hi, there is a problem with timezone-data-2008e and maybe with
|
||||
# timezone-data-2008f
|
||||
# Argentinian law [Number] 25.155 is no longer valid.
|
||||
# From Juan Manuel Docile in https://bugs.gentoo.org/240339 (2008-10-07)
|
||||
# via Rodrigo Severo:
|
||||
# Argentinian law No. 25.155 is no longer valid.
|
||||
# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
|
||||
# The new one is law [Number] 26.350
|
||||
# The new one is law No. 26.350
|
||||
# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
|
||||
# So there is no summer time in Argentina for now.
|
||||
|
||||
@ -771,7 +767,7 @@ Zone America/La_Paz -4:32:36 - LMT 1890
|
||||
# [ and in a second message (same day): ]
|
||||
# I found the decree.
|
||||
#
|
||||
# DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
|
||||
# DECRETO No. 7.584, DE 13 DE OUTUBRO DE 2011
|
||||
# Link :
|
||||
# http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
|
||||
|
||||
@ -1125,7 +1121,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
|
||||
# Conflicts between [1] and [2] were resolved as follows:
|
||||
#
|
||||
# - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites
|
||||
# Boletín Nº 1, Aviso Nº 1 (1910). Go with [2].
|
||||
# Boletín No. 1, Aviso No. 1 (1910). Go with [2].
|
||||
#
|
||||
# - [1] says SMT was -4:42:45, [2] says Chile's official time from
|
||||
# 1916 to 1919 was -4:42:46.3, the meridian of Chile's National
|
||||
@ -1133,7 +1129,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
|
||||
# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46.
|
||||
#
|
||||
# - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites
|
||||
# Boletín Nº 22, Aviso Nº 129/1918 (1918-08-23). Go with [2].
|
||||
# Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2].
|
||||
#
|
||||
# - [1] does not give times for transitions; assume they occur
|
||||
# at midnight mainland time, the current common practice. However,
|
||||
@ -1533,7 +1529,7 @@ Rule Para 1997 only - Feb lastSun 0:00 0 -
|
||||
# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
|
||||
Rule Para 1998 2001 - Mar Sun>=1 0:00 0 -
|
||||
# From Rives McDow (2002-02-28):
|
||||
# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
|
||||
# A decree was issued in Paraguay (No. 16350) on 2002-02-26 that changed the
|
||||
# dst method to be from the first Sunday in September to the first Sunday in
|
||||
# April.
|
||||
Rule Para 2002 2004 - Apr Sun>=1 0:00 0 -
|
||||
@ -1713,8 +1709,19 @@ Rule Uruguay 2005 only - Oct 9 2:00 1:00 S
|
||||
Rule Uruguay 2006 only - Mar 12 2:00 0 -
|
||||
# From Jesper Nørgaard Welen (2006-09-06):
|
||||
# http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
|
||||
Rule Uruguay 2006 max - Oct Sun>=1 2:00 1:00 S
|
||||
Rule Uruguay 2007 max - Mar Sun>=8 2:00 0 -
|
||||
#
|
||||
# From Steffen Thorsen (2015-06-30):
|
||||
# ... it looks like they will not be using DST the coming summer:
|
||||
# http://www.elobservador.com.uy/gobierno-resolvio-que-no-habra-cambio-horario-verano-n656787
|
||||
# http://www.republica.com.uy/este-ano-no-se-modificara-el-huso-horario-en-uruguay/523760/
|
||||
# From Paul Eggert (2015-06-30):
|
||||
# Apparently restaurateurs complained that DST caused people to go to the beach
|
||||
# instead of out to dinner.
|
||||
# From Pablo Camargo (2015-07-13):
|
||||
# http://archivo.presidencia.gub.uy/sci/decretos/2015/06/cons_min_201.pdf
|
||||
# [dated 2015-06-29; repeals Decree 311/006 dated 2006-09-04]
|
||||
Rule Uruguay 2006 2014 - Oct Sun>=1 2:00 1:00 S
|
||||
Rule Uruguay 2007 2015 - Mar Sun>=8 2:00 0 -
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
|
||||
-3:44:44 - MMT 1920 May 1 # Montevideo MT
|
||||
@ -1723,6 +1730,10 @@ Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
|
||||
|
||||
# Venezuela
|
||||
#
|
||||
# From Paul Eggert (2015-07-28):
|
||||
# For the 1965 transition see Gaceta Oficial No. 27.619 (1964-12-15), p 205.533
|
||||
# http://www.pgr.gob.ve/dmdocuments/1964/27619.pdf
|
||||
#
|
||||
# From John Stainforth (2007-11-28):
|
||||
# ... the change for Venezuela originally expected for 2007-12-31 has
|
||||
# been brought forward to 2007-12-09. The official announcement was
|
||||
@ -1734,6 +1745,6 @@ Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone America/Caracas -4:27:44 - LMT 1890
|
||||
-4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time?
|
||||
-4:30 - VET 1965 # Venezuela Time
|
||||
-4:30 - VET 1965 Jan 1 0:00 # Venezuela T.
|
||||
-4:00 - VET 2007 Dec 9 3:00
|
||||
-4:30 - VET
|
||||
|
@ -106,8 +106,8 @@ BW -2439+02555 Africa/Gaborone
|
||||
BY +5354+02734 Europe/Minsk
|
||||
BZ +1730-08812 America/Belize
|
||||
CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador
|
||||
CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI
|
||||
CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
|
||||
CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (peninsula), PEI
|
||||
CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia (Cape Breton)
|
||||
CA +4606-06447 America/Moncton Atlantic Time - New Brunswick
|
||||
CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations
|
||||
CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore
|
||||
|
@ -104,8 +104,8 @@ BT +2728+08939 Asia/Thimphu
|
||||
BY +5354+02734 Europe/Minsk
|
||||
BZ +1730-08812 America/Belize
|
||||
CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador
|
||||
CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI
|
||||
CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
|
||||
CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (peninsula), PEI
|
||||
CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia (Cape Breton)
|
||||
CA +4606-06447 America/Moncton Atlantic Time - New Brunswick
|
||||
CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations
|
||||
CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore
|
||||
|
@ -12,7 +12,7 @@ SUBDIR= doc\
|
||||
${_objcopy} \
|
||||
objdump \
|
||||
|
||||
.if ${MK_ELFTOOLCHAIN_TOOLS} == "no" || ${MK_ELFCOPY_AS_OBJCOPY} == "no"
|
||||
.if ${MK_ELFCOPY_AS_OBJCOPY} == "no"
|
||||
_objcopy= objcopy
|
||||
.endif
|
||||
|
||||
|
@ -182,7 +182,7 @@ _clang= clang
|
||||
_cuse= libcuse
|
||||
.endif
|
||||
|
||||
.if ${MK_ELFTOOLCHAIN_TOOLS} != "no"
|
||||
.if ${MK_TOOLCHAIN} != "no"
|
||||
_libelftc= libelftc
|
||||
.endif
|
||||
|
||||
|
@ -95,6 +95,7 @@ NOASM=
|
||||
.include "${LIBC_SRCTOP}/stdtime/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/string/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/sys/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/secure/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/rpc/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/uuid/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/xdr/Makefile.inc"
|
||||
|
@ -138,8 +138,7 @@ we_askshell(const char *words, wordexp_t *we, int flags)
|
||||
}
|
||||
else if (pid == 0) {
|
||||
/*
|
||||
* We are the child; just get /bin/sh to run the wordexp
|
||||
* builtin on `words'.
|
||||
* We are the child; make /bin/sh expand `words'.
|
||||
*/
|
||||
(void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
|
||||
if ((pdes[1] != STDOUT_FILENO ?
|
||||
@ -147,7 +146,9 @@ we_askshell(const char *words, wordexp_t *we, int flags)
|
||||
_fcntl(pdes[1], F_SETFD, 0)) < 0)
|
||||
_exit(1);
|
||||
execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u",
|
||||
"-c", "IFS=$1;eval \"$2\";eval \"wordexp $3\"", "",
|
||||
"-c", "IFS=$1;eval \"$2\";eval \"set -- $3\";IFS=;a=\"$*\";"
|
||||
"printf '%08x' \"$#\" \"${#a}\";printf '%s\\0' \"$@\"",
|
||||
"",
|
||||
ifs != NULL ? ifs : " \t\n",
|
||||
flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", words,
|
||||
(char *)NULL);
|
||||
|
12
lib/libc/secure/Makefile.inc
Normal file
12
lib/libc/secure/Makefile.inc
Normal file
@ -0,0 +1,12 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# libc sources related to security
|
||||
|
||||
.PATH: ${LIBC_SRCTOP}/secure
|
||||
|
||||
# Sources common to both syscall interfaces:
|
||||
SRCS+= \
|
||||
stack_protector.c \
|
||||
stack_protector_compat.c
|
||||
|
||||
SYM_MAPS+= ${LIBC_SRCTOP}/secure/Symbol.map
|
9
lib/libc/secure/Symbol.map
Normal file
9
lib/libc/secure/Symbol.map
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
FBSD_1.0 {
|
||||
__chk_fail;
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
};
|
@ -31,7 +31,7 @@
|
||||
.\" @(#)bcopy.3 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 11, 2015
|
||||
.Dd August 14, 2015
|
||||
.Dt BCOPY 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -57,20 +57,6 @@ The two strings may overlap.
|
||||
If
|
||||
.Fa len
|
||||
is zero, no bytes are copied.
|
||||
.Pp
|
||||
This function is deprecated (marked as LEGACY in
|
||||
POSIX.1-2001): use
|
||||
.Xr memcpy 3
|
||||
or
|
||||
.Xr memmove 3
|
||||
in new programs.
|
||||
Note that the first two arguments are
|
||||
interchanged for
|
||||
.Xr memcpy 3
|
||||
and
|
||||
.Xr memmove 3 .
|
||||
POSIX.1-2008 removes the specification of
|
||||
.Fn bcopy .
|
||||
.Sh SEE ALSO
|
||||
.Xr memccpy 3 ,
|
||||
.Xr memcpy 3 ,
|
||||
@ -89,3 +75,25 @@ before it was moved to
|
||||
for
|
||||
.St -p1003.1-2001
|
||||
compliance.
|
||||
.Pp
|
||||
The
|
||||
.St -p1003.1-2008
|
||||
removes the specification of
|
||||
.Fn bcopy
|
||||
and it is marked as LEGACY in
|
||||
.St -p1003.1-2004 .
|
||||
New programs should use
|
||||
.Xr memmove 3 .
|
||||
If the input and output buffer do not overlap, then
|
||||
.Xr memcpy 3
|
||||
is more efficient.
|
||||
Note that
|
||||
.Fn bcopy
|
||||
takes
|
||||
.Ar src
|
||||
and
|
||||
.Ar dst
|
||||
in the opposite order from
|
||||
.Fn memmove
|
||||
and
|
||||
.Fn memcpy .
|
||||
|
@ -21,8 +21,6 @@ PSEUDO+= _clock_gettime.o _gettimeofday.o
|
||||
|
||||
# Sources common to both syscall interfaces:
|
||||
SRCS+= \
|
||||
stack_protector.c \
|
||||
stack_protector_compat.c \
|
||||
__error.c \
|
||||
interposing_table.c
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* It'd be nice to have this automatically generated, but we don't
|
||||
* know to what version they will eventually belong, so for now
|
||||
* It'd be nice to automatically generate the syscall symbols, but we
|
||||
* don't know to what version they will eventually belong to, so for now
|
||||
* it has to be manual.
|
||||
*/
|
||||
FBSD_1.0 {
|
||||
@ -56,7 +56,6 @@ FBSD_1.0 {
|
||||
bind;
|
||||
chdir;
|
||||
chflags;
|
||||
__chk_fail;
|
||||
chmod;
|
||||
chown;
|
||||
chroot;
|
||||
@ -281,8 +280,6 @@ FBSD_1.0 {
|
||||
sigwaitinfo;
|
||||
socket;
|
||||
socketpair;
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
stat;
|
||||
statfs;
|
||||
swapoff;
|
||||
|
@ -286,7 +286,7 @@ EndElement(void *userData, const char *name)
|
||||
"element", name);
|
||||
return;
|
||||
}
|
||||
gc->lg_val = p ? p : strdup("1");
|
||||
gc->lg_val = p;
|
||||
LIST_INSERT_HEAD(c, gc, lg_config);
|
||||
return;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ TESTSDIR= ${TESTSBASE}/lib/libnv
|
||||
|
||||
ATF_TESTS_CXX= \
|
||||
dnv_tests \
|
||||
nv_array_tests \
|
||||
nv_tests \
|
||||
|
||||
TAP_TESTS_C+= nvlist_add_test
|
||||
|
1191
lib/libnv/tests/nv_array_tests.cc
Normal file
1191
lib/libnv/tests/nv_array_tests.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -70,8 +70,6 @@ CFLAGS+= -DUSB_GLOBAL_INCLUDE_FILE=\"${LIBUSB_GLOBAL_INCLUDE_FILE}\"
|
||||
CFLAGS+= -I ../../sys
|
||||
.endif
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
# LibUSB v1.0
|
||||
MLINKS += libusb.3 libusb_init.3
|
||||
MLINKS += libusb.3 libusb_exit.3
|
||||
@ -259,3 +257,5 @@ MLINKS += libusb20.3 libusb20_me_decode.3
|
||||
MLINKS += libusb20.3 libusb20_desc_foreach.3
|
||||
MLINKS += libusb20.3 libusb20_strerror.3
|
||||
MLINKS += libusb20.3 libusb20_error_name.3
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 15, 2015
|
||||
.Dd Aug 12, 2015
|
||||
.Dt IFCONFIG 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -2396,6 +2396,10 @@ Disable local hash computation for RSS hash on the interface.
|
||||
Set a shift parameter for RSS local hash computation.
|
||||
Hash is calculated by using flowid bits in a packet header mbuf
|
||||
which are shifted by the number of this parameter.
|
||||
.It Cm lacp_fast_timeout
|
||||
Enable lacp fast-timeout on the interface.
|
||||
.It Cm -lacp_fast_timeout
|
||||
Disable lacp fast-timeout on the interface.
|
||||
.El
|
||||
.Pp
|
||||
The following parameters are specific to IP tunnel interfaces,
|
||||
|
@ -115,6 +115,8 @@ setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
|
||||
case -LAGG_OPT_LACP_TXTEST:
|
||||
case LAGG_OPT_LACP_RXTEST:
|
||||
case -LAGG_OPT_LACP_RXTEST:
|
||||
case LAGG_OPT_LACP_TIMEOUT:
|
||||
case -LAGG_OPT_LACP_TIMEOUT:
|
||||
break;
|
||||
default:
|
||||
err(1, "Invalid lagg option");
|
||||
@ -293,6 +295,8 @@ static struct cmd lagg_cmds[] = {
|
||||
DEF_CMD("-lacp_txtest", -LAGG_OPT_LACP_TXTEST, setlaggsetopt),
|
||||
DEF_CMD("lacp_rxtest", LAGG_OPT_LACP_RXTEST, setlaggsetopt),
|
||||
DEF_CMD("-lacp_rxtest", -LAGG_OPT_LACP_RXTEST, setlaggsetopt),
|
||||
DEF_CMD("lacp_fast_timeout", LAGG_OPT_LACP_TIMEOUT, setlaggsetopt),
|
||||
DEF_CMD("-lacp_fast_timeout", -LAGG_OPT_LACP_TIMEOUT, setlaggsetopt),
|
||||
DEF_CMD_ARG("flowid_shift", setlaggflowidshift),
|
||||
};
|
||||
static struct afswtch af_lagg = {
|
||||
|
@ -2869,14 +2869,14 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen, struct tidx *tstate)
|
||||
case '/':
|
||||
masklen = atoi(p);
|
||||
if (masklen == 0)
|
||||
d[1] = htonl(0); /* mask */
|
||||
d[1] = htonl(0U); /* mask */
|
||||
else if (masklen > 32)
|
||||
errx(EX_DATAERR, "bad width ``%s''", p);
|
||||
else
|
||||
d[1] = htonl(~0 << (32 - masklen));
|
||||
d[1] = htonl(~0U << (32 - masklen));
|
||||
break;
|
||||
case '{': /* no mask, assume /24 and put back the '{' */
|
||||
d[1] = htonl(~0 << (32 - 24));
|
||||
d[1] = htonl(~0U << (32 - 24));
|
||||
*(--p) = md;
|
||||
break;
|
||||
|
||||
@ -2885,7 +2885,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen, struct tidx *tstate)
|
||||
/* FALLTHROUGH */
|
||||
case 0: /* initialization value */
|
||||
default:
|
||||
d[1] = htonl(~0); /* force /32 */
|
||||
d[1] = htonl(~0U); /* force /32 */
|
||||
break;
|
||||
}
|
||||
d[0] &= d[1]; /* mask base address with mask */
|
||||
|
@ -3,8 +3,7 @@
|
||||
PROG= ping6
|
||||
MAN= ping6.8
|
||||
|
||||
CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \
|
||||
-DHAVE_ARC4RANDOM
|
||||
CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS
|
||||
WARNS?= 3
|
||||
|
||||
BINOWN= root
|
||||
|
@ -288,9 +288,6 @@ main(int argc, char *argv[])
|
||||
{
|
||||
struct timeval last, intvl;
|
||||
struct sockaddr_in6 from, *sin6;
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
struct timeval seed;
|
||||
#endif
|
||||
struct addrinfo hints, *res;
|
||||
struct sigaction si_sa;
|
||||
int cc, i;
|
||||
@ -751,17 +748,7 @@ main(int argc, char *argv[])
|
||||
*datap++ = i;
|
||||
|
||||
ident = getpid() & 0xFFFF;
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
gettimeofday(&seed, NULL);
|
||||
srand((unsigned int)(seed.tv_sec ^ seed.tv_usec ^ (long)ident));
|
||||
memset(nonce, 0, sizeof(nonce));
|
||||
for (i = 0; i < sizeof(nonce); i += sizeof(int))
|
||||
*((int *)&nonce[i]) = rand();
|
||||
#else
|
||||
memset(nonce, 0, sizeof(nonce));
|
||||
for (i = 0; i < (int)sizeof(nonce); i += sizeof(u_int32_t))
|
||||
*((u_int32_t *)&nonce[i]) = arc4random();
|
||||
#endif
|
||||
arc4random_buf(nonce, sizeof(nonce));
|
||||
optval = 1;
|
||||
if (options & F_DONTFRAG)
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG,
|
||||
|
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 11, 2011
|
||||
.Dd August 16, 2015
|
||||
.Dt EM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -205,6 +205,11 @@ Tunables can be set at the
|
||||
prompt before booting the kernel or stored in
|
||||
.Xr loader.conf 5 .
|
||||
.Bl -tag -width indent
|
||||
.It Va hw.em.disable_crc_stripping
|
||||
Disable or enable hardware stripping of CRC field.
|
||||
This is mostly useful on BMC/IPMI shared interfaces where stripping the CRC
|
||||
causes remote access over IPMI to fail.
|
||||
Default 0 (enabled).
|
||||
.It Va hw.em.eee_setting
|
||||
Disable or enable Energy Efficient Ethernet.
|
||||
Default 1 (disabled).
|
||||
|
163
share/man/man4/man4.arm/am335x_dmtpps.4
Normal file
163
share/man/man4/man4.arm/am335x_dmtpps.4
Normal file
@ -0,0 +1,163 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 Ian Lepore <ian@freebsd.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 12, 2015
|
||||
.Dt AM335X_DMTPPS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm am335x_dmtpps
|
||||
.Nd RFC 2783 Pulse Per Second API driver for AM335x systems
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device am335x_dmtpps"
|
||||
.Pp
|
||||
Optional in
|
||||
.Pa /boot/loader.conf :
|
||||
.Cd hw.am335x_dmtpps.input="pin name"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
device driver provides a system time counter that includes precise
|
||||
capture of Pulse Per Second (PPS) signals emitted by GPS receivers
|
||||
and other timing devices.
|
||||
The
|
||||
.Nm
|
||||
driver may be compiled into the kernel or loaded as a module.
|
||||
.Pp
|
||||
The AM335x timer hardware captures the value of the system time counter
|
||||
on the leading edge of the PPS pulse.
|
||||
Because the capture is done by the hardware there is no interrupt
|
||||
latency in the measurement.
|
||||
The time counter runs at 24Mhz, providing a measurement resolution
|
||||
of 42 nanoseconds.
|
||||
.Pp
|
||||
To use the PPS timing information provided by this driver with
|
||||
.Xr ntpd 8 ,
|
||||
symlink the
|
||||
.Pa /dev/dmtpps
|
||||
device to
|
||||
.Pa /dev/pps0
|
||||
and configure server
|
||||
.Va 127.127.22.0
|
||||
in
|
||||
.Xr ntp.conf 5
|
||||
to configure a type 22 (ATOM) refclock.
|
||||
.\"
|
||||
.Sh DRIVER CONFIGURATION
|
||||
The AM335x hardware provides four timer devices with a capture input
|
||||
pin, DMTimer4 through DMTimer7.
|
||||
Because it also provides the active system time counter,
|
||||
only one instance of the
|
||||
.Nm
|
||||
driver can be active at a time.
|
||||
The driver uses system pin configuration to determine which hardware
|
||||
timer device to use.
|
||||
Configure the timer input pin in the system's FDT data, or by
|
||||
supplying the pin name using a tunable variable in
|
||||
.Xr loader.conf 5 .
|
||||
.Pp
|
||||
To use a standard kernel and FDT data, use
|
||||
.Xr loader.conf 5
|
||||
to load the
|
||||
.Nm
|
||||
module and set the
|
||||
.Va hw.am335x_dmtpps.input
|
||||
tunable variable to the name of the input pin, one of the following:
|
||||
.Pp
|
||||
.Bl -tag -width "GPMC_ADVn_ALE MMMM" -offset MMMM -compact
|
||||
.It Em Name
|
||||
.Em Hardware
|
||||
.It P8-7
|
||||
DMTimer4; Beaglebone P8 header pin 7.
|
||||
.It P8-8
|
||||
DMTimer7; Beaglebone P8 header pin 8.
|
||||
.It P8-9
|
||||
DMTimer5; Beaglebone P8 header pin 9.
|
||||
.It P8-10
|
||||
DMTimer6; Beaglebone P8 header pin 10.
|
||||
.It GPMC_ADVn_ALE
|
||||
DMTimer4.
|
||||
.It GPMC_BEn0_CLE
|
||||
DMTimer5.
|
||||
.It GPMC_WEn
|
||||
DMTimer6.
|
||||
.It GPMC_OEn_REn
|
||||
DMTimer7.
|
||||
.El
|
||||
.Pp
|
||||
To configure the
|
||||
.Nm
|
||||
driver using FDT data, create a new pinctrl node by referencing the standard
|
||||
.Va am33xx_pinmux
|
||||
driver node (which is defined in am33xx.dtsi) in your dts file.
|
||||
For example:
|
||||
.Bd -literal
|
||||
&am33xx_pinmux {
|
||||
timer4_pins: timer4_pins {
|
||||
pinctrl-single,pins = <0x90 (PIN_INPUT | MUX_MODE2)>;
|
||||
};
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Add pinctrl properties referencing
|
||||
.Va timer4_pins
|
||||
to the standard
|
||||
.Va timer4
|
||||
device node (also defined in am33xx.dtsi) by referencing it in
|
||||
your dts file as follows:
|
||||
.Bd -literal
|
||||
&timer4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&timer4_pins>;
|
||||
};
|
||||
.Ed
|
||||
.\"
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /dev/dmtpps" -compact
|
||||
.It Pa /dev/dmtpps
|
||||
The device providing
|
||||
.Xr ioctl 2
|
||||
access to the RFC 2783 API.
|
||||
.El
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr timecounters 4 ,
|
||||
.Xr loader.conf 5 ,
|
||||
.Xr ntp.conf 5 ,
|
||||
.Xr ntpd 8
|
||||
.\"
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.\"
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Ian Lepore Aq Mt ian@FreeBSD.org .
|
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 30, 2015
|
||||
.Dd August 17, 2015
|
||||
.Dt RANDOM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -31,6 +31,7 @@
|
||||
.Nd the entropy device
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device random"
|
||||
.Cd "options RANDOM_LOADABLE"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
@ -133,15 +134,49 @@ The
|
||||
.Va kern.random.harvest.mask_bin
|
||||
and
|
||||
.Va kern.random.harvest.mask_symbolic
|
||||
sysctl
|
||||
can be used confirm
|
||||
that your choices are correct.
|
||||
sysctls
|
||||
can be used to confirm
|
||||
that the choices are correct.
|
||||
Note that disabled items
|
||||
in the latter item
|
||||
are listed in square brackets.
|
||||
See
|
||||
.Xr random_harvest 9
|
||||
for more on the harvesting of entropy.
|
||||
.Pp
|
||||
When
|
||||
.Cd "options RANDOM_LOADABLE"
|
||||
is used,
|
||||
the
|
||||
.Pa /dev/random
|
||||
device is not created
|
||||
until an "algorithm module"
|
||||
is loaded.
|
||||
Two of these modules
|
||||
are built by default,
|
||||
.Em random_fortuna
|
||||
and
|
||||
.Em random_yarrow .
|
||||
The
|
||||
.Em random_yarrow
|
||||
module is deprecated,
|
||||
and will be removed in
|
||||
.Fx 12.
|
||||
Use of the Yarrow algorithm
|
||||
is not encouraged,
|
||||
but while still present
|
||||
in the kernel source,
|
||||
it can be selected with the
|
||||
.Cd "options RANDOM_YARROW"
|
||||
kernel option.
|
||||
Note that these loadable modules
|
||||
are slightly less efficient
|
||||
than their compiled-in equivalents.
|
||||
This is because some functions
|
||||
must be locked against
|
||||
load and unload events,
|
||||
and also must be indirect calls
|
||||
to allow for removal.
|
||||
.Sh RANDOMNESS
|
||||
The use of randomness in the field of computing
|
||||
is a rather subtle issue because randomness means
|
||||
@ -294,7 +329,7 @@ It replaces the previous
|
||||
implementation,
|
||||
introduced in
|
||||
.Fx 5.0 .
|
||||
The older
|
||||
.Em Yarrow
|
||||
algorithm remains available
|
||||
as a compile-time fallback.
|
||||
The Yarrow algorithm
|
||||
is no longer supported
|
||||
by its authors,
|
||||
and is therefore deprecated.
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 12, 2014
|
||||
.Dd August 12, 2015
|
||||
.Dt TIMECOUNTERS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -96,10 +96,16 @@ compared to others.
|
||||
A negative value means this time counter is broken and should not be used.
|
||||
.El
|
||||
.Pp
|
||||
The time management code of the kernel chooses one time counter from that list.
|
||||
The current choice can be read and affected via the
|
||||
The time management code of the kernel automatically switches to a
|
||||
higher-quality time counter when it registers, unless the
|
||||
.Va kern.timecounter.hardware
|
||||
tunable/sysctl.
|
||||
sysctl has been used to choose a specific device.
|
||||
.Pp
|
||||
There is no way to unregister a time counter once it has registered
|
||||
with the kernel.
|
||||
If a dynamically loaded module contains a time counter you will not
|
||||
be able to unload that module, even if the time counter it contains
|
||||
is not the one currently in use.
|
||||
.Sh SEE ALSO
|
||||
.Xr attimer 4 ,
|
||||
.Xr eventtimers 4 ,
|
||||
|
@ -1,7 +1,7 @@
|
||||
.\" DO NOT EDIT-- this file is automatically generated.
|
||||
.\" from FreeBSD: head/tools/build/options/makeman 284708 2015-06-22 20:21:57Z sjg
|
||||
.\" $FreeBSD$
|
||||
.Dd August 1, 2015
|
||||
.Dd August 16, 2015
|
||||
.Dt SRC.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -137,9 +137,8 @@ associated utilities, and examples.
|
||||
.Pp
|
||||
This option only affects amd64/amd64.
|
||||
.It Va WITHOUT_BINUTILS
|
||||
.\" from FreeBSD: head/tools/build/options/WITHOUT_BINUTILS 286036 2015-07-29 20:02:20Z emaste
|
||||
Set to not build or install binutils (as, c++-filt,
|
||||
ld, nm, objcopy, objdump, readelf, size and strip) as part
|
||||
.\" from FreeBSD: head/tools/build/options/WITHOUT_BINUTILS 286332 2015-08-05 18:30:00Z emaste
|
||||
Set to not build or install binutils (as, ld, objcopy, and objdump ) as part
|
||||
of the normal system build.
|
||||
The resulting system cannot build programs from source.
|
||||
.Pp
|
||||
@ -457,18 +456,6 @@ instead of the one from GNU Binutils.
|
||||
.Pp
|
||||
It is a default setting on
|
||||
arm64/aarch64.
|
||||
.It Va WITHOUT_ELFTOOLCHAIN_TOOLS
|
||||
.\" from FreeBSD: head/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS 286016 2015-07-29 15:42:22Z emaste
|
||||
Set to use
|
||||
.Xr addr2line 1 ,
|
||||
.Xr c++filt 1 ,
|
||||
.Xr nm 1 ,
|
||||
.Xr readelf 1 ,
|
||||
.Xr size 1 ,
|
||||
.Xr strings 1 ,
|
||||
and
|
||||
.Xr strip 1
|
||||
from GNU binutils instead of the ELF Tool Chain project.
|
||||
.It Va WITHOUT_EXAMPLES
|
||||
.\" from FreeBSD: head/tools/build/options/WITHOUT_EXAMPLES 156938 2006-03-21 09:06:24Z ru
|
||||
Set to avoid installing examples to
|
||||
@ -1228,11 +1215,6 @@ Set to disable symbol versioning when building shared libraries.
|
||||
Set to not build
|
||||
.Xr syscons 4
|
||||
support files such as keyboard maps, fonts, and screen output maps.
|
||||
.It Va WITHOUT_SYSINSTALL
|
||||
.\" from FreeBSD: head/tools/build/options/WITHOUT_SYSINSTALL 183242 2008-09-21 22:02:26Z sam
|
||||
Set to not build
|
||||
.Xr sysinstall 8
|
||||
and related programs.
|
||||
.It Va WITH_SYSROOT
|
||||
.\" from FreeBSD: head/tools/build/options/WITH_SYSROOT 284708 2015-06-22 20:21:57Z sjg
|
||||
Enable use of sysroot during build.
|
||||
|
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 9, 2015
|
||||
.Dd August 14, 2015
|
||||
.Dt ATOMIC 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -68,7 +68,7 @@
|
||||
.Fn atomic_testandset_<type> "volatile <type> *p" "u_int v"
|
||||
.Sh DESCRIPTION
|
||||
Each of the atomic operations is guaranteed to be atomic across multiple
|
||||
processors and in the presence of interrupts.
|
||||
threads and in the presence of interrupts.
|
||||
They can be used to implement reference counts or as building blocks for more
|
||||
advanced synchronization primitives such as mutexes.
|
||||
.Ss Types
|
||||
@ -108,59 +108,78 @@ unsigned 16-bit integer
|
||||
.El
|
||||
.Pp
|
||||
These must not be used in MI code because the instructions to implement them
|
||||
efficiently may not be available.
|
||||
.Ss Memory Barriers
|
||||
Memory barriers are used to guarantee the order of data accesses in
|
||||
two ways.
|
||||
First, they specify hints to the compiler to not re-order or optimize the
|
||||
operations.
|
||||
Second, on architectures that do not guarantee ordered data accesses,
|
||||
special instructions or special variants of instructions are used to indicate
|
||||
to the processor that data accesses need to occur in a certain order.
|
||||
As a result, most of the atomic operations have three variants in order to
|
||||
include optional memory barriers.
|
||||
The first form just performs the operation without any explicit barriers.
|
||||
The second form uses a read memory barrier, and the third variant uses a write
|
||||
memory barrier.
|
||||
.Pp
|
||||
The second variant of each operation includes an
|
||||
efficiently might not be available.
|
||||
.Ss Acquire and Release Operations
|
||||
By default, a thread's accesses to different memory locations might not be
|
||||
performed in
|
||||
.Em program order ,
|
||||
that is, the order in which the accesses appear in the source code.
|
||||
To optimize the program's execution, both the compiler and processor might
|
||||
reorder the thread's accesses.
|
||||
However, both ensure that their reordering of the accesses is not visible to
|
||||
the thread.
|
||||
Otherwise, the traditional memory model that is expected by single-threaded
|
||||
programs would be violated.
|
||||
Nonetheless, other threads in a multithreaded program, such as the
|
||||
.Fx
|
||||
kernel, might observe the reordering.
|
||||
Moreover, in some cases, such as the implementation of synchronization between
|
||||
threads, arbitrary reordering might result in the incorrect execution of the
|
||||
program.
|
||||
To constrain the reordering that both the compiler and processor might perform
|
||||
on a thread's accesses, the thread should use atomic operations with
|
||||
.Em acquire
|
||||
memory barrier.
|
||||
This barrier ensures that the effects of this operation are completed before the
|
||||
effects of any later data accesses.
|
||||
As a result, the operation is said to have acquire semantics as it acquires a
|
||||
pseudo-lock requiring further operations to wait until it has completed.
|
||||
To denote this, the suffix
|
||||
and
|
||||
.Em release
|
||||
semantics.
|
||||
.Pp
|
||||
Most of the atomic operations on memory have three variants.
|
||||
The first variant performs the operation without imposing any ordering
|
||||
constraints on memory accesses to other locations.
|
||||
The second variant has acquire semantics, and the third variant has release
|
||||
semantics.
|
||||
In effect, operations with acquire and release semantics establish one-way
|
||||
barriers to reordering.
|
||||
.Pp
|
||||
When an atomic operation has acquire semantics, the effects of the operation
|
||||
must have completed before any subsequent load or store (by program order) is
|
||||
performed.
|
||||
Conversely, acquire semantics do not require that prior loads or stores have
|
||||
completed before the atomic operation is performed.
|
||||
To denote acquire semantics, the suffix
|
||||
.Dq Li _acq
|
||||
is inserted into the function name immediately prior to the
|
||||
.Dq Li _ Ns Aq Fa type
|
||||
suffix.
|
||||
For example, to subtract two integers ensuring that any later writes will
|
||||
happen after the subtraction is performed, use
|
||||
For example, to subtract two integers ensuring that subsequent loads and
|
||||
stores happen after the subtraction is performed, use
|
||||
.Fn atomic_subtract_acq_int .
|
||||
.Pp
|
||||
The third variant of each operation includes a
|
||||
.Em release
|
||||
memory barrier.
|
||||
This ensures that all effects of all previous data accesses are completed
|
||||
before this operation takes place.
|
||||
As a result, the operation is said to have release semantics as it releases
|
||||
any pending data accesses to be completed before its operation is performed.
|
||||
To denote this, the suffix
|
||||
When an atomic operation has release semantics, the effects of all prior
|
||||
loads or stores (by program order) must have completed before the operation
|
||||
is performed.
|
||||
Conversely, release semantics do not require that the effects of the
|
||||
atomic operation must have completed before any subsequent load or store is
|
||||
performed.
|
||||
To denote release semantics, the suffix
|
||||
.Dq Li _rel
|
||||
is inserted into the function name immediately prior to the
|
||||
.Dq Li _ Ns Aq Fa type
|
||||
suffix.
|
||||
For example, to add two long integers ensuring that all previous
|
||||
writes will happen first, use
|
||||
For example, to add two long integers ensuring that all prior loads and
|
||||
stores happen before the addition, use
|
||||
.Fn atomic_add_rel_long .
|
||||
.Pp
|
||||
A practical example of using memory barriers is to ensure that data accesses
|
||||
that are protected by a lock are all performed while the lock is held.
|
||||
To achieve this, one would use a read barrier when acquiring the lock to
|
||||
guarantee that the lock is held before any protected operations are performed.
|
||||
Finally, one would use a write barrier when releasing the lock to ensure that
|
||||
all of the protected operations are completed before the lock is released.
|
||||
The one-way barriers provided by acquire and release operations allow the
|
||||
implementations of common synchronization primitives to express their
|
||||
ordering requirements without also imposing unnecessary ordering.
|
||||
For example, for a critical section guarded by a mutex, an acquire operation
|
||||
when the mutex is locked and a release operation when the mutex is unlocked
|
||||
will prevent any loads or stores from moving outside of the critical
|
||||
section.
|
||||
However, they will not prevent the compiler or processor from moving loads
|
||||
or stores into the critical section, which does not violate the semantics of
|
||||
a mutex.
|
||||
.Ss Multiple Processors
|
||||
In multiprocessor systems, the atomicity of the atomic operations on memory
|
||||
depends on support for cache coherence in the underlying architecture.
|
||||
@ -173,7 +192,7 @@ For example, cache coherence is guaranteed on write-back memory by the
|
||||
and
|
||||
.Tn i386
|
||||
architectures.
|
||||
However, on some architectures, cache coherence may not be enabled on all
|
||||
However, on some architectures, cache coherence might not be enabled on all
|
||||
memory types.
|
||||
To determine if cache coherence is enabled for a non-default memory type,
|
||||
consult the architecture's documentation.
|
||||
|
@ -1,5 +1,6 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2013 The FreeBSD Foundation
|
||||
.\" Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
|
||||
@ -28,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd Aug 11, 2015
|
||||
.Dd August 15, 2015
|
||||
.Dt NV 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -49,6 +50,7 @@
|
||||
.Nm nvlist_send ,
|
||||
.Nm nvlist_recv ,
|
||||
.Nm nvlist_xfer ,
|
||||
.Nm nvlist_in_array ,
|
||||
.Nm nvlist_next ,
|
||||
.Nm nvlist_add ,
|
||||
.Nm nvlist_move ,
|
||||
@ -71,6 +73,8 @@
|
||||
.Fn nvlist_empty "const nvlist_t *nvl"
|
||||
.Ft int
|
||||
.Fn nvlist_flags "const nvlist_t *nvl"
|
||||
.Ft bool
|
||||
.Fn nvlist_in_array "const nvlist_t *nvl"
|
||||
.\"
|
||||
.Ft "nvlist_t *"
|
||||
.Fn nvlist_clone "const nvlist_t *nvl"
|
||||
@ -115,6 +119,16 @@
|
||||
.Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_bool_array "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_number_array "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_string_array "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_nvlist_array "const nvlist_t *nvl" "const char *name"
|
||||
.Ft bool
|
||||
.Fn nvlist_exists_descriptor_array "const nvlist_t *nvl" "const char *name"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn nvlist_add_null "nvlist_t *nvl" "const char *name"
|
||||
@ -134,6 +148,20 @@
|
||||
.Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value"
|
||||
.Ft void
|
||||
.Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size"
|
||||
.Ft void
|
||||
.Fn nvlist_add_bool_array "nvlist_t *nvl" "const char *name" "const bool *value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_add_number_array "nvlist_t *nvl" "const char *name" "const uint64_t *value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_add_string_array "nvlist_t *nvl" "const char *name" "const char * const * value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_add_nvlist_array "nvlist_t *nvl" "const char *name" "const nvlist_t * const * value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_add_descriptor_array "nvlist_t *nvl" "const char *name" "const int *value" "size_t nitems"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value"
|
||||
@ -143,6 +171,20 @@
|
||||
.Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value"
|
||||
.Ft void
|
||||
.Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size"
|
||||
.Ft void
|
||||
.Fn nvlist_move_bool_array "nvlist_t *nvl" "const char *name" "bool *value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_move_number_array "nvlist_t *nvl" "const char *name" "uint64_t *value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_move_string_array "nvlist_t *nvl" "const char *name" "char **value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_move_nvlist_array "nvlist_t *nvl" "const char *name" "nvlist_t **value" "size_t nitems"
|
||||
.
|
||||
.Ft void
|
||||
.Fn nvlist_move_descriptor_array "nvlist_t *nvl" "const char *name" "int *value" "size_t nitems"
|
||||
.\"
|
||||
.Ft bool
|
||||
.Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name"
|
||||
@ -156,8 +198,22 @@
|
||||
.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
|
||||
.Ft "const void *"
|
||||
.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
|
||||
.Ft "const bool *"
|
||||
.Fn nvlist_get_bool_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "const uint64_t *"
|
||||
.Fn nvlist_get_number "const nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "const char * const *"
|
||||
.Fn nvlist_get_string "const nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "const nvlist_t * const *"
|
||||
.Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "const int *"
|
||||
.Fn nvlist_get_descriptor_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "const nvlist_t *"
|
||||
.Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
|
||||
.Ft "const nvlist_t *"
|
||||
.Fn nvlist_get_array_next "const nvlist_t *nvl"
|
||||
.Ft "const nvlist_t *"
|
||||
.Fn nvlist_get_pararr "const nvlist_t *nvl" "void **cookiep"
|
||||
.\"
|
||||
.Ft bool
|
||||
.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
|
||||
@ -171,6 +227,16 @@
|
||||
.Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name"
|
||||
.Ft "void *"
|
||||
.Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep"
|
||||
.Ft "bool *"
|
||||
.Fn nvlist_take_bool_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "uint64_t **"
|
||||
.Fn nvlist_take_number "nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "char **"
|
||||
.Fn nvlist_take_string "nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "nvlist_t **"
|
||||
.Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.Ft "int *"
|
||||
.Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name" "size_t *nitems"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn nvlist_free "nvlist_t *nvl" "const char *name"
|
||||
@ -191,6 +257,16 @@
|
||||
.Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_binary "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_bool_array "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_number_array "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_string_array "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_nvlist_array "nvlist_t *nvl" "const char *name"
|
||||
.Ft void
|
||||
.Fn nvlist_free_descriptor_array "nvlist_t *nvl" "const char *name"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm libnv
|
||||
@ -221,6 +297,23 @@ Note that file descriptors can be sent only over
|
||||
domain sockets.
|
||||
.It Sy binary ( NV_TYPE_BINARY )
|
||||
The value is a binary buffer.
|
||||
.It Sy bool array ( NV_TYPE_BOOL_ARRAY )
|
||||
The value is an array of boolean values.
|
||||
.It Sy number array ( NV_TYPE_NUMBER_ARRAY )
|
||||
The value is an array of numbers, each stored as
|
||||
.Vt uint64_t .
|
||||
.It Sy string array ( NV_TYPE_STRING_ARRAY )
|
||||
The value is an array of C strings.
|
||||
.It Sy nvlist array ( NV_TYPE_NVLIST_ARRAY )
|
||||
The value is an array of nvlists.
|
||||
When an nvlist is added to an array, it becomes part of the primary nvlist.
|
||||
Traversing these arrays can be done using the
|
||||
.Fn nvlist_get_array_next
|
||||
and
|
||||
.Fn nvlist_get_pararr
|
||||
functions.
|
||||
.It Sy descriptor array ( NV_TYPE_DESCRIPTOR_ARRAY )
|
||||
The value is an array of files descriptors.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
@ -280,6 +373,14 @@ function returns flags used to create the nvlist with the
|
||||
function.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_in_array
|
||||
function returns
|
||||
.Dv true
|
||||
if
|
||||
.Fa nvl
|
||||
is part of an array that is a member of another nvlist.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_clone
|
||||
functions clones the given nvlist.
|
||||
The clone shares no resources with its origin.
|
||||
@ -446,7 +547,12 @@ The
|
||||
.Fn nvlist_exists_string ,
|
||||
.Fn nvlist_exists_nvlist ,
|
||||
.Fn nvlist_exists_descriptor ,
|
||||
.Fn nvlist_exists_binary
|
||||
.Fn nvlist_exists_binary ,
|
||||
.Fn nvlist_exists_bool_array ,
|
||||
.Fn nvlist_exists_number_array ,
|
||||
.Fn nvlist_exists_string_array ,
|
||||
.Fn nvlist_exists_nvlist_array ,
|
||||
.Fn nvlist_exists_descriptor_array
|
||||
functions return
|
||||
.Dv true
|
||||
if element of the given name and the given type determined by the function name
|
||||
@ -464,7 +570,12 @@ The
|
||||
.Fn nvlist_add_stringv ,
|
||||
.Fn nvlist_add_nvlist ,
|
||||
.Fn nvlist_add_descriptor ,
|
||||
.Fn nvlist_add_binary
|
||||
.Fn nvlist_add_binary ,
|
||||
.Fn nvlist_add_bool_array ,
|
||||
.Fn nvlist_add_number_array ,
|
||||
.Fn nvlist_add_string_array ,
|
||||
.Fn nvlist_add_nvlist_array ,
|
||||
.Fn nvlist_add_descriptor_array
|
||||
functions add element to the given nvlist.
|
||||
When adding string or binary buffor the functions will allocate memory
|
||||
and copy the data over.
|
||||
@ -472,6 +583,10 @@ When adding nvlist, the nvlist will be cloned and clone will be added.
|
||||
When adding descriptor, the descriptor will be duplicated using the
|
||||
.Xr dup 2
|
||||
system call and the new descriptor will be added.
|
||||
The array functions will fail if there are any
|
||||
.Dv NULL
|
||||
elements in the array, or if the array pointer is
|
||||
.Dv NULL .
|
||||
If an error occurs while adding new element, internal error is set which can be
|
||||
examined using the
|
||||
.Fn nvlist_error
|
||||
@ -481,10 +596,21 @@ The
|
||||
.Fn nvlist_move_string ,
|
||||
.Fn nvlist_move_nvlist ,
|
||||
.Fn nvlist_move_descriptor ,
|
||||
.Fn nvlist_move_binary
|
||||
.Fn nvlist_move_binary ,
|
||||
.Fn nvlist_move_bool_array ,
|
||||
.Fn nvlist_move_number_array ,
|
||||
.Fn nvlist_move_string_array ,
|
||||
.Fn nvlist_move_nvlist_array ,
|
||||
.Fn nvlist_move_descriptor_array
|
||||
functions add new element to the given nvlist, but unlike
|
||||
.Fn nvlist_add_<type>
|
||||
functions they will consume the given resource.
|
||||
In the case of strings, descriptors, or nvlists every elements must be
|
||||
unique, or it could cause a double free.
|
||||
The array functions will fail if there are any
|
||||
.Dv NULL
|
||||
elements, or if the array pointer is
|
||||
.Dv NULL .
|
||||
If an error occurs while adding new element, the resource is destroyed and
|
||||
internal error is set which can be examined using the
|
||||
.Fn nvlist_error
|
||||
@ -496,20 +622,43 @@ The
|
||||
.Fn nvlist_get_string ,
|
||||
.Fn nvlist_get_nvlist ,
|
||||
.Fn nvlist_get_descriptor ,
|
||||
.Fn nvlist_get_binary
|
||||
functions allow to obtain value of the given name.
|
||||
In case of string, nvlist, descriptor or binary, returned resource should
|
||||
not be modified - it still belongs to the nvlist.
|
||||
If element of the given name does not exist, the program will be aborted.
|
||||
To avoid that the caller should check for existence before trying to obtain
|
||||
the value or use
|
||||
.Fn nvlist_get_binary ,
|
||||
.Fn nvlist_get_bool_array ,
|
||||
.Fn nvlist_get_number_array ,
|
||||
.Fn nvlist_get_string_array ,
|
||||
.Fn nvlist_get_nvlist_array ,
|
||||
.Fn nvlist_get_descriptor_array
|
||||
functions return the value that corresponds to the given key name.
|
||||
In the case of strings, nvlists, descriptors, binary, or arrays, the returned
|
||||
resource should not be modified - they still belong to the nvlist.
|
||||
If an element of the given name does not exist, the program will be aborted.
|
||||
To avoid this, the caller should check for the existence of the name before
|
||||
trying to obtain the value, or use the
|
||||
.Xr dnvlist 3
|
||||
extension, which allows to provide default value for a missing element.
|
||||
extension, which can provide a default value in the case of a missing element.
|
||||
The nvlist must not be in error state.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_get_parent
|
||||
function allows to obtain the parent nvlist from the nested nvlist.
|
||||
function returns the parent nvlist of the nested nvlist.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_get_array_next
|
||||
function returns the next element from the array or
|
||||
.Dv NULL
|
||||
if the nvlist is not in array or it is the last element.
|
||||
Note that
|
||||
.Fn nvlist_get_array_next
|
||||
only works if you added the nvlist array using the
|
||||
.Fn nvlist_move_nvlist_array
|
||||
or
|
||||
.Fn nvlist_add_nvlist_array
|
||||
functions.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_get_pararr
|
||||
function returns the next element in the array, or if not available
|
||||
the parent of the nested nvlist.
|
||||
.Pp
|
||||
The
|
||||
.Fn nvlist_take_bool ,
|
||||
@ -517,7 +666,12 @@ The
|
||||
.Fn nvlist_take_string ,
|
||||
.Fn nvlist_take_nvlist ,
|
||||
.Fn nvlist_take_descriptor ,
|
||||
.Fn nvlist_take_binary
|
||||
.Fn nvlist_take_binary ,
|
||||
.Fn nvlist_take_bool_array ,
|
||||
.Fn nvlist_take_number_array ,
|
||||
.Fn nvlist_take_string_array ,
|
||||
.Fn nvlist_take_nvlist_array ,
|
||||
.Fn nvlist_take_descriptor_array
|
||||
functions return value associated with the given name and remove the element
|
||||
from the nvlist.
|
||||
In case of string and binary values, the caller is responsible for free returned
|
||||
@ -532,11 +686,27 @@ In case of descriptor, the caller is responsible for closing returned descriptor
|
||||
using the
|
||||
.Fn close 2
|
||||
system call.
|
||||
If element of the given name does not exist, the program will be aborted.
|
||||
To avoid that the caller should check for existence before trying to obtain
|
||||
the value or use
|
||||
If an element of the given name does not exist, the program will be aborted.
|
||||
To avoid that the caller should check for the existence of the given name
|
||||
before trying to obtain the value, or use the
|
||||
.Xr dnvlist 3
|
||||
extension, which allows to provide default value for a missing element.
|
||||
extension, which can provide a default value in the case of a missing element.
|
||||
In the case of an array of strings or binary values, the caller is responsible
|
||||
for freeing every element of the array using the
|
||||
.Xr free 3
|
||||
function.
|
||||
In the case of an array of nvlists, the caller is responsible for destroying
|
||||
every element of array using the
|
||||
.Fn nvlist_destroy
|
||||
function.
|
||||
In the case of descriptors, the caller is responsible for closing every
|
||||
element of array using the
|
||||
.Fn close 2
|
||||
system call.
|
||||
In every case involving an array, the caller must also free the pointer to
|
||||
the array using the
|
||||
.Xr free 3
|
||||
function.
|
||||
The nvlist must not be in error state.
|
||||
.Pp
|
||||
The
|
||||
@ -561,7 +731,12 @@ The
|
||||
.Fn nvlist_free_string ,
|
||||
.Fn nvlist_free_nvlist ,
|
||||
.Fn nvlist_free_descriptor ,
|
||||
.Fn nvlist_free_binary
|
||||
.Fn nvlist_free_binary ,
|
||||
.Fn nvlist_free_bool_array ,
|
||||
.Fn nvlist_free_number_array ,
|
||||
.Fn nvlist_free_string_array ,
|
||||
.Fn nvlist_free_nvlist_array ,
|
||||
.Fn nvlist_free_descriptor_array
|
||||
functions remove element of the given name and the given type determined by the
|
||||
function name from the nvlist and free all resources associated with it.
|
||||
If element of the given name and the given type does not exist, the program
|
||||
@ -679,6 +854,65 @@ do {
|
||||
}
|
||||
} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
|
||||
.Ed
|
||||
.Pp
|
||||
Iterating over every nested nvlist and every nvlist element:
|
||||
.Bd -literal
|
||||
nvlist_t *nvl;
|
||||
const nvlist_t * const *array;
|
||||
const char *name;
|
||||
void *cookie;
|
||||
int type;
|
||||
|
||||
nvl = nvlist_recv(sock, 0);
|
||||
if (nvl == null)
|
||||
err(1, "nvlist_recv() failed");
|
||||
|
||||
cookie = null;
|
||||
do {
|
||||
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
|
||||
if (type == NV_TYPE_NVLIST) {
|
||||
nvl = nvlist_get_nvlist(nvl, name);
|
||||
cookie = NULL;
|
||||
} else if (type == NV_TYPE_NVLIST_ARRAY) {
|
||||
nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0];
|
||||
cookie = NULL;
|
||||
}
|
||||
}
|
||||
} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
|
||||
.Ed
|
||||
.Pp
|
||||
Or alternatively:
|
||||
.Bd -literal
|
||||
nvlist_t *nvl, *tmp;
|
||||
const nvlist_t * const *array;
|
||||
const char *name;
|
||||
void *cookie;
|
||||
int type;
|
||||
|
||||
nvl = nvlist_recv(sock, 0);
|
||||
if (nvl == null)
|
||||
err(1, "nvlist_recv() failed");
|
||||
|
||||
cooke = NULL;
|
||||
tmp = nvl;
|
||||
do {
|
||||
do {
|
||||
nvl = tmp;
|
||||
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
|
||||
if (type == NV_TYPE_NVLIST) {
|
||||
nvl = nvlist_get_nvlist(nvl,
|
||||
name);
|
||||
cookie = NULL;
|
||||
} else if (type == NV_TYPE_NVLIST_ARRAY) {
|
||||
nvl = nvlist_get_nvlist_array(nvl, name,
|
||||
NULL)[0];
|
||||
cookie = NULL;
|
||||
}
|
||||
}
|
||||
cookie = NULL;
|
||||
} while ((tmp = nvlist_get_array_next(nvl)) != NULL);
|
||||
} while ((tmp = nvlist_get_parent(nvl, &cookie)) != NULL);
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr close 2 ,
|
||||
.Xr dup 2 ,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -171,7 +171,7 @@ _LIBS= lib${LIB_PRIVATE}${LIB}.a
|
||||
lib${LIB_PRIVATE}${LIB}.a: ${OBJS} ${STATICOBJS}
|
||||
@${ECHO} building static ${LIB} library
|
||||
@rm -f ${.TARGET}
|
||||
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' lorder ${OBJS} ${STATICOBJS} | tsort -q` ${ARADD}
|
||||
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' NMFLAGS='${NMFLAGS}' lorder ${OBJS} ${STATICOBJS} | tsort -q` ${ARADD}
|
||||
${RANLIB} ${RANLIBFLAGS} ${.TARGET}
|
||||
.endif
|
||||
|
||||
@ -185,7 +185,7 @@ NOPATH_FILES+= ${POBJS}
|
||||
lib${LIB_PRIVATE}${LIB}_p.a: ${POBJS}
|
||||
@${ECHO} building profiled ${LIB} library
|
||||
@rm -f ${.TARGET}
|
||||
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' lorder ${POBJS} | tsort -q` ${ARADD}
|
||||
${AR} ${ARFLAGS} ${.TARGET} `NM='${NM}' NMFLAGS='${NMFLAGS}' lorder ${POBJS} | tsort -q` ${ARADD}
|
||||
${RANLIB} ${RANLIBFLAGS} ${.TARGET}
|
||||
.endif
|
||||
|
||||
@ -250,7 +250,7 @@ ${SHLIB_NAME_FULL}: ${SOBJS}
|
||||
.endif
|
||||
${_LD} ${LDFLAGS} ${SSP_CFLAGS} ${SOLINKOPTS} \
|
||||
-o ${.TARGET} -Wl,-soname,${SONAME} \
|
||||
`NM='${NM}' lorder ${SOBJS} | tsort -q` ${LDADD}
|
||||
`NM='${NM}' NMFLAGS='${NMFLAGS}' lorder ${SOBJS} | tsort -q` ${LDADD}
|
||||
.if ${MK_CTF} != "no"
|
||||
${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${SOBJS}
|
||||
.endif
|
||||
|
@ -80,7 +80,7 @@ __DEFAULT_YES_OPTIONS = \
|
||||
DYNAMICROOT \
|
||||
ED_CRYPTO \
|
||||
EE \
|
||||
ELFTOOLCHAIN_TOOLS \
|
||||
ELFTOOLCHAIN_BOOTSTRAP \
|
||||
EXAMPLES \
|
||||
FDT \
|
||||
FILE \
|
||||
@ -156,7 +156,6 @@ __DEFAULT_YES_OPTIONS = \
|
||||
SOURCELESS_UCODE \
|
||||
SVNLITE \
|
||||
SYSCONS \
|
||||
SYSINSTALL \
|
||||
TALK \
|
||||
TCP_WRAPPERS \
|
||||
TCSH \
|
||||
@ -330,6 +329,7 @@ MK_GROFF:= no
|
||||
.if ${MK_CROSS_COMPILER} == "no"
|
||||
MK_BINUTILS_BOOTSTRAP:= no
|
||||
MK_CLANG_BOOTSTRAP:= no
|
||||
MK_ELFTOOLCHAIN_BOOTSTRAP:= no
|
||||
MK_GCC_BOOTSTRAP:= no
|
||||
.endif
|
||||
|
||||
|
@ -167,6 +167,7 @@ MAKE ?= make
|
||||
|
||||
.if !defined(%POSIX)
|
||||
NM ?= nm
|
||||
NMFLAGS ?=
|
||||
|
||||
OBJC ?= cc
|
||||
OBJCFLAGS ?= ${OBJCINCLUDES} ${CFLAGS} -Wno-import
|
||||
|
@ -390,6 +390,8 @@ static struct md_page *pv_table;
|
||||
*/
|
||||
pt_entry_t *CMAP1 = 0;
|
||||
caddr_t CADDR1 = 0;
|
||||
static vm_offset_t qframe = 0;
|
||||
static struct mtx qframe_mtx;
|
||||
|
||||
static int pmap_flags = PMAP_PDE_SUPERPAGE; /* flags for x86 pmaps */
|
||||
|
||||
@ -1031,7 +1033,7 @@ pmap_init(void)
|
||||
struct pmap_preinit_mapping *ppim;
|
||||
vm_page_t mpte;
|
||||
vm_size_t s;
|
||||
int i, pv_npg;
|
||||
int error, i, pv_npg;
|
||||
|
||||
/*
|
||||
* Initialize the vm page array entries for the kernel pmap's
|
||||
@ -1112,6 +1114,12 @@ pmap_init(void)
|
||||
printf("PPIM %u: PA=%#lx, VA=%#lx, size=%#lx, mode=%#x\n", i,
|
||||
ppim->pa, ppim->va, ppim->sz, ppim->mode);
|
||||
}
|
||||
|
||||
mtx_init(&qframe_mtx, "qfrmlk", NULL, MTX_SPIN);
|
||||
error = vmem_alloc(kernel_arena, PAGE_SIZE, M_BESTFIT | M_WAITOK,
|
||||
(vmem_addr_t *)&qframe);
|
||||
if (error != 0)
|
||||
panic("qframe allocation failed");
|
||||
}
|
||||
|
||||
static SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0,
|
||||
@ -7019,13 +7027,27 @@ pmap_unmap_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
|
||||
vm_offset_t
|
||||
pmap_quick_enter_page(vm_page_t m)
|
||||
{
|
||||
vm_paddr_t paddr;
|
||||
|
||||
return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)));
|
||||
paddr = VM_PAGE_TO_PHYS(m);
|
||||
if (paddr < dmaplimit)
|
||||
return (PHYS_TO_DMAP(paddr));
|
||||
mtx_lock_spin(&qframe_mtx);
|
||||
KASSERT(*vtopte(qframe) == 0, ("qframe busy"));
|
||||
pte_store(vtopte(qframe), paddr | X86_PG_RW | X86_PG_V | X86_PG_A |
|
||||
X86_PG_M | pmap_cache_bits(kernel_pmap, m->md.pat_mode, 0));
|
||||
return (qframe);
|
||||
}
|
||||
|
||||
void
|
||||
pmap_quick_remove_page(vm_offset_t addr)
|
||||
{
|
||||
|
||||
if (addr != qframe)
|
||||
return;
|
||||
pte_store(vtopte(qframe), 0);
|
||||
invlpg(qframe);
|
||||
mtx_unlock_spin(&qframe_mtx);
|
||||
}
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
@ -904,6 +904,7 @@ set_cpufuncs()
|
||||
cputype == CPU_ID_CORTEXA9R1 ||
|
||||
cputype == CPU_ID_CORTEXA9R2 ||
|
||||
cputype == CPU_ID_CORTEXA9R3 ||
|
||||
cputype == CPU_ID_CORTEXA9R4 ||
|
||||
cputype == CPU_ID_CORTEXA12R0 ||
|
||||
cputype == CPU_ID_CORTEXA15R0 ||
|
||||
cputype == CPU_ID_CORTEXA15R1 ||
|
||||
|
@ -185,6 +185,8 @@ const struct cpuidtab cpuids[] = {
|
||||
generic_steppings },
|
||||
{ CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3",
|
||||
generic_steppings },
|
||||
{ CPU_ID_CORTEXA9R4, CPU_CLASS_CORTEXA, "Cortex A9-r4",
|
||||
generic_steppings },
|
||||
{ CPU_ID_CORTEXA12R0, CPU_CLASS_CORTEXA, "Cortex A12-r0",
|
||||
generic_steppings },
|
||||
{ CPU_ID_CORTEXA15R0, CPU_CLASS_CORTEXA, "Cortex A15-r0",
|
||||
|
@ -1166,10 +1166,9 @@ pmap_init_qpages(void)
|
||||
pc = pcpu_find(i);
|
||||
pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
|
||||
if (pc->pc_qmap_addr == 0)
|
||||
panic("pmap_init_qpages: unable to allocate KVA");
|
||||
panic("%s: unable to allocate KVA", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
|
||||
|
||||
/*
|
||||
@ -5728,18 +5727,17 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
|
||||
vm_offset_t
|
||||
pmap_quick_enter_page(vm_page_t m)
|
||||
{
|
||||
pt2_entry_t *pte;
|
||||
vm_offset_t qmap_addr;
|
||||
pt2_entry_t *pte2p;
|
||||
vm_offset_t qmap_addr;
|
||||
|
||||
critical_enter();
|
||||
|
||||
qmap_addr = PCPU_GET(qmap_addr);
|
||||
pte = pt2map_entry(qmap_addr);
|
||||
pte2p = pt2map_entry(qmap_addr);
|
||||
|
||||
KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy"));
|
||||
KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__));
|
||||
|
||||
pte2_store(pte, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m),
|
||||
PTE2_AP_KRW, pmap_page_get_memattr(m)));
|
||||
pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
|
||||
pmap_page_get_memattr(m)));
|
||||
tlb_flush_local(qmap_addr);
|
||||
|
||||
return (qmap_addr);
|
||||
@ -5748,16 +5746,16 @@ pmap_quick_enter_page(vm_page_t m)
|
||||
void
|
||||
pmap_quick_remove_page(vm_offset_t addr)
|
||||
{
|
||||
pt2_entry_t *pte;
|
||||
pt2_entry_t *pte2p;
|
||||
vm_offset_t qmap_addr;
|
||||
|
||||
qmap_addr = PCPU_GET(qmap_addr);
|
||||
pte = pt2map_entry(qmap_addr);
|
||||
pte2p = pt2map_entry(qmap_addr);
|
||||
|
||||
KASSERT(addr == qmap_addr, ("pmap_quick_remove_page: invalid address"));
|
||||
KASSERT(*pte != 0, ("pmap_quick_remove_page: PTE not in use"));
|
||||
KASSERT(addr == qmap_addr, ("%s: invalid address", __func__));
|
||||
KASSERT(pte2_load(pte2p) != 0, ("%s: PTE2 not in use", __func__));
|
||||
|
||||
pte2_clear(pte);
|
||||
pte2_clear(pte2p);
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <machine/acle-compat.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
@ -67,19 +68,12 @@ do_sync(void)
|
||||
|
||||
__asm volatile ("" : : : "memory");
|
||||
}
|
||||
#elif __ARM_ARCH >= 7
|
||||
static inline void
|
||||
do_sync(void)
|
||||
{
|
||||
|
||||
__asm volatile ("dmb" : : : "memory");
|
||||
}
|
||||
#elif __ARM_ARCH >= 6
|
||||
static inline void
|
||||
do_sync(void)
|
||||
{
|
||||
|
||||
__asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
|
||||
dmb();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define BCM2835_NUM_TIMERS 4
|
||||
|
||||
#define DEFAULT_TIMER 3
|
||||
#define DEFAULT_TIMER_NAME "BCM2835-3"
|
||||
#define DEFAULT_FREQUENCY 1000000
|
||||
#define MIN_PERIOD 5LLU
|
||||
|
||||
@ -101,7 +102,7 @@ static struct bcm_systimer_softc *bcm_systimer_sc = NULL;
|
||||
static unsigned bcm_systimer_tc_get_timecount(struct timecounter *);
|
||||
|
||||
static struct timecounter bcm_systimer_tc = {
|
||||
.tc_name = "BCM2835 Timecounter",
|
||||
.tc_name = DEFAULT_TIMER_NAME,
|
||||
.tc_get_timecount = bcm_systimer_tc_get_timecount,
|
||||
.tc_poll_pps = NULL,
|
||||
.tc_counter_mask = ~0u,
|
||||
@ -238,8 +239,7 @@ bcm_systimer_attach(device_t dev)
|
||||
|
||||
sc->st[DEFAULT_TIMER].index = DEFAULT_TIMER;
|
||||
sc->st[DEFAULT_TIMER].enabled = 0;
|
||||
sc->st[DEFAULT_TIMER].et.et_name = malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
sprintf(sc->st[DEFAULT_TIMER].et.et_name, "BCM2835 Event Timer %d", DEFAULT_TIMER);
|
||||
sc->st[DEFAULT_TIMER].et.et_name = DEFAULT_TIMER_NAME;
|
||||
sc->st[DEFAULT_TIMER].et.et_flags = ET_FLAGS_ONESHOT;
|
||||
sc->st[DEFAULT_TIMER].et.et_quality = 1000;
|
||||
sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
|
||||
|
@ -26,7 +26,7 @@ ident BEAGLEBONE
|
||||
include "std.armv6"
|
||||
include "../ti/am335x/std.am335x"
|
||||
|
||||
makeoptions MODULES_EXTRA="dtb/am335x"
|
||||
makeoptions MODULES_EXTRA="dtb/am335x am335x_dmtpps"
|
||||
|
||||
# DTrace support
|
||||
options KDTRACE_HOOKS # Kernel DTrace hooks
|
||||
@ -77,6 +77,7 @@ device ti_i2c
|
||||
device am335x_pmic # AM335x Power Management IC (TPC65217)
|
||||
|
||||
device am335x_rtc # RTC support (power management only)
|
||||
#define am335x_dmtpps # Pulse Per Second capture driver
|
||||
|
||||
# Console and misc
|
||||
device uart
|
||||
|
@ -133,6 +133,7 @@
|
||||
#define CPU_ID_CORTEXA9R1 0x411fc090
|
||||
#define CPU_ID_CORTEXA9R2 0x412fc090
|
||||
#define CPU_ID_CORTEXA9R3 0x413fc090
|
||||
#define CPU_ID_CORTEXA9R4 0x414fc090
|
||||
#define CPU_ID_CORTEXA12R0 0x410fc0d0
|
||||
#define CPU_ID_CORTEXA15R0 0x410fc0f0
|
||||
#define CPU_ID_CORTEXA15R1 0x411fc0f0
|
||||
|
549
sys/arm/ti/am335x/am335x_dmtpps.c
Normal file
549
sys/arm/ti/am335x/am335x_dmtpps.c
Normal file
@ -0,0 +1,549 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ian lepore <ian@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* AM335x PPS driver using DMTimer capture.
|
||||
*
|
||||
* Note that this PPS driver does not use an interrupt. Instead it uses the
|
||||
* hardware's ability to latch the timer's count register in response to a
|
||||
* signal on an IO pin. Each of timers 4-7 have an associated pin, and this
|
||||
* code allows any one of those to be used.
|
||||
*
|
||||
* The timecounter routines in kern_tc.c call the pps poll routine periodically
|
||||
* to see if a new counter value has been latched. When a new value has been
|
||||
* latched, the only processing done in the poll routine is to capture the
|
||||
* current set of timecounter timehands (done with pps_capture()) and the
|
||||
* latched value from the timer. The remaining work (done by pps_event() while
|
||||
* holding a mutex) is scheduled to be done later in a non-interrupt context.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/timepps.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <arm/ti/ti_prcm.h>
|
||||
#include <arm/ti/ti_hwmods.h>
|
||||
#include <arm/ti/ti_pinmux.h>
|
||||
#include <arm/ti/am335x/am335x_scm_padconf.h>
|
||||
|
||||
#include "am335x_dmtreg.h"
|
||||
|
||||
#define PPS_CDEV_NAME "dmtpps"
|
||||
|
||||
struct dmtpps_softc {
|
||||
device_t dev;
|
||||
int mem_rid;
|
||||
struct resource * mem_res;
|
||||
int tmr_num; /* N from hwmod str "timerN" */
|
||||
char tmr_name[12]; /* "DMTimerN" */
|
||||
uint32_t tclr; /* Cached TCLR register. */
|
||||
struct timecounter tc;
|
||||
int pps_curmode; /* Edge mode now set in hw. */
|
||||
struct task pps_task; /* For pps_event handling. */
|
||||
struct cdev * pps_cdev;
|
||||
struct pps_state pps_state;
|
||||
struct mtx pps_mtx;
|
||||
};
|
||||
|
||||
static int dmtpps_tmr_num; /* Set by probe() */
|
||||
|
||||
/* List of compatible strings for FDT tree */
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"ti,am335x-timer", 1},
|
||||
{"ti,am335x-timer-1ms", 1},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* A table relating pad names to the hardware timer number they can be mux'd to.
|
||||
*/
|
||||
struct padinfo {
|
||||
char * ballname;
|
||||
int tmr_num;
|
||||
};
|
||||
static struct padinfo dmtpps_padinfo[] = {
|
||||
{"GPMC_ADVn_ALE", 4},
|
||||
{"I2C0_SDA", 4},
|
||||
{"MII1_TX_EN", 4},
|
||||
{"XDMA_EVENT_INTR0", 4},
|
||||
{"GPMC_BEn0_CLE", 5},
|
||||
{"MDC", 5},
|
||||
{"MMC0_DAT3", 5},
|
||||
{"UART1_RTSn", 5},
|
||||
{"GPMC_WEn", 6},
|
||||
{"MDIO", 6},
|
||||
{"MMC0_DAT2", 6},
|
||||
{"UART1_CTSn", 6},
|
||||
{"GPMC_OEn_REn", 7},
|
||||
{"I2C0_SCL", 7},
|
||||
{"UART0_CTSn", 7},
|
||||
{"XDMA_EVENT_INTR1", 7},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* This is either brilliantly user-friendly, or utterly lame...
|
||||
*
|
||||
* The am335x chip is used on the popular Beaglebone boards. Those boards have
|
||||
* pins for all four capture-capable timers available on the P8 header. Allow
|
||||
* users to configure the input pin by giving the name of the header pin.
|
||||
*/
|
||||
struct nicknames {
|
||||
const char * nick;
|
||||
const char * name;
|
||||
};
|
||||
static struct nicknames dmtpps_pin_nicks[] = {
|
||||
{"P8-7", "GPMC_ADVn_ALE"},
|
||||
{"P8-9", "GPMC_BEn0_CLE"},
|
||||
{"P8-10", "GPMC_WEn"},
|
||||
{"P8-8", "GPMC_OEn_REn",},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#define DMTIMER_READ4(sc, reg) bus_read_4((sc)->mem_res, (reg))
|
||||
#define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->mem_res, (reg), (val))
|
||||
|
||||
/*
|
||||
* Translate a short friendly case-insensitive name to its canonical name.
|
||||
*/
|
||||
static const char *
|
||||
dmtpps_translate_nickname(const char *nick)
|
||||
{
|
||||
struct nicknames *nn;
|
||||
|
||||
for (nn = dmtpps_pin_nicks; nn->nick != NULL; nn++)
|
||||
if (strcasecmp(nick, nn->nick) == 0)
|
||||
return nn->name;
|
||||
return (nick);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if our tunable is set to the name of the input pin. If not, that's NOT
|
||||
* an error, return 0. If so, try to configure that pin as a timer capture
|
||||
* input pin, and if that works, then we have our timer unit number and if it
|
||||
* fails that IS an error, return -1.
|
||||
*/
|
||||
static int
|
||||
dmtpps_find_tmr_num_by_tunable()
|
||||
{
|
||||
struct padinfo *pi;
|
||||
char iname[20];
|
||||
char muxmode[12];
|
||||
const char * ballname;
|
||||
int err;
|
||||
|
||||
if (!TUNABLE_STR_FETCH("hw.am335x_dmtpps.input", iname, sizeof(iname)))
|
||||
return (0);
|
||||
ballname = dmtpps_translate_nickname(iname);
|
||||
for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
|
||||
if (strcmp(ballname, pi->ballname) != 0)
|
||||
continue;
|
||||
snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
|
||||
err = ti_pinmux_padconf_set(pi->ballname, muxmode,
|
||||
PADCONF_INPUT);
|
||||
if (err != 0) {
|
||||
printf("am335x_dmtpps: unable to configure capture pin "
|
||||
"for %s to input mode\n", muxmode);
|
||||
return (-1);
|
||||
} else if (bootverbose) {
|
||||
printf("am335x_dmtpps: configured pin %s as input "
|
||||
"for %s\n", iname, muxmode);
|
||||
}
|
||||
return (pi->tmr_num);
|
||||
}
|
||||
|
||||
/* Invalid name in the tunable, that's an error. */
|
||||
printf("am335x_dmtpps: unknown pin name '%s'\n", iname);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the pinmux driver whether any pin has been configured as a TIMER4..TIMER7
|
||||
* input pin. If so, return the timer number, if not return 0.
|
||||
*/
|
||||
static int
|
||||
dmtpps_find_tmr_num_by_padconf()
|
||||
{
|
||||
int err;
|
||||
unsigned int padstate;
|
||||
const char * padmux;
|
||||
struct padinfo *pi;
|
||||
char muxmode[12];
|
||||
|
||||
for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
|
||||
err = ti_pinmux_padconf_get(pi->ballname, &padmux, &padstate);
|
||||
snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
|
||||
if (err == 0 && (padstate & RXACTIVE) != 0 &&
|
||||
strcmp(muxmode, padmux) == 0)
|
||||
return (pi->tmr_num);
|
||||
}
|
||||
/* Nothing found, not an error. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out which hardware timer number to use based on input pin
|
||||
* configuration. This is done just once, the first time probe() runs.
|
||||
*/
|
||||
static int
|
||||
dmtpps_find_tmr_num()
|
||||
{
|
||||
int tmr_num;
|
||||
|
||||
if ((tmr_num = dmtpps_find_tmr_num_by_tunable()) == 0)
|
||||
tmr_num = dmtpps_find_tmr_num_by_padconf();
|
||||
|
||||
if (tmr_num <= 0) {
|
||||
printf("am335x_dmtpps: PPS driver not enabled: unable to find "
|
||||
"or configure a capture input pin\n");
|
||||
tmr_num = -1; /* Must return non-zero to prevent re-probing. */
|
||||
}
|
||||
return (tmr_num);
|
||||
}
|
||||
|
||||
static void
|
||||
dmtpps_set_hw_capture(struct dmtpps_softc *sc, bool force_off)
|
||||
{
|
||||
int newmode;
|
||||
|
||||
if (force_off)
|
||||
newmode = 0;
|
||||
else
|
||||
newmode = sc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT;
|
||||
|
||||
if (newmode == sc->pps_curmode)
|
||||
return;
|
||||
sc->pps_curmode = newmode;
|
||||
|
||||
if (newmode == PPS_CAPTUREASSERT)
|
||||
sc->tclr |= DMT_TCLR_CAPTRAN_LOHI;
|
||||
else
|
||||
sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK;
|
||||
DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
dmtpps_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
|
||||
sc = tc->tc_priv;
|
||||
|
||||
return (DMTIMER_READ4(sc, DMT_TCRR));
|
||||
}
|
||||
|
||||
static void
|
||||
dmtpps_poll(struct timecounter *tc)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
|
||||
sc = tc->tc_priv;
|
||||
|
||||
/*
|
||||
* If a new value has been latched we've got a PPS event. Capture the
|
||||
* timecounter data, then override the capcount field (pps_capture()
|
||||
* populates it from the current DMT_TCRR register) with the latched
|
||||
* value from the TCAR1 register.
|
||||
*
|
||||
* There is no locking here, by design. pps_capture() writes into an
|
||||
* area of struct pps_state which is read only by pps_event(). The
|
||||
* synchronization of access to that area is temporal rather than
|
||||
* interlock based... we write in this routine and trigger the task that
|
||||
* will read the data, so no simultaneous access can occur.
|
||||
*
|
||||
* Note that we don't have the TCAR interrupt enabled, but the hardware
|
||||
* still provides the status bits in the "RAW" status register even when
|
||||
* they're masked from generating an irq. However, when clearing the
|
||||
* TCAR status to re-arm the capture for the next second, we have to
|
||||
* write to the IRQ status register, not the RAW register. Quirky.
|
||||
*/
|
||||
if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {
|
||||
pps_capture(&sc->pps_state);
|
||||
sc->pps_state.capcount = DMTIMER_READ4(sc, DMT_TCAR1);
|
||||
DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);
|
||||
taskqueue_enqueue_fast(taskqueue_fast, &sc->pps_task);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmtpps_event(void *arg, int pending)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
|
||||
sc = arg;
|
||||
|
||||
/* This is the task function that gets enqueued by poll_pps. Once the
|
||||
* time has been captured by the timecounter polling code which runs in
|
||||
* primary interrupt context, the remaining (more expensive) work to
|
||||
* process the event is done later in a threaded context.
|
||||
*
|
||||
* Here there is an interlock that protects the event data in struct
|
||||
* pps_state. That data can be accessed at any time from userland via
|
||||
* ioctl() calls so we must ensure that there is no read access to
|
||||
* partially updated data while pps_event() does its work.
|
||||
*/
|
||||
mtx_lock(&sc->pps_mtx);
|
||||
pps_event(&sc->pps_state, PPS_CAPTUREASSERT);
|
||||
mtx_unlock(&sc->pps_mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
dmtpps_open(struct cdev *dev, int flags, int fmt,
|
||||
struct thread *td)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/*
|
||||
* Begin polling for pps and enable capture in the hardware whenever the
|
||||
* device is open. Doing this stuff again is harmless if this isn't the
|
||||
* first open.
|
||||
*/
|
||||
sc->tc.tc_poll_pps = dmtpps_poll;
|
||||
dmtpps_set_hw_capture(sc, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dmtpps_close(struct cdev *dev, int flags, int fmt,
|
||||
struct thread *td)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/*
|
||||
* Stop polling and disable capture on last close. Use the force-off
|
||||
* flag to override the configured mode and turn off the hardware.
|
||||
*/
|
||||
sc->tc.tc_poll_pps = NULL;
|
||||
dmtpps_set_hw_capture(sc, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dmtpps_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
int err;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/* Let the kernel do the heavy lifting for ioctl. */
|
||||
mtx_lock(&sc->pps_mtx);
|
||||
err = pps_ioctl(cmd, data, &sc->pps_state);
|
||||
mtx_unlock(&sc->pps_mtx);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
/*
|
||||
* The capture mode could have changed, set the hardware to whatever
|
||||
* mode is now current. Effectively a no-op if nothing changed.
|
||||
*/
|
||||
dmtpps_set_hw_capture(sc, false);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static struct cdevsw dmtpps_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = dmtpps_open,
|
||||
.d_close = dmtpps_close,
|
||||
.d_ioctl = dmtpps_ioctl,
|
||||
.d_name = PPS_CDEV_NAME,
|
||||
};
|
||||
|
||||
static int
|
||||
dmtpps_probe(device_t dev)
|
||||
{
|
||||
char strbuf[64];
|
||||
int tmr_num;
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* If we haven't chosen which hardware timer to use yet, go do that now.
|
||||
* We need to know that to decide whether to return success for this
|
||||
* hardware timer instance or not.
|
||||
*/
|
||||
if (dmtpps_tmr_num == 0)
|
||||
dmtpps_tmr_num = dmtpps_find_tmr_num();
|
||||
|
||||
/*
|
||||
* Figure out which hardware timer is being probed and see if it matches
|
||||
* the configured timer number determined earlier.
|
||||
*/
|
||||
tmr_num = ti_hwmods_get_unit(dev, "timer");
|
||||
if (dmtpps_tmr_num != tmr_num)
|
||||
return (ENXIO);
|
||||
|
||||
snprintf(strbuf, sizeof(strbuf), "AM335x PPS-Capture DMTimer%d",
|
||||
tmr_num);
|
||||
device_set_desc_copy(dev, strbuf);
|
||||
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
dmtpps_attach(device_t dev)
|
||||
{
|
||||
struct dmtpps_softc *sc;
|
||||
clk_ident_t timer_id;
|
||||
int err, sysclk_freq;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
/* Get the base clock frequency. */
|
||||
err = ti_prcm_clk_get_source_freq(SYS_CLK, &sysclk_freq);
|
||||
|
||||
/* Enable clocks and power on the device. */
|
||||
if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT)
|
||||
return (ENXIO);
|
||||
if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0)
|
||||
return (err);
|
||||
if ((err = ti_prcm_clk_enable(timer_id)) != 0)
|
||||
return (err);
|
||||
|
||||
/* Request the memory resources. */
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->mem_rid, RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Figure out which hardware timer this is and set the name string. */
|
||||
sc->tmr_num = ti_hwmods_get_unit(dev, "timer");
|
||||
snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
|
||||
|
||||
/* Set up timecounter hardware, start it. */
|
||||
DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
|
||||
while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
|
||||
continue;
|
||||
|
||||
sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
|
||||
DMTIMER_WRITE4(sc, DMT_TLDR, 0);
|
||||
DMTIMER_WRITE4(sc, DMT_TCRR, 0);
|
||||
DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
|
||||
|
||||
/* Register the timecounter. */
|
||||
sc->tc.tc_name = sc->tmr_name;
|
||||
sc->tc.tc_get_timecount = dmtpps_get_timecount;
|
||||
sc->tc.tc_counter_mask = ~0u;
|
||||
sc->tc.tc_frequency = sysclk_freq;
|
||||
sc->tc.tc_quality = 1000;
|
||||
sc->tc.tc_priv = sc;
|
||||
|
||||
tc_init(&sc->tc);
|
||||
|
||||
/*
|
||||
* Indicate our PPS capabilities. Have the kernel init its part of the
|
||||
* pps_state struct and add its capabilities.
|
||||
*
|
||||
* While the hardware has a mode to capture each edge, it's not clear we
|
||||
* can use it that way, because there's only a single interrupt/status
|
||||
* bit to say something was captured, but not which edge it was. For
|
||||
* now, just say we can only capture assert events (the positive-going
|
||||
* edge of the pulse).
|
||||
*/
|
||||
mtx_init(&sc->pps_mtx, "dmtpps", NULL, MTX_DEF);
|
||||
sc->pps_state.ppscap = PPS_CAPTUREASSERT;
|
||||
sc->pps_state.driver_abi = PPS_ABI_VERSION;
|
||||
sc->pps_state.driver_mtx = &sc->pps_mtx;
|
||||
pps_init_abi(&sc->pps_state);
|
||||
|
||||
/*
|
||||
* Init the task that does deferred pps_event() processing after
|
||||
* the polling routine has captured a pps pulse time.
|
||||
*/
|
||||
TASK_INIT(&sc->pps_task, 0, dmtpps_event, sc);
|
||||
|
||||
/* Create the PPS cdev. */
|
||||
sc->pps_cdev = make_dev(&dmtpps_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
|
||||
PPS_CDEV_NAME);
|
||||
sc->pps_cdev->si_drv1 = sc;
|
||||
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "Using %s for PPS device /dev/%s\n",
|
||||
sc->tmr_name, PPS_CDEV_NAME);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
dmtpps_detach(device_t dev)
|
||||
{
|
||||
|
||||
/*
|
||||
* There is no way to remove a timecounter once it has been registered,
|
||||
* even if it's not in use, so we can never detach. If we were
|
||||
* dynamically loaded as a module this will prevent unloading.
|
||||
*/
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
static device_method_t dmtpps_methods[] = {
|
||||
DEVMETHOD(device_probe, dmtpps_probe),
|
||||
DEVMETHOD(device_attach, dmtpps_attach),
|
||||
DEVMETHOD(device_detach, dmtpps_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t dmtpps_driver = {
|
||||
"am335x_dmtpps",
|
||||
dmtpps_methods,
|
||||
sizeof(struct dmtpps_softc),
|
||||
};
|
||||
|
||||
static devclass_t dmtpps_devclass;
|
||||
|
||||
DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, dmtpps_devclass, 0, 0);
|
||||
MODULE_DEPEND(am335x_dmtpps, am335x_prcm, 1, 1, 1);
|
||||
|
@ -3,6 +3,7 @@
|
||||
arm/ti/aintc.c standard
|
||||
|
||||
arm/ti/am335x/am335x_dmtimer.c standard
|
||||
arm/ti/am335x/am335x_dmtpps.c optional am335x_dmtpps
|
||||
arm/ti/am335x/am335x_gpio.c optional gpio
|
||||
arm/ti/am335x/am335x_lcd.c optional sc | vt
|
||||
arm/ti/am335x/am335x_lcd_syscons.c optional sc
|
||||
|
@ -244,7 +244,7 @@ sp804_timer_attach(device_t dev)
|
||||
* Timer 1, timecounter
|
||||
*/
|
||||
sc->tc.tc_frequency = sc->sysclk_freq;
|
||||
sc->tc.tc_name = "SP804 Time Counter";
|
||||
sc->tc.tc_name = "SP804-1";
|
||||
sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount;
|
||||
sc->tc.tc_poll_pps = NULL;
|
||||
sc->tc.tc_counter_mask = ~0u;
|
||||
@ -263,9 +263,7 @@ sp804_timer_attach(device_t dev)
|
||||
* Timer 2, event timer
|
||||
*/
|
||||
sc->et_enabled = 0;
|
||||
sc->et.et_name = malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
sprintf(sc->et.et_name, "SP804 Event Timer %d",
|
||||
device_get_unit(dev));
|
||||
sc->et.et_name = "SP804-2";
|
||||
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
|
||||
sc->et.et_quality = 1000;
|
||||
sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR;
|
||||
|
@ -49,6 +49,15 @@ void generic_bs_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
|
||||
void generic_bs_rm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
|
||||
bus_size_t);
|
||||
|
||||
void generic_bs_rr_1(void *, bus_space_handle_t, bus_size_t, uint8_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_rr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
|
||||
bus_size_t);
|
||||
|
||||
void generic_bs_w_1(void *, bus_space_handle_t, bus_size_t, uint8_t);
|
||||
void generic_bs_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t);
|
||||
void generic_bs_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t);
|
||||
@ -63,6 +72,15 @@ void generic_bs_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
|
||||
void generic_bs_wm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
|
||||
bus_size_t);
|
||||
|
||||
void generic_bs_wr_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
|
||||
bus_size_t);
|
||||
void generic_bs_wr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
|
||||
bus_size_t);
|
||||
|
||||
static int
|
||||
generic_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
|
||||
bus_space_handle_t *bshp)
|
||||
@ -126,6 +144,12 @@ struct bus_space memmap_bus = {
|
||||
.bs_rm_4 = generic_bs_rm_4,
|
||||
.bs_rm_8 = generic_bs_rm_8,
|
||||
|
||||
/* read region */
|
||||
.bs_rr_1 = generic_bs_rr_1,
|
||||
.bs_rr_2 = generic_bs_rr_2,
|
||||
.bs_rr_4 = generic_bs_rr_4,
|
||||
.bs_rr_8 = generic_bs_rr_8,
|
||||
|
||||
/* write single */
|
||||
.bs_w_1 = generic_bs_w_1,
|
||||
.bs_w_2 = generic_bs_w_2,
|
||||
@ -139,10 +163,10 @@ struct bus_space memmap_bus = {
|
||||
.bs_wm_8 = generic_bs_wm_8,
|
||||
|
||||
/* write region */
|
||||
.bs_wr_1 = NULL,
|
||||
.bs_wr_2 = NULL,
|
||||
.bs_wr_4 = NULL,
|
||||
.bs_wr_8 = NULL,
|
||||
.bs_wr_1 = generic_bs_wr_1,
|
||||
.bs_wr_2 = generic_bs_wr_2,
|
||||
.bs_wr_4 = generic_bs_wr_4,
|
||||
.bs_wr_8 = generic_bs_wr_8,
|
||||
|
||||
/* set multiple */
|
||||
.bs_sm_1 = NULL,
|
||||
|
@ -133,6 +133,90 @@ ENTRY(generic_bs_rm_8)
|
||||
2: ret
|
||||
END(generic_bs_rm_8)
|
||||
|
||||
ENTRY(generic_bs_rr_1)
|
||||
/* Is there is anything to read. */
|
||||
cbz x4, 2f
|
||||
|
||||
/* Calculate the device address. */
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Read the data. */
|
||||
1: ldrb w1, [x0], #1
|
||||
strb w1, [x3], #1
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_rr_1)
|
||||
|
||||
ENTRY(generic_bs_rr_2)
|
||||
/* Is there is anything to read. */
|
||||
cbz x4, 2f
|
||||
|
||||
/* Calculate the device address. */
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Read the data. */
|
||||
1: ldrh w1, [x0], #2
|
||||
strh w1, [x3], #2
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_rr_2)
|
||||
|
||||
ENTRY(generic_bs_rr_4)
|
||||
/* Is there is anything to read. */
|
||||
cbz x4, 2f
|
||||
|
||||
/* Calculate the device address. */
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Read the data. */
|
||||
1: ldr w1, [x0], #4
|
||||
str w1, [x3], #4
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_rr_4)
|
||||
|
||||
ENTRY(generic_bs_rr_8)
|
||||
/* Is there is anything to read. */
|
||||
cbz x4, 2f
|
||||
|
||||
/* Calculate the device address. */
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Read the data. */
|
||||
1: ldr x1, [x0], #8
|
||||
str x1, [x3], #8
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_rr_8)
|
||||
|
||||
|
||||
ENTRY(generic_bs_w_1)
|
||||
strb w3, [x1, x2]
|
||||
@ -233,3 +317,83 @@ ENTRY(generic_bs_wm_8)
|
||||
|
||||
2: ret
|
||||
END(generic_bs_wm_8)
|
||||
|
||||
ENTRY(generic_bs_wr_1)
|
||||
/* Is there is anything to write. */
|
||||
cbz x4, 2f
|
||||
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Write the data */
|
||||
1: ldrb w1, [x3], #1
|
||||
strb w1, [x0], #1
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_wr_1)
|
||||
|
||||
ENTRY(generic_bs_wr_2)
|
||||
/* Is there is anything to write. */
|
||||
cbz x4, 2f
|
||||
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Write the data */
|
||||
1: ldrh w1, [x3], #2
|
||||
strh w1, [x0], #2
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_wr_2)
|
||||
|
||||
ENTRY(generic_bs_wr_4)
|
||||
/* Is there is anything to write. */
|
||||
cbz x4, 2f
|
||||
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Write the data */
|
||||
1: ldr w1, [x3], #4
|
||||
str w1, [x0], #4
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_wr_4)
|
||||
|
||||
ENTRY(generic_bs_wr_8)
|
||||
/* Is there is anything to write. */
|
||||
cbz x4, 2f
|
||||
|
||||
add x0, x1, x2
|
||||
/*
|
||||
* x0 = The device address.
|
||||
* x3 = The kernel address.
|
||||
* x4 = Count
|
||||
*/
|
||||
|
||||
/* Write the data */
|
||||
1: ldr x1, [x3], #8
|
||||
str x1, [x0], #8
|
||||
subs x4, x4, #1
|
||||
b.ne 1b
|
||||
|
||||
2: ret
|
||||
END(generic_bs_wr_8)
|
||||
|
@ -104,7 +104,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
/* Read the current thread flags */
|
||||
1: ldr x1, [x18, #PC_CURTHREAD] /* Load curthread */
|
||||
ldr x2, [x1, #TD_FLAGS]! /* TODO: No need for the ! but clang fails without it */
|
||||
ldr x2, [x1, #TD_FLAGS]
|
||||
|
||||
/* Check if we have either bits set */
|
||||
mov x3, #((TDF_ASTPENDING|TDF_NEEDRESCHED) >> 8)
|
||||
|
@ -229,6 +229,21 @@ data_abort(struct trapframe *frame, uint64_t esr, int lower)
|
||||
userret(td, frame);
|
||||
}
|
||||
|
||||
static void
|
||||
print_registers(struct trapframe *frame)
|
||||
{
|
||||
u_int reg;
|
||||
|
||||
for (reg = 0; reg < 31; reg++) {
|
||||
printf(" %sx%d: %16lx\n", (reg < 10) ? " " : "", reg,
|
||||
frame->tf_x[reg]);
|
||||
}
|
||||
printf(" sp: %16lx\n", frame->tf_sp);
|
||||
printf(" lr: %16lx\n", frame->tf_lr);
|
||||
printf(" elr: %16lx\n", frame->tf_elr);
|
||||
printf("spsr: %16lx\n", frame->tf_spsr);
|
||||
}
|
||||
|
||||
void
|
||||
do_el1h_sync(struct trapframe *frame)
|
||||
{
|
||||
@ -265,6 +280,7 @@ do_el1h_sync(struct trapframe *frame)
|
||||
switch(exception) {
|
||||
case EXCP_FP_SIMD:
|
||||
case EXCP_TRAP_FP:
|
||||
print_registers(frame);
|
||||
panic("VFP exception in the kernel");
|
||||
case EXCP_DATA_ABORT:
|
||||
data_abort(frame, esr, 0);
|
||||
@ -286,11 +302,30 @@ do_el1h_sync(struct trapframe *frame)
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
print_registers(frame);
|
||||
panic("Unknown kernel exception %x esr_el1 %lx\n", exception,
|
||||
esr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We get EXCP_UNKNOWN from QEMU when executing zeroed memory. For now turn
|
||||
* this into a SIGILL.
|
||||
*/
|
||||
static void
|
||||
el0_excp_unknown(struct trapframe *frame)
|
||||
{
|
||||
struct thread *td;
|
||||
uint64_t far;
|
||||
|
||||
td = curthread;
|
||||
far = READ_SPECIALREG(far_el1);
|
||||
printf("el0 EXCP_UNKNOWN exception\n");
|
||||
print_registers(frame);
|
||||
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)far);
|
||||
userret(td, frame);
|
||||
}
|
||||
|
||||
void
|
||||
do_el0_sync(struct trapframe *frame)
|
||||
{
|
||||
@ -332,7 +367,11 @@ do_el0_sync(struct trapframe *frame)
|
||||
case EXCP_DATA_ABORT:
|
||||
data_abort(frame, esr, 1);
|
||||
break;
|
||||
case EXCP_UNKNOWN:
|
||||
el0_excp_unknown(frame);
|
||||
break;
|
||||
default:
|
||||
print_registers(frame);
|
||||
panic("Unknown userland exception %x esr_el1 %lx\n", exception,
|
||||
esr);
|
||||
}
|
||||
|
@ -43,7 +43,8 @@
|
||||
#define M_USBDEV 0
|
||||
#define USB_PROC_MAX 3
|
||||
#define USB_BUS_GIANT_PROC(bus) (usb_process + 2)
|
||||
#define USB_BUS_NON_GIANT_PROC(bus) (usb_process + 2)
|
||||
#define USB_BUS_NON_GIANT_BULK_PROC(bus) (usb_process + 2)
|
||||
#define USB_BUS_NON_GIANT_ISOC_PROC(bus) (usb_process + 2)
|
||||
#define USB_BUS_EXPLORE_PROC(bus) (usb_process + 0)
|
||||
#define USB_BUS_CONTROL_XFER_PROC(bus) (usb_process + 1)
|
||||
#define SYSCTL_DECL(...)
|
||||
|
@ -69,10 +69,11 @@ fdt_platform_load_dtb(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* If the U-boot environment contains a variable giving the name of a
|
||||
* file, use it if we can load and validate it.
|
||||
* Try to get FDT filename first from loader env and then from u-boot env
|
||||
*/
|
||||
s = ub_env_get("fdtfile");
|
||||
s = getenv("fdt_file");
|
||||
if (s == NULL)
|
||||
s = ub_env_get("fdtfile");
|
||||
if (s == NULL)
|
||||
s = ub_env_get("fdt_file");
|
||||
if (s != NULL && *s != '\0') {
|
||||
|
@ -366,16 +366,6 @@ This is a CTL frontend port that is also a CAM SIM. The idea is that this
|
||||
frontend allows for using CTL without any target-capable hardware. So any
|
||||
LUNs you create in CTL are visible via this port.
|
||||
|
||||
|
||||
ctl_frontend_internal.c
|
||||
ctl_frontend_internal.h:
|
||||
-----------------------
|
||||
|
||||
This is a frontend port written for Copan to do some system-specific tasks
|
||||
that required sending commands into CTL from inside the kernel. This isn't
|
||||
entirely relevant to FreeBSD in general, but can perhaps be repurposed or
|
||||
removed later.
|
||||
|
||||
ctl_ha.h:
|
||||
--------
|
||||
|
||||
|
@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
@ -383,18 +382,7 @@ static int ctl_init(void);
|
||||
void ctl_shutdown(void);
|
||||
static int ctl_open(struct cdev *dev, int flags, int fmt, struct thread *td);
|
||||
static int ctl_close(struct cdev *dev, int flags, int fmt, struct thread *td);
|
||||
static void ctl_ioctl_online(void *arg);
|
||||
static void ctl_ioctl_offline(void *arg);
|
||||
static int ctl_ioctl_lun_enable(void *arg, int lun_id);
|
||||
static int ctl_ioctl_lun_disable(void *arg, int lun_id);
|
||||
static int ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio);
|
||||
static int ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio);
|
||||
static int ctl_ioctl_submit_wait(union ctl_io *io);
|
||||
static void ctl_ioctl_datamove(union ctl_io *io);
|
||||
static void ctl_ioctl_done(union ctl_io *io);
|
||||
static void ctl_ioctl_hard_startstop_callback(void *arg,
|
||||
struct cfi_metatask *metatask);
|
||||
static void ctl_ioctl_bbrread_callback(void *arg,struct cfi_metatask *metatask);
|
||||
static int ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num,
|
||||
struct ctl_ooa *ooa_hdr,
|
||||
struct ctl_ooa_entry *kern_entries);
|
||||
@ -529,11 +517,6 @@ static moduledata_t ctl_moduledata = {
|
||||
DECLARE_MODULE(ctl, ctl_moduledata, SI_SUB_CONFIGURE, SI_ORDER_THIRD);
|
||||
MODULE_VERSION(ctl, 1);
|
||||
|
||||
static struct ctl_frontend ioctl_frontend =
|
||||
{
|
||||
.name = "ioctl",
|
||||
};
|
||||
|
||||
#ifdef notyet
|
||||
static void
|
||||
ctl_isc_handler_finish_xfer(struct ctl_softc *ctl_softc,
|
||||
@ -1064,7 +1047,6 @@ ctl_init(void)
|
||||
{
|
||||
struct ctl_softc *softc;
|
||||
void *other_pool;
|
||||
struct ctl_port *port;
|
||||
int i, error, retval;
|
||||
//int isc_retval;
|
||||
|
||||
@ -1189,32 +1171,6 @@ ctl_init(void)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the ioctl front end.
|
||||
*/
|
||||
ctl_frontend_register(&ioctl_frontend);
|
||||
port = &softc->ioctl_info.port;
|
||||
port->frontend = &ioctl_frontend;
|
||||
sprintf(softc->ioctl_info.port_name, "ioctl");
|
||||
port->port_type = CTL_PORT_IOCTL;
|
||||
port->num_requested_ctl_io = 100;
|
||||
port->port_name = softc->ioctl_info.port_name;
|
||||
port->port_online = ctl_ioctl_online;
|
||||
port->port_offline = ctl_ioctl_offline;
|
||||
port->onoff_arg = &softc->ioctl_info;
|
||||
port->lun_enable = ctl_ioctl_lun_enable;
|
||||
port->lun_disable = ctl_ioctl_lun_disable;
|
||||
port->targ_lun_arg = &softc->ioctl_info;
|
||||
port->fe_datamove = ctl_ioctl_datamove;
|
||||
port->fe_done = ctl_ioctl_done;
|
||||
port->max_targets = 15;
|
||||
port->max_target_id = 15;
|
||||
|
||||
if (ctl_port_register(&softc->ioctl_info.port) != 0) {
|
||||
printf("ctl: ioctl front end registration failed, will "
|
||||
"continue anyway\n");
|
||||
}
|
||||
|
||||
SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
|
||||
OID_AUTO, "ha_state", CTLTYPE_INT | CTLFLAG_RWTUN,
|
||||
softc, 0, ctl_ha_state_sysctl, "I", "HA state for this head");
|
||||
@ -1238,9 +1194,6 @@ ctl_shutdown(void)
|
||||
|
||||
softc = (struct ctl_softc *)control_softc;
|
||||
|
||||
if (ctl_port_deregister(&softc->ioctl_info.port) != 0)
|
||||
printf("ctl: ioctl front end deregistration failed\n");
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
|
||||
/*
|
||||
@ -1253,8 +1206,6 @@ ctl_shutdown(void)
|
||||
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
|
||||
ctl_frontend_deregister(&ioctl_frontend);
|
||||
|
||||
#if 0
|
||||
ctl_shutdown_thread(softc->work_thread);
|
||||
mtx_destroy(&softc->queue_lock);
|
||||
@ -1426,26 +1377,6 @@ ctl_port_list(struct ctl_port_entry *entries, int num_entries_alloced,
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_online(void *arg)
|
||||
{
|
||||
struct ctl_ioctl_info *ioctl_info;
|
||||
|
||||
ioctl_info = (struct ctl_ioctl_info *)arg;
|
||||
|
||||
ioctl_info->flags |= CTL_IOCTL_FLAG_ENABLED;
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_offline(void *arg)
|
||||
{
|
||||
struct ctl_ioctl_info *ioctl_info;
|
||||
|
||||
ioctl_info = (struct ctl_ioctl_info *)arg;
|
||||
|
||||
ioctl_info->flags &= ~CTL_IOCTL_FLAG_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an initiator by port number and initiator ID.
|
||||
* Returns 0 for success, -1 for failure.
|
||||
@ -1641,181 +1572,6 @@ ctl_create_iid(struct ctl_port *port, int iid, uint8_t *buf)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_ioctl_lun_enable(void *arg, int lun_id)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_ioctl_lun_disable(void *arg, int lun_id)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Data movement routine for the CTL ioctl frontend port.
|
||||
*/
|
||||
static int
|
||||
ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio)
|
||||
{
|
||||
struct ctl_sg_entry *ext_sglist, *kern_sglist;
|
||||
struct ctl_sg_entry ext_entry, kern_entry;
|
||||
int ext_sglen, ext_sg_entries, kern_sg_entries;
|
||||
int ext_sg_start, ext_offset;
|
||||
int len_to_copy, len_copied;
|
||||
int kern_watermark, ext_watermark;
|
||||
int ext_sglist_malloced;
|
||||
int i, j;
|
||||
|
||||
ext_sglist_malloced = 0;
|
||||
ext_sg_start = 0;
|
||||
ext_offset = 0;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove\n"));
|
||||
|
||||
/*
|
||||
* If this flag is set, fake the data transfer.
|
||||
*/
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_NO_DATAMOVE) {
|
||||
ctsio->ext_data_filled = ctsio->ext_data_len;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
/*
|
||||
* To simplify things here, if we have a single buffer, stick it in
|
||||
* a S/G entry and just make it a single entry S/G list.
|
||||
*/
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_EDPTR_SGLIST) {
|
||||
int len_seen;
|
||||
|
||||
ext_sglen = ctsio->ext_sg_entries * sizeof(*ext_sglist);
|
||||
|
||||
ext_sglist = (struct ctl_sg_entry *)malloc(ext_sglen, M_CTL,
|
||||
M_WAITOK);
|
||||
ext_sglist_malloced = 1;
|
||||
if (copyin(ctsio->ext_data_ptr, ext_sglist,
|
||||
ext_sglen) != 0) {
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/ 0);
|
||||
goto bailout;
|
||||
}
|
||||
ext_sg_entries = ctsio->ext_sg_entries;
|
||||
len_seen = 0;
|
||||
for (i = 0; i < ext_sg_entries; i++) {
|
||||
if ((len_seen + ext_sglist[i].len) >=
|
||||
ctsio->ext_data_filled) {
|
||||
ext_sg_start = i;
|
||||
ext_offset = ctsio->ext_data_filled - len_seen;
|
||||
break;
|
||||
}
|
||||
len_seen += ext_sglist[i].len;
|
||||
}
|
||||
} else {
|
||||
ext_sglist = &ext_entry;
|
||||
ext_sglist->addr = ctsio->ext_data_ptr;
|
||||
ext_sglist->len = ctsio->ext_data_len;
|
||||
ext_sg_entries = 1;
|
||||
ext_sg_start = 0;
|
||||
ext_offset = ctsio->ext_data_filled;
|
||||
}
|
||||
|
||||
if (ctsio->kern_sg_entries > 0) {
|
||||
kern_sglist = (struct ctl_sg_entry *)ctsio->kern_data_ptr;
|
||||
kern_sg_entries = ctsio->kern_sg_entries;
|
||||
} else {
|
||||
kern_sglist = &kern_entry;
|
||||
kern_sglist->addr = ctsio->kern_data_ptr;
|
||||
kern_sglist->len = ctsio->kern_data_len;
|
||||
kern_sg_entries = 1;
|
||||
}
|
||||
|
||||
|
||||
kern_watermark = 0;
|
||||
ext_watermark = ext_offset;
|
||||
len_copied = 0;
|
||||
for (i = ext_sg_start, j = 0;
|
||||
i < ext_sg_entries && j < kern_sg_entries;) {
|
||||
uint8_t *ext_ptr, *kern_ptr;
|
||||
|
||||
len_to_copy = MIN(ext_sglist[i].len - ext_watermark,
|
||||
kern_sglist[j].len - kern_watermark);
|
||||
|
||||
ext_ptr = (uint8_t *)ext_sglist[i].addr;
|
||||
ext_ptr = ext_ptr + ext_watermark;
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_BUS_ADDR) {
|
||||
/*
|
||||
* XXX KDM fix this!
|
||||
*/
|
||||
panic("need to implement bus address support");
|
||||
#if 0
|
||||
kern_ptr = bus_to_virt(kern_sglist[j].addr);
|
||||
#endif
|
||||
} else
|
||||
kern_ptr = (uint8_t *)kern_sglist[j].addr;
|
||||
kern_ptr = kern_ptr + kern_watermark;
|
||||
|
||||
kern_watermark += len_to_copy;
|
||||
ext_watermark += len_to_copy;
|
||||
|
||||
if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
|
||||
CTL_FLAG_DATA_IN) {
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: copying %d "
|
||||
"bytes to user\n", len_to_copy));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: from %p "
|
||||
"to %p\n", kern_ptr, ext_ptr));
|
||||
if (copyout(kern_ptr, ext_ptr, len_to_copy) != 0) {
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/ 0);
|
||||
goto bailout;
|
||||
}
|
||||
} else {
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: copying %d "
|
||||
"bytes from user\n", len_to_copy));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: from %p "
|
||||
"to %p\n", ext_ptr, kern_ptr));
|
||||
if (copyin(ext_ptr, kern_ptr, len_to_copy)!= 0){
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/0);
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
|
||||
len_copied += len_to_copy;
|
||||
|
||||
if (ext_sglist[i].len == ext_watermark) {
|
||||
i++;
|
||||
ext_watermark = 0;
|
||||
}
|
||||
|
||||
if (kern_sglist[j].len == kern_watermark) {
|
||||
j++;
|
||||
kern_watermark = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctsio->ext_data_filled += len_copied;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: ext_sg_entries: %d, "
|
||||
"kern_sg_entries: %d\n", ext_sg_entries,
|
||||
kern_sg_entries));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: ext_data_len = %d, "
|
||||
"kern_data_len = %d\n", ctsio->ext_data_len,
|
||||
ctsio->kern_data_len));
|
||||
|
||||
|
||||
/* XXX KDM set residual?? */
|
||||
bailout:
|
||||
|
||||
if (ext_sglist_malloced != 0)
|
||||
free(ext_sglist, M_CTL);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a command that went down the "wrong" side, and so was sent to
|
||||
* this controller for execution. The logic is a little different than the
|
||||
@ -1982,149 +1738,6 @@ ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_ioctl_submit_wait(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params params;
|
||||
ctl_fe_ioctl_state last_state;
|
||||
int done, retval;
|
||||
|
||||
retval = 0;
|
||||
|
||||
bzero(¶ms, sizeof(params));
|
||||
|
||||
mtx_init(¶ms.ioctl_mtx, "ctliocmtx", NULL, MTX_DEF);
|
||||
cv_init(¶ms.sem, "ctlioccv");
|
||||
params.state = CTL_IOCTL_INPROG;
|
||||
last_state = params.state;
|
||||
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ¶ms;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_submit_wait\n"));
|
||||
|
||||
/* This shouldn't happen */
|
||||
if ((retval = ctl_queue(io)) != CTL_RETVAL_COMPLETE)
|
||||
return (retval);
|
||||
|
||||
done = 0;
|
||||
|
||||
do {
|
||||
mtx_lock(¶ms.ioctl_mtx);
|
||||
/*
|
||||
* Check the state here, and don't sleep if the state has
|
||||
* already changed (i.e. wakeup has already occured, but we
|
||||
* weren't waiting yet).
|
||||
*/
|
||||
if (params.state == last_state) {
|
||||
/* XXX KDM cv_wait_sig instead? */
|
||||
cv_wait(¶ms.sem, ¶ms.ioctl_mtx);
|
||||
}
|
||||
last_state = params.state;
|
||||
|
||||
switch (params.state) {
|
||||
case CTL_IOCTL_INPROG:
|
||||
/* Why did we wake up? */
|
||||
/* XXX KDM error here? */
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
break;
|
||||
case CTL_IOCTL_DATAMOVE:
|
||||
CTL_DEBUG_PRINT(("got CTL_IOCTL_DATAMOVE\n"));
|
||||
|
||||
/*
|
||||
* change last_state back to INPROG to avoid
|
||||
* deadlock on subsequent data moves.
|
||||
*/
|
||||
params.state = last_state = CTL_IOCTL_INPROG;
|
||||
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
ctl_ioctl_do_datamove(&io->scsiio);
|
||||
/*
|
||||
* Note that in some cases, most notably writes,
|
||||
* this will queue the I/O and call us back later.
|
||||
* In other cases, generally reads, this routine
|
||||
* will immediately call back and wake us up,
|
||||
* probably using our own context.
|
||||
*/
|
||||
io->scsiio.be_move_done(io);
|
||||
break;
|
||||
case CTL_IOCTL_DONE:
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
CTL_DEBUG_PRINT(("got CTL_IOCTL_DONE\n"));
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
/* XXX KDM error here? */
|
||||
break;
|
||||
}
|
||||
} while (done == 0);
|
||||
|
||||
mtx_destroy(¶ms.ioctl_mtx);
|
||||
cv_destroy(¶ms.sem);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_datamove(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params *params;
|
||||
|
||||
params = (struct ctl_fe_ioctl_params *)
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
|
||||
|
||||
mtx_lock(¶ms->ioctl_mtx);
|
||||
params->state = CTL_IOCTL_DATAMOVE;
|
||||
cv_broadcast(¶ms->sem);
|
||||
mtx_unlock(¶ms->ioctl_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_done(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params *params;
|
||||
|
||||
params = (struct ctl_fe_ioctl_params *)
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
|
||||
|
||||
mtx_lock(¶ms->ioctl_mtx);
|
||||
params->state = CTL_IOCTL_DONE;
|
||||
cv_broadcast(¶ms->sem);
|
||||
mtx_unlock(¶ms->ioctl_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_hard_startstop_callback(void *arg, struct cfi_metatask *metatask)
|
||||
{
|
||||
struct ctl_fe_ioctl_startstop_info *sd_info;
|
||||
|
||||
sd_info = (struct ctl_fe_ioctl_startstop_info *)arg;
|
||||
|
||||
sd_info->hs_info.status = metatask->status;
|
||||
sd_info->hs_info.total_luns = metatask->taskinfo.startstop.total_luns;
|
||||
sd_info->hs_info.luns_complete =
|
||||
metatask->taskinfo.startstop.luns_complete;
|
||||
sd_info->hs_info.luns_failed = metatask->taskinfo.startstop.luns_failed;
|
||||
|
||||
cv_broadcast(&sd_info->sem);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_ioctl_bbrread_callback(void *arg, struct cfi_metatask *metatask)
|
||||
{
|
||||
struct ctl_fe_ioctl_bbrread_info *fe_bbr_info;
|
||||
|
||||
fe_bbr_info = (struct ctl_fe_ioctl_bbrread_info *)arg;
|
||||
|
||||
mtx_lock(fe_bbr_info->lock);
|
||||
fe_bbr_info->bbr_info->status = metatask->status;
|
||||
fe_bbr_info->bbr_info->bbr_status = metatask->taskinfo.bbrread.status;
|
||||
fe_bbr_info->wakeup_done = 1;
|
||||
mtx_unlock(fe_bbr_info->lock);
|
||||
|
||||
cv_broadcast(&fe_bbr_info->sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 for success, errno for failure.
|
||||
*/
|
||||
@ -2367,57 +1980,9 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
retval = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case CTL_IO: {
|
||||
union ctl_io *io;
|
||||
void *pool_tmp;
|
||||
|
||||
/*
|
||||
* If we haven't been "enabled", don't allow any SCSI I/O
|
||||
* to this FETD.
|
||||
*/
|
||||
if ((softc->ioctl_info.flags & CTL_IOCTL_FLAG_ENABLED) == 0) {
|
||||
retval = EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
io = ctl_alloc_io(softc->ioctl_info.port.ctl_pool_ref);
|
||||
|
||||
/*
|
||||
* Need to save the pool reference so it doesn't get
|
||||
* spammed by the user's ctl_io.
|
||||
*/
|
||||
pool_tmp = io->io_hdr.pool;
|
||||
memcpy(io, (void *)addr, sizeof(*io));
|
||||
io->io_hdr.pool = pool_tmp;
|
||||
|
||||
/*
|
||||
* No status yet, so make sure the status is set properly.
|
||||
*/
|
||||
io->io_hdr.status = CTL_STATUS_NONE;
|
||||
|
||||
/*
|
||||
* The user sets the initiator ID, target and LUN IDs.
|
||||
*/
|
||||
io->io_hdr.nexus.targ_port = softc->ioctl_info.port.targ_port;
|
||||
io->io_hdr.flags |= CTL_FLAG_USER_REQ;
|
||||
if ((io->io_hdr.io_type == CTL_IO_SCSI)
|
||||
&& (io->scsiio.tag_type != CTL_TAG_UNTAGGED))
|
||||
io->scsiio.tag_num = softc->ioctl_info.cur_tag_num++;
|
||||
|
||||
retval = ctl_ioctl_submit_wait(io);
|
||||
|
||||
if (retval != 0) {
|
||||
ctl_free_io(io);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy((void *)addr, io, sizeof(*io));
|
||||
|
||||
/* return this to our pool */
|
||||
ctl_free_io(io);
|
||||
|
||||
case CTL_IO:
|
||||
retval = ctl_ioctl_io(dev, cmd, addr, flag, td);
|
||||
break;
|
||||
}
|
||||
case CTL_ENABLE_PORT:
|
||||
case CTL_DISABLE_PORT:
|
||||
case CTL_SET_PORT_WWNS: {
|
||||
@ -2724,103 +2289,6 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
|
||||
break;
|
||||
}
|
||||
case CTL_HARD_START:
|
||||
case CTL_HARD_STOP: {
|
||||
struct ctl_fe_ioctl_startstop_info ss_info;
|
||||
struct cfi_metatask *metatask;
|
||||
struct mtx hs_mtx;
|
||||
|
||||
mtx_init(&hs_mtx, "HS Mutex", NULL, MTX_DEF);
|
||||
|
||||
cv_init(&ss_info.sem, "hard start/stop cv" );
|
||||
|
||||
metatask = cfi_alloc_metatask(/*can_wait*/ 1);
|
||||
if (metatask == NULL) {
|
||||
retval = ENOMEM;
|
||||
mtx_destroy(&hs_mtx);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == CTL_HARD_START)
|
||||
metatask->tasktype = CFI_TASK_STARTUP;
|
||||
else
|
||||
metatask->tasktype = CFI_TASK_SHUTDOWN;
|
||||
|
||||
metatask->callback = ctl_ioctl_hard_startstop_callback;
|
||||
metatask->callback_arg = &ss_info;
|
||||
|
||||
cfi_action(metatask);
|
||||
|
||||
/* Wait for the callback */
|
||||
mtx_lock(&hs_mtx);
|
||||
cv_wait_sig(&ss_info.sem, &hs_mtx);
|
||||
mtx_unlock(&hs_mtx);
|
||||
|
||||
/*
|
||||
* All information has been copied from the metatask by the
|
||||
* time cv_broadcast() is called, so we free the metatask here.
|
||||
*/
|
||||
cfi_free_metatask(metatask);
|
||||
|
||||
memcpy((void *)addr, &ss_info.hs_info, sizeof(ss_info.hs_info));
|
||||
|
||||
mtx_destroy(&hs_mtx);
|
||||
break;
|
||||
}
|
||||
case CTL_BBRREAD: {
|
||||
struct ctl_bbrread_info *bbr_info;
|
||||
struct ctl_fe_ioctl_bbrread_info fe_bbr_info;
|
||||
struct mtx bbr_mtx;
|
||||
struct cfi_metatask *metatask;
|
||||
|
||||
bbr_info = (struct ctl_bbrread_info *)addr;
|
||||
|
||||
bzero(&fe_bbr_info, sizeof(fe_bbr_info));
|
||||
|
||||
bzero(&bbr_mtx, sizeof(bbr_mtx));
|
||||
mtx_init(&bbr_mtx, "BBR Mutex", NULL, MTX_DEF);
|
||||
|
||||
fe_bbr_info.bbr_info = bbr_info;
|
||||
fe_bbr_info.lock = &bbr_mtx;
|
||||
|
||||
cv_init(&fe_bbr_info.sem, "BBR read cv");
|
||||
metatask = cfi_alloc_metatask(/*can_wait*/ 1);
|
||||
|
||||
if (metatask == NULL) {
|
||||
mtx_destroy(&bbr_mtx);
|
||||
cv_destroy(&fe_bbr_info.sem);
|
||||
retval = ENOMEM;
|
||||
break;
|
||||
}
|
||||
metatask->tasktype = CFI_TASK_BBRREAD;
|
||||
metatask->callback = ctl_ioctl_bbrread_callback;
|
||||
metatask->callback_arg = &fe_bbr_info;
|
||||
metatask->taskinfo.bbrread.lun_num = bbr_info->lun_num;
|
||||
metatask->taskinfo.bbrread.lba = bbr_info->lba;
|
||||
metatask->taskinfo.bbrread.len = bbr_info->len;
|
||||
|
||||
cfi_action(metatask);
|
||||
|
||||
mtx_lock(&bbr_mtx);
|
||||
while (fe_bbr_info.wakeup_done == 0)
|
||||
cv_wait_sig(&fe_bbr_info.sem, &bbr_mtx);
|
||||
mtx_unlock(&bbr_mtx);
|
||||
|
||||
bbr_info->status = metatask->status;
|
||||
bbr_info->bbr_status = metatask->taskinfo.bbrread.status;
|
||||
bbr_info->scsi_status = metatask->taskinfo.bbrread.scsi_status;
|
||||
memcpy(&bbr_info->sense_data,
|
||||
&metatask->taskinfo.bbrread.sense_data,
|
||||
MIN(sizeof(bbr_info->sense_data),
|
||||
sizeof(metatask->taskinfo.bbrread.sense_data)));
|
||||
|
||||
cfi_free_metatask(metatask);
|
||||
|
||||
mtx_destroy(&bbr_mtx);
|
||||
cv_destroy(&fe_bbr_info.sem);
|
||||
|
||||
break;
|
||||
}
|
||||
case CTL_DELAY_IO: {
|
||||
struct ctl_io_delay_info *delay_info;
|
||||
#ifdef CTL_IO_DELAY
|
||||
|
@ -194,6 +194,8 @@ void ctl_portDB_changed(int portnum);
|
||||
#ifdef notyet
|
||||
void ctl_init_isc_msg(void);
|
||||
#endif
|
||||
int ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct thread *td);
|
||||
|
||||
/*
|
||||
* KPI to manipulate LUN/port options
|
||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_ha.h>
|
||||
#include <cam/ctl/ctl_private.h>
|
||||
|
@ -84,7 +84,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_scsi_all.h>
|
||||
#include <cam/ctl/ctl_error.h>
|
||||
@ -170,7 +169,6 @@ struct ctl_be_block_lun {
|
||||
uint64_t size_blocks;
|
||||
uint64_t size_bytes;
|
||||
uint32_t blocksize;
|
||||
int blocksize_shift;
|
||||
uint16_t pblockexp;
|
||||
uint16_t pblockoff;
|
||||
uint16_t ublockexp;
|
||||
@ -773,7 +771,7 @@ ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
|
||||
|
||||
DPRINTF("entered\n");
|
||||
|
||||
off = roff = ((off_t)lbalen->lba) << be_lun->blocksize_shift;
|
||||
off = roff = ((off_t)lbalen->lba) * be_lun->blocksize;
|
||||
vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
|
||||
error = VOP_IOCTL(be_lun->vn, FIOSEEKHOLE, &off,
|
||||
0, curthread->td_ucred, curthread);
|
||||
@ -791,10 +789,9 @@ ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
|
||||
}
|
||||
VOP_UNLOCK(be_lun->vn, 0);
|
||||
|
||||
off >>= be_lun->blocksize_shift;
|
||||
data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
|
||||
scsi_u64to8b(lbalen->lba, data->descr[0].addr);
|
||||
scsi_ulto4b(MIN(UINT32_MAX, off - lbalen->lba),
|
||||
scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->blocksize - lbalen->lba),
|
||||
data->descr[0].length);
|
||||
data->descr[0].status = status;
|
||||
|
||||
@ -816,14 +813,14 @@ ctl_be_block_getattr_file(struct ctl_be_block_lun *be_lun, const char *attrname)
|
||||
if (strcmp(attrname, "blocksused") == 0) {
|
||||
error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
|
||||
if (error == 0)
|
||||
val = vattr.va_bytes >> be_lun->blocksize_shift;
|
||||
val = vattr.va_bytes / be_lun->blocksize;
|
||||
}
|
||||
if (strcmp(attrname, "blocksavail") == 0 &&
|
||||
(be_lun->vn->v_iflag & VI_DOOMED) == 0) {
|
||||
error = VFS_STATFS(be_lun->vn->v_mount, &statfs);
|
||||
if (error == 0)
|
||||
val = (statfs.f_bavail * statfs.f_bsize) >>
|
||||
be_lun->blocksize_shift;
|
||||
val = statfs.f_bavail * statfs.f_bsize /
|
||||
be_lun->blocksize;
|
||||
}
|
||||
VOP_UNLOCK(be_lun->vn, 0);
|
||||
return (val);
|
||||
@ -934,7 +931,7 @@ ctl_be_block_gls_zvol(struct ctl_be_block_lun *be_lun,
|
||||
|
||||
DPRINTF("entered\n");
|
||||
|
||||
off = roff = ((off_t)lbalen->lba) << be_lun->blocksize_shift;
|
||||
off = roff = ((off_t)lbalen->lba) * be_lun->blocksize;
|
||||
error = (*dev_data->csw->d_ioctl)(dev_data->cdev, FIOSEEKHOLE,
|
||||
(caddr_t)&off, FREAD, curthread);
|
||||
if (error == 0 && off > roff)
|
||||
@ -950,10 +947,9 @@ ctl_be_block_gls_zvol(struct ctl_be_block_lun *be_lun,
|
||||
}
|
||||
}
|
||||
|
||||
off >>= be_lun->blocksize_shift;
|
||||
data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
|
||||
scsi_u64to8b(lbalen->lba, data->descr[0].addr);
|
||||
scsi_ulto4b(MIN(UINT32_MAX, off - lbalen->lba),
|
||||
scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->blocksize - lbalen->lba),
|
||||
data->descr[0].length);
|
||||
data->descr[0].status = status;
|
||||
|
||||
@ -1866,7 +1862,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
struct cdevsw *devsw;
|
||||
char *value;
|
||||
int error, atomic, maxio, unmap;
|
||||
off_t ps, pss, po, pos, us, uss, uo, uos;
|
||||
off_t ps, pss, po, pos, us, uss, uo, uos, tmp;
|
||||
|
||||
params = &be_lun->params;
|
||||
|
||||
@ -1909,8 +1905,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
error = devsw->d_ioctl(dev, DIOCGSECTORSIZE,
|
||||
(caddr_t)&be_lun->blocksize, FREAD,
|
||||
error = devsw->d_ioctl(dev, DIOCGSECTORSIZE, (caddr_t)&tmp, FREAD,
|
||||
curthread);
|
||||
if (error) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
@ -1925,15 +1920,9 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
* the user is asking for is an even multiple of the underlying
|
||||
* device's blocksize.
|
||||
*/
|
||||
if ((params->blocksize_bytes != 0)
|
||||
&& (params->blocksize_bytes > be_lun->blocksize)) {
|
||||
uint32_t bs_multiple, tmp_blocksize;
|
||||
|
||||
bs_multiple = params->blocksize_bytes / be_lun->blocksize;
|
||||
|
||||
tmp_blocksize = bs_multiple * be_lun->blocksize;
|
||||
|
||||
if (tmp_blocksize == params->blocksize_bytes) {
|
||||
if ((params->blocksize_bytes != 0) &&
|
||||
(params->blocksize_bytes >= tmp)) {
|
||||
if (params->blocksize_bytes % tmp == 0) {
|
||||
be_lun->blocksize = params->blocksize_bytes;
|
||||
} else {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
@ -1944,17 +1933,16 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
return (EINVAL);
|
||||
|
||||
}
|
||||
} else if ((params->blocksize_bytes != 0)
|
||||
&& (params->blocksize_bytes != be_lun->blocksize)) {
|
||||
} else if (params->blocksize_bytes != 0) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"requested blocksize %u < backing device "
|
||||
"blocksize %u", params->blocksize_bytes,
|
||||
be_lun->blocksize);
|
||||
return (EINVAL);
|
||||
}
|
||||
} else
|
||||
be_lun->blocksize = tmp;
|
||||
|
||||
error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
|
||||
(caddr_t)&be_lun->size_bytes, FREAD,
|
||||
error = devsw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&tmp, FREAD,
|
||||
curthread);
|
||||
if (error) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
@ -1965,7 +1953,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
}
|
||||
|
||||
if (params->lun_size_bytes != 0) {
|
||||
if (params->lun_size_bytes > be_lun->size_bytes) {
|
||||
if (params->lun_size_bytes > tmp) {
|
||||
snprintf(req->error_str, sizeof(req->error_str),
|
||||
"requested LUN size %ju > backing device "
|
||||
"size %ju",
|
||||
@ -1975,7 +1963,8 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
|
||||
}
|
||||
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
}
|
||||
} else
|
||||
be_lun->size_bytes = tmp;
|
||||
|
||||
error = devsw->d_ioctl(dev, DIOCGSTRIPESIZE,
|
||||
(caddr_t)&ps, FREAD, curthread);
|
||||
@ -2160,14 +2149,8 @@ ctl_be_block_open(struct ctl_be_block_softc *softc,
|
||||
}
|
||||
VOP_UNLOCK(be_lun->vn, 0);
|
||||
|
||||
if (error != 0) {
|
||||
if (error != 0)
|
||||
ctl_be_block_close(be_lun);
|
||||
return (error);
|
||||
}
|
||||
|
||||
be_lun->blocksize_shift = fls(be_lun->blocksize) - 1;
|
||||
be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2224,10 +2207,14 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
goto bailout_error;
|
||||
}
|
||||
be_lun->dev_path = strdup(value, M_CTLBLK);
|
||||
be_lun->blocksize = 512;
|
||||
be_lun->blocksize_shift = fls(be_lun->blocksize) - 1;
|
||||
be_lun->size_bytes = params->lun_size_bytes;
|
||||
if (params->blocksize_bytes != 0)
|
||||
be_lun->blocksize = params->blocksize_bytes;
|
||||
else
|
||||
be_lun->blocksize = 512;
|
||||
|
||||
retval = ctl_be_block_open(softc, be_lun, req);
|
||||
be_lun->size_blocks = be_lun->size_bytes / be_lun->blocksize;
|
||||
if (retval != 0) {
|
||||
retval = 0;
|
||||
req->status = CTL_LUN_WARNING;
|
||||
@ -2652,10 +2639,9 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
error = ctl_be_block_modify_file(be_lun, req);
|
||||
else
|
||||
error = EINVAL;
|
||||
be_lun->size_blocks = be_lun->size_bytes / be_lun->blocksize;
|
||||
|
||||
if (error == 0 && be_lun->size_bytes != oldsize) {
|
||||
be_lun->size_blocks = be_lun->size_bytes >>
|
||||
be_lun->blocksize_shift;
|
||||
|
||||
/*
|
||||
* The maximum LBA is the size - 1.
|
||||
|
@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_debug.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_error.h>
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_ha.h>
|
||||
#include <cam/ctl/ctl_private.h>
|
||||
|
@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_error.h>
|
||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
/* XXX KDM move defines from ctl_ioctl.h to somewhere else */
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
|
@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_debug.h>
|
||||
|
||||
#define io_ptr spriv_ptr1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,154 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Silicon Graphics International Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* 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 MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend_internal.h#1 $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* CTL kernel internal frontend target driver. This allows kernel-level
|
||||
* clients to send commands into CTL.
|
||||
*
|
||||
* Author: Ken Merry <ken@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#ifndef _CTL_FRONTEND_INTERNAL_H_
|
||||
#define _CTL_FRONTEND_INTERNAL_H_
|
||||
|
||||
/*
|
||||
* These are general metatask error codes. If the error code is CFI_MT_ERROR,
|
||||
* check any metatask-specific status codes for more detail on the problem.
|
||||
*/
|
||||
typedef enum {
|
||||
CFI_MT_NONE,
|
||||
CFI_MT_PORT_OFFLINE,
|
||||
CFI_MT_ERROR,
|
||||
CFI_MT_SUCCESS
|
||||
} cfi_mt_status;
|
||||
|
||||
typedef enum {
|
||||
CFI_TASK_NONE,
|
||||
CFI_TASK_SHUTDOWN,
|
||||
CFI_TASK_STARTUP,
|
||||
CFI_TASK_BBRREAD
|
||||
} cfi_tasktype;
|
||||
|
||||
struct cfi_task_startstop {
|
||||
int total_luns;
|
||||
int luns_complete;
|
||||
int luns_failed;
|
||||
};
|
||||
|
||||
/*
|
||||
* Error code description:
|
||||
* CFI_BBR_SUCCESS - the read was successful
|
||||
* CFI_BBR_LUN_UNCONFIG - CFI probe for this lun hasn't completed
|
||||
* CFI_BBR_NO_LUN - this lun doesn't exist, as far as CFI knows
|
||||
* CFI_BBR_NO_MEM - memory allocation error
|
||||
* CFI_BBR_BAD_LEN - data length isn't a multiple of the blocksize
|
||||
* CFI_BBR_RESERV_CONFLICT - another initiator has this lun reserved, so
|
||||
* we can't issue I/O at all.
|
||||
* CFI_BBR_LUN_STOPPED - the lun is powered off.
|
||||
* CFI_BBR_LUN_OFFLINE_CTL - the lun is offline from a CTL standpoint
|
||||
* CFI_BBR_LUN_OFFLINE_RC - the lun is offline from a RAIDCore standpoint.
|
||||
* This is bad, because it basically means we've
|
||||
* had a double failure on the LUN.
|
||||
* CFI_BBR_SCSI_ERROR - generic SCSI error, see status byte and sense
|
||||
* data for more resolution if you want it.
|
||||
* CFI_BBR_ERROR - the catch-all error code.
|
||||
*/
|
||||
typedef enum {
|
||||
CFI_BBR_SUCCESS,
|
||||
CFI_BBR_LUN_UNCONFIG,
|
||||
CFI_BBR_NO_LUN,
|
||||
CFI_BBR_NO_MEM,
|
||||
CFI_BBR_BAD_LEN,
|
||||
CFI_BBR_RESERV_CONFLICT,
|
||||
CFI_BBR_LUN_STOPPED,
|
||||
CFI_BBR_LUN_OFFLINE_CTL,
|
||||
CFI_BBR_LUN_OFFLINE_RC,
|
||||
CFI_BBR_SCSI_ERROR,
|
||||
CFI_BBR_ERROR,
|
||||
} cfi_bbrread_status;
|
||||
|
||||
struct cfi_task_bbrread {
|
||||
int lun_num; /* lun number */
|
||||
uint64_t lba; /* logical block address */
|
||||
int len; /* length in bytes */
|
||||
cfi_bbrread_status status; /* BBR status */
|
||||
uint8_t scsi_status; /* SCSI status */
|
||||
struct scsi_sense_data sense_data; /* SCSI sense data */
|
||||
};
|
||||
|
||||
union cfi_taskinfo {
|
||||
struct cfi_task_startstop startstop;
|
||||
struct cfi_task_bbrread bbrread;
|
||||
};
|
||||
|
||||
struct cfi_metatask;
|
||||
|
||||
typedef void (*cfi_cb_t)(void *arg, struct cfi_metatask *metatask);
|
||||
|
||||
struct cfi_metatask {
|
||||
cfi_tasktype tasktype; /* passed to CFI */
|
||||
cfi_mt_status status; /* returned from CFI */
|
||||
union cfi_taskinfo taskinfo; /* returned from CFI */
|
||||
struct ctl_mem_element *element; /* used by CFI, don't touch*/
|
||||
cfi_cb_t callback; /* passed to CFI */
|
||||
void *callback_arg; /* passed to CFI */
|
||||
STAILQ_ENTRY(cfi_metatask) links; /* used by CFI, don't touch*/
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
MALLOC_DECLARE(M_CTL_CFI);
|
||||
|
||||
/*
|
||||
* This is the API for sending meta commands (commands that are sent to more
|
||||
* than one LUN) to the internal frontend:
|
||||
* - Allocate a metatask using cfi_alloc_metatask(). can_wait == 0 means
|
||||
* that you're calling from an interrupt context. can_wait == 1 means
|
||||
* that you're calling from a thread context and don't mind waiting to
|
||||
* allocate memory.
|
||||
* - Setup the task type, callback and callback argument.
|
||||
* - Call cfi_action().
|
||||
* - When the callback comes, note the status and any per-command status
|
||||
* (see the taskinfo union) and then free the metatask with
|
||||
* cfi_free_metatask().
|
||||
*/
|
||||
struct cfi_metatask *cfi_alloc_metatask(int can_wait);
|
||||
void cfi_free_metatask(struct cfi_metatask *metatask);
|
||||
void cfi_action(struct cfi_metatask *metatask);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _CTL_FRONTEND_INTERNAL_H_ */
|
||||
|
||||
/*
|
||||
* vim: ts=8
|
||||
*/
|
470
sys/cam/ctl/ctl_frontend_ioctl.c
Normal file
470
sys/cam/ctl/ctl_frontend_ioctl.c
Normal file
@ -0,0 +1,470 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2009 Silicon Graphics International Corp.
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* Copyright (c) 2015 Alexander Motin <mav@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_da.h>
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
#include <cam/ctl/ctl_ha.h>
|
||||
#include <cam/ctl/ctl_private.h>
|
||||
#include <cam/ctl/ctl_debug.h>
|
||||
#include <cam/ctl/ctl_error.h>
|
||||
|
||||
struct cfi_softc {
|
||||
uint32_t cur_tag_num;
|
||||
struct ctl_port port;
|
||||
};
|
||||
|
||||
static struct cfi_softc cfi_softc;
|
||||
|
||||
static int cfi_init(void);
|
||||
static void cfi_shutdown(void);
|
||||
static void cfi_online(void *arg);
|
||||
static void cfi_offline(void *arg);
|
||||
static int cfi_lun_enable(void *arg, int lun_id);
|
||||
static int cfi_lun_disable(void *arg, int lun_id);
|
||||
static void cfi_datamove(union ctl_io *io);
|
||||
static void cfi_done(union ctl_io *io);
|
||||
|
||||
static struct ctl_frontend cfi_frontend =
|
||||
{
|
||||
.name = "ioctl",
|
||||
.init = cfi_init,
|
||||
.shutdown = cfi_shutdown,
|
||||
};
|
||||
CTL_FRONTEND_DECLARE(ctlioctl, cfi_frontend);
|
||||
|
||||
static int
|
||||
cfi_init(void)
|
||||
{
|
||||
struct cfi_softc *isoftc = &cfi_softc;
|
||||
struct ctl_port *port;
|
||||
|
||||
memset(isoftc, 0, sizeof(*isoftc));
|
||||
|
||||
port = &isoftc->port;
|
||||
port->frontend = &cfi_frontend;
|
||||
port->port_type = CTL_PORT_IOCTL;
|
||||
port->num_requested_ctl_io = 100;
|
||||
port->port_name = "ioctl";
|
||||
port->port_online = cfi_online;
|
||||
port->port_offline = cfi_offline;
|
||||
port->onoff_arg = &isoftc;
|
||||
port->lun_enable = cfi_lun_enable;
|
||||
port->lun_disable = cfi_lun_disable;
|
||||
port->targ_lun_arg = &isoftc;
|
||||
port->fe_datamove = cfi_datamove;
|
||||
port->fe_done = cfi_done;
|
||||
port->max_targets = 1;
|
||||
port->max_target_id = 0;
|
||||
port->max_initiators = 1;
|
||||
|
||||
if (ctl_port_register(port) != 0) {
|
||||
printf("%s: ioctl port registration failed\n", __func__);
|
||||
return (0);
|
||||
}
|
||||
ctl_port_online(port);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
cfi_shutdown(void)
|
||||
{
|
||||
struct cfi_softc *isoftc = &cfi_softc;
|
||||
struct ctl_port *port;
|
||||
|
||||
port = &isoftc->port;
|
||||
ctl_port_offline(port);
|
||||
if (ctl_port_deregister(&isoftc->port) != 0)
|
||||
printf("%s: ctl_frontend_deregister() failed\n", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
cfi_online(void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
cfi_offline(void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
cfi_lun_enable(void *arg, int lun_id)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cfi_lun_disable(void *arg, int lun_id)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Data movement routine for the CTL ioctl frontend port.
|
||||
*/
|
||||
static int
|
||||
ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio)
|
||||
{
|
||||
struct ctl_sg_entry *ext_sglist, *kern_sglist;
|
||||
struct ctl_sg_entry ext_entry, kern_entry;
|
||||
int ext_sglen, ext_sg_entries, kern_sg_entries;
|
||||
int ext_sg_start, ext_offset;
|
||||
int len_to_copy, len_copied;
|
||||
int kern_watermark, ext_watermark;
|
||||
int ext_sglist_malloced;
|
||||
int i, j;
|
||||
|
||||
ext_sglist_malloced = 0;
|
||||
ext_sg_start = 0;
|
||||
ext_offset = 0;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove\n"));
|
||||
|
||||
/*
|
||||
* If this flag is set, fake the data transfer.
|
||||
*/
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_NO_DATAMOVE) {
|
||||
ctsio->ext_data_filled = ctsio->ext_data_len;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
/*
|
||||
* To simplify things here, if we have a single buffer, stick it in
|
||||
* a S/G entry and just make it a single entry S/G list.
|
||||
*/
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_EDPTR_SGLIST) {
|
||||
int len_seen;
|
||||
|
||||
ext_sglen = ctsio->ext_sg_entries * sizeof(*ext_sglist);
|
||||
|
||||
ext_sglist = (struct ctl_sg_entry *)malloc(ext_sglen, M_CTL,
|
||||
M_WAITOK);
|
||||
ext_sglist_malloced = 1;
|
||||
if (copyin(ctsio->ext_data_ptr, ext_sglist,
|
||||
ext_sglen) != 0) {
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/ 0);
|
||||
goto bailout;
|
||||
}
|
||||
ext_sg_entries = ctsio->ext_sg_entries;
|
||||
len_seen = 0;
|
||||
for (i = 0; i < ext_sg_entries; i++) {
|
||||
if ((len_seen + ext_sglist[i].len) >=
|
||||
ctsio->ext_data_filled) {
|
||||
ext_sg_start = i;
|
||||
ext_offset = ctsio->ext_data_filled - len_seen;
|
||||
break;
|
||||
}
|
||||
len_seen += ext_sglist[i].len;
|
||||
}
|
||||
} else {
|
||||
ext_sglist = &ext_entry;
|
||||
ext_sglist->addr = ctsio->ext_data_ptr;
|
||||
ext_sglist->len = ctsio->ext_data_len;
|
||||
ext_sg_entries = 1;
|
||||
ext_sg_start = 0;
|
||||
ext_offset = ctsio->ext_data_filled;
|
||||
}
|
||||
|
||||
if (ctsio->kern_sg_entries > 0) {
|
||||
kern_sglist = (struct ctl_sg_entry *)ctsio->kern_data_ptr;
|
||||
kern_sg_entries = ctsio->kern_sg_entries;
|
||||
} else {
|
||||
kern_sglist = &kern_entry;
|
||||
kern_sglist->addr = ctsio->kern_data_ptr;
|
||||
kern_sglist->len = ctsio->kern_data_len;
|
||||
kern_sg_entries = 1;
|
||||
}
|
||||
|
||||
|
||||
kern_watermark = 0;
|
||||
ext_watermark = ext_offset;
|
||||
len_copied = 0;
|
||||
for (i = ext_sg_start, j = 0;
|
||||
i < ext_sg_entries && j < kern_sg_entries;) {
|
||||
uint8_t *ext_ptr, *kern_ptr;
|
||||
|
||||
len_to_copy = MIN(ext_sglist[i].len - ext_watermark,
|
||||
kern_sglist[j].len - kern_watermark);
|
||||
|
||||
ext_ptr = (uint8_t *)ext_sglist[i].addr;
|
||||
ext_ptr = ext_ptr + ext_watermark;
|
||||
if (ctsio->io_hdr.flags & CTL_FLAG_BUS_ADDR) {
|
||||
/*
|
||||
* XXX KDM fix this!
|
||||
*/
|
||||
panic("need to implement bus address support");
|
||||
#if 0
|
||||
kern_ptr = bus_to_virt(kern_sglist[j].addr);
|
||||
#endif
|
||||
} else
|
||||
kern_ptr = (uint8_t *)kern_sglist[j].addr;
|
||||
kern_ptr = kern_ptr + kern_watermark;
|
||||
|
||||
kern_watermark += len_to_copy;
|
||||
ext_watermark += len_to_copy;
|
||||
|
||||
if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
|
||||
CTL_FLAG_DATA_IN) {
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: copying %d "
|
||||
"bytes to user\n", len_to_copy));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: from %p "
|
||||
"to %p\n", kern_ptr, ext_ptr));
|
||||
if (copyout(kern_ptr, ext_ptr, len_to_copy) != 0) {
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/ 0);
|
||||
goto bailout;
|
||||
}
|
||||
} else {
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: copying %d "
|
||||
"bytes from user\n", len_to_copy));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: from %p "
|
||||
"to %p\n", ext_ptr, kern_ptr));
|
||||
if (copyin(ext_ptr, kern_ptr, len_to_copy)!= 0){
|
||||
ctl_set_internal_failure(ctsio,
|
||||
/*sks_valid*/ 0,
|
||||
/*retry_count*/0);
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
|
||||
len_copied += len_to_copy;
|
||||
|
||||
if (ext_sglist[i].len == ext_watermark) {
|
||||
i++;
|
||||
ext_watermark = 0;
|
||||
}
|
||||
|
||||
if (kern_sglist[j].len == kern_watermark) {
|
||||
j++;
|
||||
kern_watermark = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctsio->ext_data_filled += len_copied;
|
||||
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: ext_sg_entries: %d, "
|
||||
"kern_sg_entries: %d\n", ext_sg_entries,
|
||||
kern_sg_entries));
|
||||
CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove: ext_data_len = %d, "
|
||||
"kern_data_len = %d\n", ctsio->ext_data_len,
|
||||
ctsio->kern_data_len));
|
||||
|
||||
|
||||
/* XXX KDM set residual?? */
|
||||
bailout:
|
||||
|
||||
if (ext_sglist_malloced != 0)
|
||||
free(ext_sglist, M_CTL);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
static void
|
||||
cfi_datamove(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params *params;
|
||||
|
||||
params = (struct ctl_fe_ioctl_params *)
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
|
||||
|
||||
mtx_lock(¶ms->ioctl_mtx);
|
||||
params->state = CTL_IOCTL_DATAMOVE;
|
||||
cv_broadcast(¶ms->sem);
|
||||
mtx_unlock(¶ms->ioctl_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
cfi_done(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params *params;
|
||||
|
||||
params = (struct ctl_fe_ioctl_params *)
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
|
||||
|
||||
mtx_lock(¶ms->ioctl_mtx);
|
||||
params->state = CTL_IOCTL_DONE;
|
||||
cv_broadcast(¶ms->sem);
|
||||
mtx_unlock(¶ms->ioctl_mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
cfi_submit_wait(union ctl_io *io)
|
||||
{
|
||||
struct ctl_fe_ioctl_params params;
|
||||
ctl_fe_ioctl_state last_state;
|
||||
int done, retval;
|
||||
|
||||
retval = 0;
|
||||
|
||||
bzero(¶ms, sizeof(params));
|
||||
|
||||
mtx_init(¶ms.ioctl_mtx, "ctliocmtx", NULL, MTX_DEF);
|
||||
cv_init(¶ms.sem, "ctlioccv");
|
||||
params.state = CTL_IOCTL_INPROG;
|
||||
last_state = params.state;
|
||||
|
||||
io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ¶ms;
|
||||
|
||||
CTL_DEBUG_PRINT(("cfi_submit_wait\n"));
|
||||
|
||||
/* This shouldn't happen */
|
||||
if ((retval = ctl_queue(io)) != CTL_RETVAL_COMPLETE)
|
||||
return (retval);
|
||||
|
||||
done = 0;
|
||||
|
||||
do {
|
||||
mtx_lock(¶ms.ioctl_mtx);
|
||||
/*
|
||||
* Check the state here, and don't sleep if the state has
|
||||
* already changed (i.e. wakeup has already occured, but we
|
||||
* weren't waiting yet).
|
||||
*/
|
||||
if (params.state == last_state) {
|
||||
/* XXX KDM cv_wait_sig instead? */
|
||||
cv_wait(¶ms.sem, ¶ms.ioctl_mtx);
|
||||
}
|
||||
last_state = params.state;
|
||||
|
||||
switch (params.state) {
|
||||
case CTL_IOCTL_INPROG:
|
||||
/* Why did we wake up? */
|
||||
/* XXX KDM error here? */
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
break;
|
||||
case CTL_IOCTL_DATAMOVE:
|
||||
CTL_DEBUG_PRINT(("got CTL_IOCTL_DATAMOVE\n"));
|
||||
|
||||
/*
|
||||
* change last_state back to INPROG to avoid
|
||||
* deadlock on subsequent data moves.
|
||||
*/
|
||||
params.state = last_state = CTL_IOCTL_INPROG;
|
||||
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
ctl_ioctl_do_datamove(&io->scsiio);
|
||||
/*
|
||||
* Note that in some cases, most notably writes,
|
||||
* this will queue the I/O and call us back later.
|
||||
* In other cases, generally reads, this routine
|
||||
* will immediately call back and wake us up,
|
||||
* probably using our own context.
|
||||
*/
|
||||
io->scsiio.be_move_done(io);
|
||||
break;
|
||||
case CTL_IOCTL_DONE:
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
CTL_DEBUG_PRINT(("got CTL_IOCTL_DONE\n"));
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
mtx_unlock(¶ms.ioctl_mtx);
|
||||
/* XXX KDM error here? */
|
||||
break;
|
||||
}
|
||||
} while (done == 0);
|
||||
|
||||
mtx_destroy(¶ms.ioctl_mtx);
|
||||
cv_destroy(¶ms.sem);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct thread *td)
|
||||
{
|
||||
union ctl_io *io;
|
||||
void *pool_tmp;
|
||||
int retval = 0;
|
||||
|
||||
/*
|
||||
* If we haven't been "enabled", don't allow any SCSI I/O
|
||||
* to this FETD.
|
||||
*/
|
||||
if ((cfi_softc.port.status & CTL_PORT_STATUS_ONLINE) == 0)
|
||||
return (EPERM);
|
||||
|
||||
io = ctl_alloc_io(cfi_softc.port.ctl_pool_ref);
|
||||
|
||||
/*
|
||||
* Need to save the pool reference so it doesn't get
|
||||
* spammed by the user's ctl_io.
|
||||
*/
|
||||
pool_tmp = io->io_hdr.pool;
|
||||
memcpy(io, (void *)addr, sizeof(*io));
|
||||
io->io_hdr.pool = pool_tmp;
|
||||
|
||||
/*
|
||||
* No status yet, so make sure the status is set properly.
|
||||
*/
|
||||
io->io_hdr.status = CTL_STATUS_NONE;
|
||||
|
||||
/*
|
||||
* The user sets the initiator ID, target and LUN IDs.
|
||||
*/
|
||||
io->io_hdr.nexus.targ_port = cfi_softc.port.targ_port;
|
||||
io->io_hdr.flags |= CTL_FLAG_USER_REQ;
|
||||
if ((io->io_hdr.io_type == CTL_IO_SCSI) &&
|
||||
(io->scsiio.tag_type != CTL_TAG_UNTAGGED))
|
||||
io->scsiio.tag_num = cfi_softc.cur_tag_num++;
|
||||
|
||||
retval = cfi_submit_wait(io);
|
||||
if (retval == 0)
|
||||
memcpy((void *)addr, io, sizeof(*io));
|
||||
ctl_free_io(io);
|
||||
return (retval);
|
||||
}
|
@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_error.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_debug.h>
|
||||
#include <cam/ctl/ctl_ha.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
|
@ -92,23 +92,6 @@ struct ctl_ooa_info {
|
||||
ctl_ooa_status status; /* Returned from CTL */
|
||||
};
|
||||
|
||||
struct ctl_hard_startstop_info {
|
||||
cfi_mt_status status;
|
||||
int total_luns;
|
||||
int luns_complete;
|
||||
int luns_failed;
|
||||
};
|
||||
|
||||
struct ctl_bbrread_info {
|
||||
int lun_num; /* Passed in to CTL */
|
||||
uint64_t lba; /* Passed in to CTL */
|
||||
int len; /* Passed in to CTL */
|
||||
cfi_mt_status status; /* Returned from CTL */
|
||||
cfi_bbrread_status bbr_status; /* Returned from CTL */
|
||||
uint8_t scsi_status; /* Returned from CTL */
|
||||
struct scsi_sense_data sense_data; /* Returned from CTL */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CTL_DELAY_TYPE_NONE,
|
||||
CTL_DELAY_TYPE_CONT,
|
||||
@ -828,10 +811,6 @@ struct ctl_lun_map {
|
||||
#define CTL_DISABLE_PORT _IOW(CTL_MINOR, 0x05, struct ctl_port_entry)
|
||||
#define CTL_DUMP_OOA _IO(CTL_MINOR, 0x06)
|
||||
#define CTL_CHECK_OOA _IOWR(CTL_MINOR, 0x07, struct ctl_ooa_info)
|
||||
#define CTL_HARD_STOP _IOR(CTL_MINOR, 0x08, \
|
||||
struct ctl_hard_startstop_info)
|
||||
#define CTL_HARD_START _IOR(CTL_MINOR, 0x09, \
|
||||
struct ctl_hard_startstop_info)
|
||||
#define CTL_DELAY_IO _IOWR(CTL_MINOR, 0x10, struct ctl_io_delay_info)
|
||||
#define CTL_REALSYNC_GET _IOR(CTL_MINOR, 0x11, int)
|
||||
#define CTL_REALSYNC_SET _IOW(CTL_MINOR, 0x12, int)
|
||||
@ -839,7 +818,6 @@ struct ctl_lun_map {
|
||||
#define CTL_GETSYNC _IOWR(CTL_MINOR, 0x14, struct ctl_sync_info)
|
||||
#define CTL_GETSTATS _IOWR(CTL_MINOR, 0x15, struct ctl_stats)
|
||||
#define CTL_ERROR_INJECT _IOWR(CTL_MINOR, 0x16, struct ctl_error_desc)
|
||||
#define CTL_BBRREAD _IOWR(CTL_MINOR, 0x17, struct ctl_bbrread_info)
|
||||
#define CTL_GET_OOA _IOWR(CTL_MINOR, 0x18, struct ctl_ooa)
|
||||
#define CTL_DUMP_STRUCTS _IO(CTL_MINOR, 0x19)
|
||||
#define CTL_GET_PORT_LIST _IOWR(CTL_MINOR, 0x20, struct ctl_port_list)
|
||||
|
@ -47,18 +47,6 @@
|
||||
#define CTL_PROCESSOR_PRODUCT "CTLPROCESSOR "
|
||||
#define CTL_UNKNOWN_PRODUCT "CTLDEVICE "
|
||||
|
||||
struct ctl_fe_ioctl_startstop_info {
|
||||
struct cv sem;
|
||||
struct ctl_hard_startstop_info hs_info;
|
||||
};
|
||||
|
||||
struct ctl_fe_ioctl_bbrread_info {
|
||||
struct cv sem;
|
||||
struct ctl_bbrread_info *bbr_info;
|
||||
int wakeup_done;
|
||||
struct mtx *lock;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CTL_IOCTL_INPROG,
|
||||
CTL_IOCTL_DATAMOVE,
|
||||
@ -80,18 +68,6 @@ struct ctl_io_pool {
|
||||
struct uma_zone *zone;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CTL_IOCTL_FLAG_NONE = 0x00,
|
||||
CTL_IOCTL_FLAG_ENABLED = 0x01
|
||||
} ctl_ioctl_flags;
|
||||
|
||||
struct ctl_ioctl_info {
|
||||
ctl_ioctl_flags flags;
|
||||
uint32_t cur_tag_num;
|
||||
struct ctl_port port;
|
||||
char port_name[24];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CTL_SER_BLOCK,
|
||||
CTL_SER_BLOCKOPT,
|
||||
@ -472,7 +448,6 @@ struct ctl_softc {
|
||||
int inquiry_pq_no_lun;
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
struct ctl_ioctl_info ioctl_info;
|
||||
void *othersc_pool;
|
||||
struct proc *ctl_proc;
|
||||
int targ_online;
|
||||
|
@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
|
@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/ctl/ctl_io.h>
|
||||
#include <cam/ctl/ctl.h>
|
||||
#include <cam/ctl/ctl_frontend.h>
|
||||
#include <cam/ctl/ctl_frontend_internal.h>
|
||||
#include <cam/ctl/ctl_util.h>
|
||||
#include <cam/ctl/ctl_backend.h>
|
||||
#include <cam/ctl/ctl_ioctl.h>
|
||||
|
@ -42,29 +42,19 @@
|
||||
*/
|
||||
#define nvlist_add_binary illumos_nvlist_add_binary
|
||||
#define nvlist_add_bool illumos_nvlist_add_bool
|
||||
#define nvlist_add_bool_array illumos_nvlist_add_bool_array
|
||||
#define nvlist_add_descriptor illumos_nvlist_add_descriptor
|
||||
#define nvlist_add_descriptor_array illumos_nvlist_add_descriptor_array
|
||||
#define nvlist_add_null illumos_nvlist_add_null
|
||||
#define nvlist_add_number illumos_nvlist_add_number
|
||||
#define nvlist_add_number_array illumos_nvlist_add_number_array
|
||||
#define nvlist_add_nvlist illumos_nvlist_add_nvlist
|
||||
#define nvlist_add_nvlist_array illumos_nvlist_add_nvlist_array
|
||||
#define nvlist_add_nvpair illumos_nvlist_add_nvpair
|
||||
#define nvlist_add_string illumos_nvlist_add_string
|
||||
#define nvlist_add_string_array illumos_nvlist_add_string_array
|
||||
#define nvlist_add_stringf illumos_nvlist_add_stringf
|
||||
#define nvlist_add_stringv illumos_nvlist_add_stringv
|
||||
#define nvlist_addf_binary illumos_nvlist_addf_binary
|
||||
#define nvlist_addf_bool illumos_nvlist_addf_bool
|
||||
#define nvlist_addf_descriptor illumos_nvlist_addf_descriptor
|
||||
#define nvlist_addf_null illumos_nvlist_addf_null
|
||||
#define nvlist_addf_number illumos_nvlist_addf_number
|
||||
#define nvlist_addf_nvlist illumos_nvlist_addf_nvlist
|
||||
#define nvlist_addf_string illumos_nvlist_addf_string
|
||||
#define nvlist_addv_binary illumos_nvlist_addv_binary
|
||||
#define nvlist_addv_bool illumos_nvlist_addv_bool
|
||||
#define nvlist_addv_descriptor illumos_nvlist_addv_descriptor
|
||||
#define nvlist_addv_null illumos_nvlist_addv_null
|
||||
#define nvlist_addv_number illumos_nvlist_addv_number
|
||||
#define nvlist_addv_nvlist illumos_nvlist_addv_nvlist
|
||||
#define nvlist_addv_string illumos_nvlist_addv_string
|
||||
#define nvlist_check_header illumos_nvlist_check_header
|
||||
#define nvlist_clone illumos_nvlist_clone
|
||||
#define nvlist_create illumos_nvlist_create
|
||||
#define nvlist_descriptors illumos_nvlist_descriptors
|
||||
@ -75,92 +65,61 @@
|
||||
#define nvlist_exists illumos_nvlist_exists
|
||||
#define nvlist_exists_binary illumos_nvlist_exists_binary
|
||||
#define nvlist_exists_bool illumos_nvlist_exists_bool
|
||||
#define nvlist_exists_bool_array illumos_nvlist_exists_bool_array
|
||||
#define nvlist_exists_descriptor illumos_nvlist_exists_descriptor
|
||||
#define nvlist_exists_descriptor_array illumos_nvlist_exists_descriptor_array
|
||||
#define nvlist_exists_null illumos_nvlist_exists_null
|
||||
#define nvlist_exists_number illumos_nvlist_exists_number
|
||||
#define nvlist_exists_number_array illumos_nvlist_exists_number_array
|
||||
#define nvlist_exists_nvlist illumos_nvlist_exists_nvlist
|
||||
#define nvlist_exists_nvlist_array illumos_nvlist_exists_nvlist_array
|
||||
#define nvlist_exists_string illumos_nvlist_exists_string
|
||||
#define nvlist_exists_string_array illumos_nvlist_exists_string_array
|
||||
#define nvlist_exists_type illumos_nvlist_exists_type
|
||||
#define nvlist_existsf illumos_nvlist_existsf
|
||||
#define nvlist_existsf_binary illumos_nvlist_existsf_binary
|
||||
#define nvlist_existsf_bool illumos_nvlist_existsf_bool
|
||||
#define nvlist_existsf_descriptor illumos_nvlist_existsf_descriptor
|
||||
#define nvlist_existsf_null illumos_nvlist_existsf_null
|
||||
#define nvlist_existsf_number illumos_nvlist_existsf_number
|
||||
#define nvlist_existsf_nvlist illumos_nvlist_existsf_nvlist
|
||||
#define nvlist_existsf_string illumos_nvlist_existsf_string
|
||||
#define nvlist_existsf_type illumos_nvlist_existsf_type
|
||||
#define nvlist_existsv illumos_nvlist_existsv
|
||||
#define nvlist_existsv_binary illumos_nvlist_existsv_binary
|
||||
#define nvlist_existsv_bool illumos_nvlist_existsv_bool
|
||||
#define nvlist_existsv_descriptor illumos_nvlist_existsv_descriptor
|
||||
#define nvlist_existsv_null illumos_nvlist_existsv_null
|
||||
#define nvlist_existsv_number illumos_nvlist_existsv_number
|
||||
#define nvlist_existsv_nvlist illumos_nvlist_existsv_nvlist
|
||||
#define nvlist_existsv_string illumos_nvlist_existsv_string
|
||||
#define nvlist_existsv_type illumos_nvlist_existsv_type
|
||||
#define nvlist_fdump illumos_nvlist_fdump
|
||||
#define nvlist_first_nvpair illumos_nvlist_first_nvpair
|
||||
#define nvlist_flags illumos_nvlist_flags
|
||||
#define nvlist_free illumos_nvlist_free
|
||||
#define nvlist_free_binary illumos_nvlist_free_binary
|
||||
#define nvlist_free_binary_array illumos_nvlist_free_binary_array
|
||||
#define nvlist_free_bool illumos_nvlist_free_bool
|
||||
#define nvlist_free_bool_array illumos_nvlist_free_bool_array
|
||||
#define nvlist_free_descriptor illumos_nvlist_free_descriptor
|
||||
#define nvlist_free_descriptor_array illumos_nvlist_free_descriptor_array
|
||||
#define nvlist_free_null illumos_nvlist_free_null
|
||||
#define nvlist_free_number illumos_nvlist_free_number
|
||||
#define nvlist_free_number_array illumos_nvlist_free_number_array
|
||||
#define nvlist_free_nvlist illumos_nvlist_free_nvlist
|
||||
#define nvlist_free_nvlist_array illumos_nvlist_free_nvlist_array
|
||||
#define nvlist_free_nvpair illumos_nvlist_free_nvpair
|
||||
#define nvlist_free_string illumos_nvlist_free_string
|
||||
#define nvlist_free_string_array illumos_nvlist_free_string_array
|
||||
#define nvlist_free_type illumos_nvlist_free_type
|
||||
#define nvlist_freef illumos_nvlist_freef
|
||||
#define nvlist_freef_binary illumos_nvlist_freef_binary
|
||||
#define nvlist_freef_bool illumos_nvlist_freef_bool
|
||||
#define nvlist_freef_descriptor illumos_nvlist_freef_descriptor
|
||||
#define nvlist_freef_null illumos_nvlist_freef_null
|
||||
#define nvlist_freef_number illumos_nvlist_freef_number
|
||||
#define nvlist_freef_nvlist illumos_nvlist_freef_nvlist
|
||||
#define nvlist_freef_string illumos_nvlist_freef_string
|
||||
#define nvlist_freef_type illumos_nvlist_freef_type
|
||||
#define nvlist_freev illumos_nvlist_freev
|
||||
#define nvlist_freev_binary illumos_nvlist_freev_binary
|
||||
#define nvlist_freev_bool illumos_nvlist_freev_bool
|
||||
#define nvlist_freev_descriptor illumos_nvlist_freev_descriptor
|
||||
#define nvlist_freev_null illumos_nvlist_freev_null
|
||||
#define nvlist_freev_number illumos_nvlist_freev_number
|
||||
#define nvlist_freev_nvlist illumos_nvlist_freev_nvlist
|
||||
#define nvlist_freev_string illumos_nvlist_freev_string
|
||||
#define nvlist_freev_type illumos_nvlist_freev_type
|
||||
#define nvlist_get_array_next illumos_nvlist_get_array_next
|
||||
#define nvlist_get_binary illumos_nvlist_get_binary
|
||||
#define nvlist_get_bool illumos_nvlist_get_bool
|
||||
#define nvlist_get_bool_array illumos_nvlist_get_bool_array
|
||||
#define nvlist_get_descriptor illumos_nvlist_get_descriptor
|
||||
#define nvlist_get_descriptor_array illumos_nvlist_get_descriptor_array
|
||||
#define nvlist_get_number illumos_nvlist_get_number
|
||||
#define nvlist_get_number_array illumos_nvlist_get_number_array
|
||||
#define nvlist_get_nvlist illumos_nvlist_get_nvlist
|
||||
#define nvlist_get_nvpair illumos_nvlist_get_nvpair
|
||||
#define nvlist_get_nvpair_parent illumos_nvlist_get_nvpair_parent
|
||||
#define nvlist_get_pararr illumos_nvlist_get_pararr
|
||||
#define nvlist_get_parent illumos_nvlist_get_parent
|
||||
#define nvlist_get_string illumos_nvlist_get_string
|
||||
#define nvlist_getf_binary illumos_nvlist_getf_binary
|
||||
#define nvlist_getf_bool illumos_nvlist_getf_bool
|
||||
#define nvlist_getf_descriptor illumos_nvlist_getf_descriptor
|
||||
#define nvlist_getf_number illumos_nvlist_getf_number
|
||||
#define nvlist_getf_nvlist illumos_nvlist_getf_nvlist
|
||||
#define nvlist_getf_string illumos_nvlist_getf_string
|
||||
#define nvlist_getv_binary illumos_nvlist_getv_binary
|
||||
#define nvlist_getv_bool illumos_nvlist_getv_bool
|
||||
#define nvlist_getv_descriptor illumos_nvlist_getv_descriptor
|
||||
#define nvlist_getv_number illumos_nvlist_getv_number
|
||||
#define nvlist_getv_nvlist illumos_nvlist_getv_nvlist
|
||||
#define nvlist_getv_string illumos_nvlist_getv_string
|
||||
#define nvlist_in_array illumos_nvlist_in_array
|
||||
#define nvlist_move_binary illumos_nvlist_move_binary
|
||||
#define nvlist_move_bool_array illumos_nvlist_move_bool_array
|
||||
#define nvlist_move_descriptor illumos_nvlist_move_descriptor
|
||||
#define nvlist_move_descriptor_array illumos_nvlist_move_descriptor_array
|
||||
#define nvlist_move_number_array illumos_nvlist_move_number_array
|
||||
#define nvlist_move_nvlist illumos_nvlist_move_nvlist
|
||||
#define nvlist_move_nvlist_array illumos_nvlist_move_nvlist_array
|
||||
#define nvlist_move_nvpair illumos_nvlist_move_nvpair
|
||||
#define nvlist_move_string illumos_nvlist_move_string
|
||||
#define nvlist_movef_binary illumos_nvlist_movef_binary
|
||||
#define nvlist_movef_descriptor illumos_nvlist_movef_descriptor
|
||||
#define nvlist_movef_nvlist illumos_nvlist_movef_nvlist
|
||||
#define nvlist_movef_string illumos_nvlist_movef_string
|
||||
#define nvlist_movev_binary illumos_nvlist_movev_binary
|
||||
#define nvlist_movev_descriptor illumos_nvlist_movev_descriptor
|
||||
#define nvlist_movev_nvlist illumos_nvlist_movev_nvlist
|
||||
#define nvlist_movev_string illumos_nvlist_movev_string
|
||||
#define nvlist_move_string_array illumos_nvlist_move_string_array
|
||||
#define nvlist_ndescriptors illumos_nvlist_ndescriptors
|
||||
#define nvlist_next illumos_nvlist_next
|
||||
#define nvlist_next_nvpair illumos_nvlist_next_nvpair
|
||||
@ -168,93 +127,101 @@
|
||||
#define nvlist_prev_nvpair illumos_nvlist_prev_nvpair
|
||||
#define nvlist_recv illumos_nvlist_recv
|
||||
#define nvlist_remove_nvpair illumos_nvlist_remove_nvpair
|
||||
#define nvlist_report_missing illumos_nvlist_report_missing
|
||||
#define nvlist_send illumos_nvlist_send
|
||||
#define nvlist_set_array_next illumos_nvlist_set_array_next
|
||||
#define nvlist_set_error illumos_nvlist_set_error
|
||||
#define nvlist_set_flags illumos_nvlist_set_flags
|
||||
#define nvlist_set_parent illumos_nvlist_set_parent
|
||||
#define nvlist_size illumos_nvlist_size
|
||||
#define nvlist_take_binary illumos_nvlist_take_binary
|
||||
#define nvlist_take_bool illumos_nvlist_take_bool
|
||||
#define nvlist_take_bool_array illumos_nvlist_take_bool_array
|
||||
#define nvlist_take_descriptor illumos_nvlist_take_descriptor
|
||||
#define nvlist_take_descriptor_array illumos_nvlist_take_descriptor_array
|
||||
#define nvlist_take_number illumos_nvlist_take_number
|
||||
#define nvlist_take_number_array illumos_nvlist_take_number_array
|
||||
#define nvlist_take_nvlist illumos_nvlist_take_nvlist
|
||||
#define nvlist_take_nvlist_array illumos_nvlist_take_nvlist_array
|
||||
#define nvlist_take_nvpair illumos_nvlist_take_nvpair
|
||||
#define nvlist_take_string illumos_nvlist_take_string
|
||||
#define nvlist_takef_binary illumos_nvlist_takef_binary
|
||||
#define nvlist_takef_bool illumos_nvlist_takef_bool
|
||||
#define nvlist_takef_descriptor illumos_nvlist_takef_descriptor
|
||||
#define nvlist_takef_number illumos_nvlist_takef_number
|
||||
#define nvlist_takef_nvlist illumos_nvlist_takef_nvlist
|
||||
#define nvlist_takef_string illumos_nvlist_takef_string
|
||||
#define nvlist_takev_binary illumos_nvlist_takev_binary
|
||||
#define nvlist_takev_bool illumos_nvlist_takev_bool
|
||||
#define nvlist_takev_descriptor illumos_nvlist_takev_descriptor
|
||||
#define nvlist_takev_number illumos_nvlist_takev_number
|
||||
#define nvlist_takev_nvlist illumos_nvlist_takev_nvlist
|
||||
#define nvlist_takev_string illumos_nvlist_takev_string
|
||||
#define nvlist_take_string_array illumos_nvlist_take_string_array
|
||||
#define nvlist_unpack illumos_nvlist_unpack
|
||||
#define nvlist_unpack_header illumos_nvlist_unpack_header
|
||||
#define nvlist_xfer illumos_nvlist_xfer
|
||||
#define nvlist_xpack illumos_nvlist_xpack
|
||||
#define nvlist_xunpack illumos_nvlist_xunpack
|
||||
#define nvpair_allocv illumos_nvpair_allocv
|
||||
#define nvpair_assert illumos_nvpair_assert
|
||||
#define nvpair_clone illumos_nvpair_clone
|
||||
#define nvpair_create_binary illumos_nvpair_create_binary
|
||||
#define nvpair_create_bool illumos_nvpair_create_bool
|
||||
#define nvpair_create_bool_array illumos_nvpair_create_bool_array
|
||||
#define nvpair_create_descriptor illumos_nvpair_create_descriptor
|
||||
#define nvpair_create_descriptor_array illumos_nvpair_create_descriptor_array
|
||||
#define nvpair_create_null illumos_nvpair_create_null
|
||||
#define nvpair_create_number illumos_nvpair_create_number
|
||||
#define nvpair_create_number_array illumos_nvpair_create_number_array
|
||||
#define nvpair_create_nvlist illumos_nvpair_create_nvlist
|
||||
#define nvpair_create_nvlist_array illumos_nvpair_create_nvlist_array
|
||||
#define nvpair_create_string illumos_nvpair_create_string
|
||||
#define nvpair_create_string_array illumos_nvpair_create_string_array
|
||||
#define nvpair_create_stringf illumos_nvpair_create_stringf
|
||||
#define nvpair_create_stringv illumos_nvpair_create_stringv
|
||||
#define nvpair_createf_binary illumos_nvpair_createf_binary
|
||||
#define nvpair_createf_bool illumos_nvpair_createf_bool
|
||||
#define nvpair_createf_descriptor illumos_nvpair_createf_descriptor
|
||||
#define nvpair_createf_null illumos_nvpair_createf_null
|
||||
#define nvpair_createf_number illumos_nvpair_createf_number
|
||||
#define nvpair_createf_nvlist illumos_nvpair_createf_nvlist
|
||||
#define nvpair_createf_string illumos_nvpair_createf_string
|
||||
#define nvpair_createv_binary illumos_nvpair_createv_binary
|
||||
#define nvpair_createv_bool illumos_nvpair_createv_bool
|
||||
#define nvpair_createv_descriptor illumos_nvpair_createv_descriptor
|
||||
#define nvpair_createv_null illumos_nvpair_createv_null
|
||||
#define nvpair_createv_number illumos_nvpair_createv_number
|
||||
#define nvpair_createv_nvlist illumos_nvpair_createv_nvlist
|
||||
#define nvpair_createv_string illumos_nvpair_createv_string
|
||||
#define nvpair_free illumos_nvpair_free
|
||||
#define nvpair_free_structure illumos_nvpair_free_structure
|
||||
#define nvpair_get_binary illumos_nvpair_get_binary
|
||||
#define nvpair_get_bool illumos_nvpair_get_bool
|
||||
#define nvpair_get_bool_array illumos_nvpair_get_bool_array
|
||||
#define nvpair_get_descriptor illumos_nvpair_get_descriptor
|
||||
#define nvpair_get_descriptor_array illumos_nvpair_get_descriptor_array
|
||||
#define nvpair_get_number illumos_nvpair_get_number
|
||||
#define nvpair_get_number_array illumos_nvpair_get_number_array
|
||||
#define nvpair_get_nvlist illumos_nvpair_get_nvlist
|
||||
#define nvpair_get_string illumos_nvpair_get_string
|
||||
#define nvpair_header_size illumos_nvpair_header_size
|
||||
#define nvpair_init_datasize illumos_nvpair_init_datasize
|
||||
#define nvpair_insert illumos_nvpair_insert
|
||||
#define nvpair_move_binary illumos_nvpair_move_binary
|
||||
#define nvpair_move_bool_array illumos_nvpair_move_bool_array
|
||||
#define nvpair_move_descriptor illumos_nvpair_move_descriptor
|
||||
#define nvpair_move_descriptor_array illumos_nvpair_move_descriptor_array
|
||||
#define nvpair_move_number_array illumos_nvpair_move_number_array
|
||||
#define nvpair_move_nvlist illumos_nvpair_move_nvlist
|
||||
#define nvpair_move_nvlist_array illumos_nvpair_move_nvlist_array
|
||||
#define nvpair_move_string illumos_nvpair_move_string
|
||||
#define nvpair_movef_binary illumos_nvpair_movef_binary
|
||||
#define nvpair_movef_descriptor illumos_nvpair_movef_descriptor
|
||||
#define nvpair_movef_nvlist illumos_nvpair_movef_nvlist
|
||||
#define nvpair_movef_string illumos_nvpair_movef_string
|
||||
#define nvpair_movev_binary illumos_nvpair_movev_binary
|
||||
#define nvpair_movev_descriptor illumos_nvpair_movev_descriptor
|
||||
#define nvpair_movev_nvlist illumos_nvpair_movev_nvlist
|
||||
#define nvpair_movev_string illumos_nvpair_movev_string
|
||||
#define nvpair_move_string_array illumos_nvpair_move_string_array
|
||||
#define nvpair_name illumos_nvpair_name
|
||||
#define nvpair_next illumos_nvpair_next
|
||||
#define nvpair_nvlist illumos_nvpair_nvlist
|
||||
#define nvpair_pack illumos_nvpair_pack
|
||||
#define nvpair_pack_binary illumos_nvpair_pack_binary
|
||||
#define nvpair_pack_bool illumos_nvpair_pack_bool
|
||||
#define nvpair_pack_bool_array illumos_nvpair_pack_bool_array
|
||||
#define nvpair_pack_descriptor illumos_nvpair_pack_descriptor
|
||||
#define nvpair_pack_descriptor_array illumos_nvpair_pack_descriptor_array
|
||||
#define nvpair_pack_header illumos_nvpair_pack_header
|
||||
#define nvpair_pack_null illumos_nvpair_pack_null
|
||||
#define nvpair_pack_number illumos_nvpair_pack_number
|
||||
#define nvpair_pack_number_array illumos_nvpair_pack_number_array
|
||||
#define nvpair_pack_nvlist_array_next illumos_nvpair_pack_nvlist_array_next
|
||||
#define nvpair_pack_nvlist_up illumos_nvpair_pack_nvlist_up
|
||||
#define nvpair_pack_string illumos_nvpair_pack_string
|
||||
#define nvpair_pack_string_array illumos_nvpair_pack_string_array
|
||||
#define nvpair_prev illumos_nvpair_prev
|
||||
#define nvpair_remove illumos_nvpair_remove
|
||||
#define nvpair_size illumos_nvpair_size
|
||||
#define nvpair_type illumos_nvpair_type
|
||||
#define nvpair_type_string illumos_nvpair_type_string
|
||||
#define nvpair_unpack illumos_nvpair_unpack
|
||||
#define nvpair_unpack_binary illumos_nvpair_unpack_binary
|
||||
#define nvpair_unpack_bool illumos_nvpair_unpack_bool
|
||||
#define nvpair_unpack_bool_array illumos_nvpair_unpack_bool_array
|
||||
#define nvpair_unpack_descriptor illumos_nvpair_unpack_descriptor
|
||||
#define nvpair_unpack_descriptor_array illumos_nvpair_unpack_descriptor_array
|
||||
#define nvpair_unpack_header illumos_nvpair_unpack_header
|
||||
#define nvpair_unpack_null illumos_nvpair_unpack_null
|
||||
#define nvpair_unpack_number illumos_nvpair_unpack_number
|
||||
#define nvpair_unpack_number_array illumos_nvpair_unpack_number_array
|
||||
#define nvpair_unpack_nvlist illumos_nvpair_unpack_nvlist
|
||||
#define nvpair_unpack_nvlist_array illumos_nvpair_unpack_nvlist_array
|
||||
#define nvpair_unpack_string illumos_nvpair_unpack_string
|
||||
#define nvpair_unpack_string_array illumos_nvpair_unpack_string_array
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
||||
@ -129,15 +129,15 @@ zfeature_depends_on(spa_feature_t fid, spa_feature_t check) {
|
||||
|
||||
static void
|
||||
zfeature_register(spa_feature_t fid, const char *guid, const char *name,
|
||||
const char *desc, boolean_t readonly, boolean_t mos,
|
||||
boolean_t activate_on_enable, const spa_feature_t *deps)
|
||||
const char *desc, zfeature_flags_t flags, const spa_feature_t *deps)
|
||||
{
|
||||
zfeature_info_t *feature = &spa_feature_table[fid];
|
||||
static spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
|
||||
|
||||
ASSERT(name != NULL);
|
||||
ASSERT(desc != NULL);
|
||||
ASSERT(!readonly || !mos);
|
||||
ASSERT((flags & ZFEATURE_FLAG_READONLY_COMPAT) == 0 ||
|
||||
(flags & ZFEATURE_FLAG_MOS) == 0);
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(zfeature_is_valid_guid(guid));
|
||||
|
||||
@ -148,9 +148,7 @@ zfeature_register(spa_feature_t fid, const char *guid, const char *name,
|
||||
feature->fi_guid = guid;
|
||||
feature->fi_uname = name;
|
||||
feature->fi_desc = desc;
|
||||
feature->fi_can_readonly = readonly;
|
||||
feature->fi_mos = mos;
|
||||
feature->fi_activate_on_enable = activate_on_enable;
|
||||
feature->fi_flags = flags;
|
||||
feature->fi_depends = deps;
|
||||
}
|
||||
|
||||
@ -159,45 +157,46 @@ zpool_feature_init(void)
|
||||
{
|
||||
zfeature_register(SPA_FEATURE_ASYNC_DESTROY,
|
||||
"com.delphix:async_destroy", "async_destroy",
|
||||
"Destroy filesystems asynchronously.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Destroy filesystems asynchronously.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_EMPTY_BPOBJ,
|
||||
"com.delphix:empty_bpobj", "empty_bpobj",
|
||||
"Snapshots use less space.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Snapshots use less space.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_LZ4_COMPRESS,
|
||||
"org.illumos:lz4_compress", "lz4_compress",
|
||||
"LZ4 compression algorithm support.", B_FALSE, B_FALSE,
|
||||
B_TRUE, NULL);
|
||||
"LZ4 compression algorithm support.",
|
||||
ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_MULTI_VDEV_CRASH_DUMP,
|
||||
"com.joyent:multi_vdev_crash_dump", "multi_vdev_crash_dump",
|
||||
"Crash dumps to multiple vdev pools.", B_FALSE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Crash dumps to multiple vdev pools.",
|
||||
0, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM,
|
||||
"com.delphix:spacemap_histogram", "spacemap_histogram",
|
||||
"Spacemaps maintain space histograms.", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Spacemaps maintain space histograms.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
zfeature_register(SPA_FEATURE_ENABLED_TXG,
|
||||
"com.delphix:enabled_txg", "enabled_txg",
|
||||
"Record txg at which a feature is enabled", B_TRUE, B_FALSE,
|
||||
B_FALSE, NULL);
|
||||
"Record txg at which a feature is enabled",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, NULL);
|
||||
|
||||
static spa_feature_t hole_birth_deps[] = { SPA_FEATURE_ENABLED_TXG,
|
||||
SPA_FEATURE_NONE };
|
||||
zfeature_register(SPA_FEATURE_HOLE_BIRTH,
|
||||
"com.delphix:hole_birth", "hole_birth",
|
||||
"Retain hole birth txg for more precise zfs send",
|
||||
B_FALSE, B_TRUE, B_TRUE, hole_birth_deps);
|
||||
ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
|
||||
hole_birth_deps);
|
||||
|
||||
zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET,
|
||||
"com.delphix:extensible_dataset", "extensible_dataset",
|
||||
"Enhanced dataset functionality, used by other features.",
|
||||
B_FALSE, B_FALSE, B_FALSE, NULL);
|
||||
0, NULL);
|
||||
|
||||
static const spa_feature_t bookmarks_deps[] = {
|
||||
SPA_FEATURE_EXTENSIBLE_DATASET,
|
||||
@ -206,7 +205,7 @@ zpool_feature_init(void)
|
||||
zfeature_register(SPA_FEATURE_BOOKMARKS,
|
||||
"com.delphix:bookmarks", "bookmarks",
|
||||
"\"zfs bookmark\" command",
|
||||
B_TRUE, B_FALSE, B_FALSE, bookmarks_deps);
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, bookmarks_deps);
|
||||
|
||||
static const spa_feature_t filesystem_limits_deps[] = {
|
||||
SPA_FEATURE_EXTENSIBLE_DATASET,
|
||||
@ -214,13 +213,14 @@ zpool_feature_init(void)
|
||||
};
|
||||
zfeature_register(SPA_FEATURE_FS_SS_LIMIT,
|
||||
"com.joyent:filesystem_limits", "filesystem_limits",
|
||||
"Filesystem and snapshot limits.", B_TRUE, B_FALSE, B_FALSE,
|
||||
filesystem_limits_deps);
|
||||
"Filesystem and snapshot limits.",
|
||||
ZFEATURE_FLAG_READONLY_COMPAT, filesystem_limits_deps);
|
||||
|
||||
zfeature_register(SPA_FEATURE_EMBEDDED_DATA,
|
||||
"com.delphix:embedded_data", "embedded_data",
|
||||
"Blocks which compress very well use even less space.",
|
||||
B_FALSE, B_TRUE, B_TRUE, NULL);
|
||||
ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
|
||||
NULL);
|
||||
|
||||
static const spa_feature_t large_blocks_deps[] = {
|
||||
SPA_FEATURE_EXTENSIBLE_DATASET,
|
||||
@ -228,6 +228,6 @@ zpool_feature_init(void)
|
||||
};
|
||||
zfeature_register(SPA_FEATURE_LARGE_BLOCKS,
|
||||
"org.open-zfs:large_blocks", "large_blocks",
|
||||
"Support for blocks larger than 128KB.", B_FALSE, B_FALSE, B_FALSE,
|
||||
large_blocks_deps);
|
||||
"Support for blocks larger than 128KB.",
|
||||
ZFEATURE_FLAG_PER_DATASET, large_blocks_deps);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
@ -56,15 +56,23 @@ typedef enum spa_feature {
|
||||
|
||||
#define SPA_FEATURE_DISABLED (-1ULL)
|
||||
|
||||
typedef enum zfeature_flags {
|
||||
/* Can open pool readonly even if this feature is not supported. */
|
||||
ZFEATURE_FLAG_READONLY_COMPAT = (1 << 0),
|
||||
/* Is this feature necessary to read the MOS? */
|
||||
ZFEATURE_FLAG_MOS = (1 << 1),
|
||||
/* Activate this feature at the same time it is enabled. */
|
||||
ZFEATURE_FLAG_ACTIVATE_ON_ENABLE = (1 << 2),
|
||||
/* Each dataset has a field set if it has ever used this feature. */
|
||||
ZFEATURE_FLAG_PER_DATASET = (1 << 3)
|
||||
} zfeature_flags_t;
|
||||
|
||||
typedef struct zfeature_info {
|
||||
spa_feature_t fi_feature;
|
||||
const char *fi_uname; /* User-facing feature name */
|
||||
const char *fi_guid; /* On-disk feature identifier */
|
||||
const char *fi_desc; /* Feature description */
|
||||
boolean_t fi_can_readonly; /* Can open pool readonly w/o support? */
|
||||
boolean_t fi_mos; /* Is the feature necessary to read the MOS? */
|
||||
/* Activate this feature at the same time it is enabled */
|
||||
boolean_t fi_activate_on_enable;
|
||||
zfeature_flags_t fi_flags;
|
||||
/* array of dependencies, terminated by SPA_FEATURE_NONE */
|
||||
const spa_feature_t *fi_depends;
|
||||
} zfeature_info_t;
|
||||
|
@ -22,7 +22,9 @@
|
||||
#
|
||||
# Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2012 Joyent, Inc. All rights reserved.
|
||||
# Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
#
|
||||
#
|
||||
@ -36,6 +38,7 @@ ZFS_COMMON_OBJS += \
|
||||
blkptr.o \
|
||||
bpobj.o \
|
||||
bptree.o \
|
||||
bqueue.o \
|
||||
dbuf.o \
|
||||
ddt.o \
|
||||
ddt_zap.o \
|
||||
@ -65,6 +68,7 @@ ZFS_COMMON_OBJS += \
|
||||
lz4.o \
|
||||
lzjb.o \
|
||||
metaslab.o \
|
||||
multilist.o \
|
||||
range_tree.o \
|
||||
refcount.o \
|
||||
rrwlock.o \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -154,7 +154,7 @@ bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
int err;
|
||||
struct bptree_args *ba = arg;
|
||||
|
||||
if (BP_IS_HOLE(bp))
|
||||
if (bp == NULL || BP_IS_HOLE(bp))
|
||||
return (0);
|
||||
|
||||
err = ba->ba_func(ba->ba_arg, bp, ba->ba_tx);
|
||||
|
111
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bqueue.c
Normal file
111
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bqueue.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2014 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/bqueue.h>
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
static inline bqueue_node_t *
|
||||
obj2node(bqueue_t *q, void *data)
|
||||
{
|
||||
return ((bqueue_node_t *)((char *)data + q->bq_node_offset));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a blocking queue The maximum capacity of the queue is set to
|
||||
* size. Types that want to be stored in a bqueue must contain a bqueue_node_t,
|
||||
* and offset should give its offset from the start of the struct. Return 0 on
|
||||
* success, or -1 on failure.
|
||||
*/
|
||||
int
|
||||
bqueue_init(bqueue_t *q, uint64_t size, size_t node_offset)
|
||||
{
|
||||
list_create(&q->bq_list, node_offset + sizeof (bqueue_node_t),
|
||||
node_offset + offsetof(bqueue_node_t, bqn_node));
|
||||
cv_init(&q->bq_add_cv, NULL, CV_DEFAULT, NULL);
|
||||
cv_init(&q->bq_pop_cv, NULL, CV_DEFAULT, NULL);
|
||||
mutex_init(&q->bq_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
q->bq_node_offset = node_offset;
|
||||
q->bq_size = 0;
|
||||
q->bq_maxsize = size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a blocking queue. This function asserts that there are no
|
||||
* elements in the queue, and no one is blocked on the condition
|
||||
* variables.
|
||||
*/
|
||||
void
|
||||
bqueue_destroy(bqueue_t *q)
|
||||
{
|
||||
ASSERT0(q->bq_size);
|
||||
cv_destroy(&q->bq_add_cv);
|
||||
cv_destroy(&q->bq_pop_cv);
|
||||
mutex_destroy(&q->bq_lock);
|
||||
list_destroy(&q->bq_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add data to q, consuming size units of capacity. If there is insufficient
|
||||
* capacity to consume size units, block until capacity exists. Asserts size is
|
||||
* > 0.
|
||||
*/
|
||||
void
|
||||
bqueue_enqueue(bqueue_t *q, void *data, uint64_t item_size)
|
||||
{
|
||||
ASSERT3U(item_size, >, 0);
|
||||
ASSERT3U(item_size, <, q->bq_maxsize);
|
||||
mutex_enter(&q->bq_lock);
|
||||
obj2node(q, data)->bqn_size = item_size;
|
||||
while (q->bq_size + item_size > q->bq_maxsize) {
|
||||
cv_wait(&q->bq_add_cv, &q->bq_lock);
|
||||
}
|
||||
q->bq_size += item_size;
|
||||
list_insert_tail(&q->bq_list, data);
|
||||
cv_signal(&q->bq_pop_cv);
|
||||
mutex_exit(&q->bq_lock);
|
||||
}
|
||||
/*
|
||||
* Take the first element off of q. If there are no elements on the queue, wait
|
||||
* until one is put there. Return the removed element.
|
||||
*/
|
||||
void *
|
||||
bqueue_dequeue(bqueue_t *q)
|
||||
{
|
||||
void *ret;
|
||||
uint64_t item_size;
|
||||
mutex_enter(&q->bq_lock);
|
||||
while (q->bq_size == 0) {
|
||||
cv_wait(&q->bq_pop_cv, &q->bq_lock);
|
||||
}
|
||||
ret = list_remove_head(&q->bq_list);
|
||||
item_size = obj2node(q, ret)->bqn_size;
|
||||
q->bq_size -= item_size;
|
||||
mutex_exit(&q->bq_lock);
|
||||
cv_signal(&q->bq_add_cv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the space used is 0.
|
||||
*/
|
||||
boolean_t
|
||||
bqueue_empty(bqueue_t *q)
|
||||
{
|
||||
return (q->bq_size == 0);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user