aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib')
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs.abi32
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_diff.c6
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_pool.c36
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c63
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_util.c15
-rw-r--r--sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi26
-rw-r--r--sys/contrib/openzfs/lib/libzutil/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c299
8 files changed, 446 insertions, 32 deletions
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs.abi b/sys/contrib/openzfs/lib/libzfs/libzfs.abi
index 14e03ee28ffe..13ce19df9b34 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs.abi
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs.abi
@@ -99,6 +99,7 @@
<elf-symbol name='sa_validate_shareopts' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='snapshot_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='unshare_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zcmd_alloc_dst_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zcmd_expand_dst_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zcmd_free_nvlists' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -378,6 +379,7 @@
<elf-symbol name='zpool_vdev_path_to_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -5069,6 +5071,9 @@
<parameter type-id='9cf59a50'/>
<return type-id='48b5725f'/>
</function-decl>
+ <function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='mkdirp' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='d50d396c'/>
@@ -5858,6 +5863,11 @@
<parameter type-id='c19b74c3' name='istmp'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zpool_vdev_remove_wanted' mangled-name='zpool_vdev_remove_wanted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove_wanted'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='path'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_vdev_fault' mangled-name='zpool_vdev_fault' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_fault'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='9c313c2d' name='guid'/>
@@ -6098,7 +6108,7 @@
<array-type-def dimensions='1' type-id='b96825af' size-in-bits='64' id='13339fda'>
<subrange length='8' type-id='7359adad' id='56e0c0b1'/>
</array-type-def>
- <class-decl name='sendflags' size-in-bits='544' is-struct='yes' visibility='default' id='f6aa15be'>
+ <class-decl name='sendflags' size-in-bits='576' is-struct='yes' visibility='default' id='f6aa15be'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='verbosity' type-id='95e97e5e' visibility='default'/>
</data-member>
@@ -6130,24 +6140,27 @@
<var-decl name='progress' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='progressastitle' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='352'>
- <var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='compress' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='416'>
- <var-decl name='raw' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='compress' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='backup' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='raw' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='480'>
- <var-decl name='holds' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='backup' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='holds' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='544'>
<var-decl name='saved' type-id='c19b74c3' visibility='default'/>
</data-member>
</class-decl>
@@ -6728,6 +6741,11 @@
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
+ <function-decl name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='avl_insert' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='a3681dea'/>
<parameter type-id='eaa32e2f'/>
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
index b9698bb22b1f..cf625949fe32 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
@@ -56,10 +56,10 @@
#define ZDIFF_REMOVED '-'
#define ZDIFF_RENAMED "R"
-#define ZDIFF_ADDED_COLOR ANSI_GREEN
+#define ZDIFF_ADDED_COLOR ANSI_GREEN
#define ZDIFF_MODIFIED_COLOR ANSI_YELLOW
-#define ZDIFF_REMOVED_COLOR ANSI_RED
-#define ZDIFF_RENAMED_COLOR ANSI_BLUE
+#define ZDIFF_REMOVED_COLOR ANSI_RED
+#define ZDIFF_RENAMED_COLOR ANSI_BOLD_BLUE
/*
* Given a {dsname, object id}, get the object path
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
index e43ebb15c608..29f077841da0 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
@@ -3051,7 +3051,7 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
- if (avail_spare)
+ if (!(flags & ZFS_ONLINE_SPARE) && avail_spare)
return (zfs_error(hdl, EZFS_ISSPARE, msg));
if ((flags & ZFS_ONLINE_EXPAND ||
@@ -3159,6 +3159,40 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
}
/*
+ * Remove the specified vdev asynchronously from the configuration, so
+ * that it may come ONLINE if reinserted. This is called from zed on
+ * Udev remove event.
+ * Note: We also have a similar function zpool_vdev_remove() that
+ * removes the vdev from the pool.
+ */
+int
+zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path)
+{
+ zfs_cmd_t zc = {"\0"};
+ char errbuf[1024];
+ nvlist_t *tgt;
+ boolean_t avail_spare, l2cache;
+ libzfs_handle_t *hdl = zhp->zpool_hdl;
+
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
+
+ (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+ if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
+ NULL)) == NULL)
+ return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
+
+ zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
+
+ zc.zc_cookie = VDEV_STATE_REMOVED;
+
+ if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
+ return (0);
+
+ return (zpool_standard_error(hdl, errno, errbuf));
+}
+
+/*
* Mark the given vdev faulted.
*/
int
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
index 6a53571e3a87..8f496b20b89f 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
@@ -83,6 +83,9 @@ typedef struct progress_arg {
boolean_t pa_parsable;
boolean_t pa_estimate;
int pa_verbosity;
+ boolean_t pa_astitle;
+ boolean_t pa_progress;
+ uint64_t pa_size;
} progress_arg_t;
static int
@@ -712,6 +715,7 @@ typedef struct send_dump_data {
boolean_t seenfrom, seento, replicate, doall, fromorigin;
boolean_t dryrun, parsable, progress, embed_data, std_out;
boolean_t large_block, compress, raw, holds;
+ boolean_t progressastitle;
int outfd;
boolean_t err;
nvlist_t *fss;
@@ -904,6 +908,7 @@ send_progress_thread(void *arg)
zfs_handle_t *zhp = pa->pa_zhp;
uint64_t bytes;
uint64_t blocks;
+ uint64_t total = pa->pa_size / 100;
char buf[16];
time_t t;
struct tm *tm;
@@ -922,7 +927,7 @@ send_progress_thread(void *arg)
return ((void *)(uintptr_t)err);
}
- if (firstloop && !pa->pa_parsable) {
+ if (firstloop && !pa->pa_parsable && pa->pa_progress) {
(void) fprintf(stderr,
"TIME %s %sSNAPSHOT %s\n",
pa->pa_estimate ? "BYTES" : " SENT",
@@ -934,6 +939,17 @@ send_progress_thread(void *arg)
(void) time(&t);
tm = localtime(&t);
+ if (pa->pa_astitle) {
+ char buf_bytes[16];
+ char buf_size[16];
+ int pct;
+ zfs_nicenum(bytes, buf_bytes, sizeof (buf_bytes));
+ zfs_nicenum(pa->pa_size, buf_size, sizeof (buf_size));
+ pct = (total > 0) ? bytes / total : 100;
+ zfs_setproctitle("sending %s (%d%%: %s/%s)",
+ zhp->zfs_name, MIN(pct, 100), buf_bytes, buf_size);
+ }
+
if (pa->pa_verbosity >= 2 && pa->pa_parsable) {
(void) fprintf(stderr,
"%02d:%02d:%02d\t%llu\t%llu\t%s\n",
@@ -950,7 +966,7 @@ send_progress_thread(void *arg)
(void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
tm->tm_hour, tm->tm_min, tm->tm_sec,
(u_longlong_t)bytes, zhp->zfs_name);
- } else {
+ } else if (pa->pa_progress) {
zfs_nicebytes(bytes, buf, sizeof (buf));
(void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n",
tm->tm_hour, tm->tm_min, tm->tm_sec,
@@ -1114,12 +1130,15 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
* If progress reporting is requested, spawn a new thread to
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (sdd->progress) {
+ if (sdd->progress || sdd->progressastitle) {
pa.pa_zhp = zhp;
pa.pa_fd = sdd->outfd;
pa.pa_parsable = sdd->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = sdd->verbosity;
+ pa.pa_size = sdd->size;
+ pa.pa_astitle = sdd->progressastitle;
+ pa.pa_progress = sdd->progress;
if ((err = pthread_create(&tid, NULL,
send_progress_thread, &pa)) != 0) {
@@ -1131,7 +1150,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
fromorigin, sdd->outfd, flags, sdd->debugnv);
- if (sdd->progress) {
+ if (sdd->progress || sdd->progressastitle) {
void *status = NULL;
(void) pthread_cancel(tid);
(void) pthread_join(tid, &status);
@@ -1462,7 +1481,7 @@ lzc_flags_from_sendflags(const sendflags_t *flags)
static int
estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
uint64_t resumeobj, uint64_t resumeoff, uint64_t bytes,
- const char *redactbook, char *errbuf)
+ const char *redactbook, char *errbuf, uint64_t *sizep)
{
uint64_t size;
FILE *fout = flags->dryrun ? stdout : stderr;
@@ -1470,7 +1489,7 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
int err = 0;
pthread_t ptid;
- if (flags->progress) {
+ if (flags->progress || flags->progressastitle) {
pa.pa_zhp = zhp;
pa.pa_fd = fd;
pa.pa_parsable = flags->parsable;
@@ -1489,8 +1508,9 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
err = lzc_send_space_resume_redacted(zhp->zfs_name, from,
lzc_flags_from_sendflags(flags), resumeobj, resumeoff, bytes,
redactbook, fd, &size);
+ *sizep = size;
- if (flags->progress) {
+ if (flags->progress || flags->progressastitle) {
void *status = NULL;
(void) pthread_cancel(ptid);
(void) pthread_join(ptid, &status);
@@ -1505,6 +1525,9 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
}
}
+ if (!flags->progress && !flags->parsable)
+ return (err);
+
if (err != 0) {
zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
@@ -1638,6 +1661,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
uint64_t *redact_snap_guids = NULL;
int num_redact_snaps = 0;
char *redact_book = NULL;
+ uint64_t size = 0;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot resume send"));
@@ -1731,7 +1755,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
}
}
- if (flags->verbosity != 0) {
+ if (flags->verbosity != 0 || flags->progressastitle) {
/*
* Some of these may have come from the resume token, set them
* here for size estimate purposes.
@@ -1748,7 +1772,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
if (lzc_flags & LZC_SEND_FLAG_SAVED)
tmpflags.saved = B_TRUE;
error = estimate_size(zhp, fromname, outfd, &tmpflags,
- resumeobj, resumeoff, bytes, redact_book, errbuf);
+ resumeobj, resumeoff, bytes, redact_book, errbuf, &size);
}
if (!flags->dryrun) {
@@ -1758,12 +1782,15 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
* If progress reporting is requested, spawn a new thread to
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (flags->progress) {
+ if (flags->progress || flags->progressastitle) {
pa.pa_zhp = zhp;
pa.pa_fd = outfd;
pa.pa_parsable = flags->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = flags->verbosity;
+ pa.pa_size = size;
+ pa.pa_astitle = flags->progressastitle;
+ pa.pa_progress = flags->progress;
error = pthread_create(&tid, NULL,
send_progress_thread, &pa);
@@ -1780,7 +1807,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
if (redact_book != NULL)
free(redact_book);
- if (flags->progress) {
+ if (flags->progress || flags->progress) {
void *status = NULL;
(void) pthread_cancel(tid);
(void) pthread_join(tid, &status);
@@ -1790,6 +1817,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN,
"progress thread exited nonzero"));
+ zfs_close(zhp);
return (zfs_standard_error(hdl, error, errbuf));
}
}
@@ -2199,6 +2227,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sdd.verbosity = flags->verbosity;
sdd.parsable = flags->parsable;
sdd.progress = flags->progress;
+ sdd.progressastitle = flags->progressastitle;
sdd.dryrun = flags->dryrun;
sdd.large_block = flags->largeblock;
sdd.embed_data = flags->embed_data;
@@ -2410,6 +2439,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
char *name = zhp->zfs_name;
pthread_t ptid;
progress_arg_t pa = { 0 };
+ uint64_t size = 0;
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -2492,9 +2522,9 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
/*
* Perform size estimate if verbose was specified.
*/
- if (flags->verbosity != 0) {
+ if (flags->verbosity != 0 || flags->progressastitle) {
err = estimate_size(zhp, from, fd, flags, 0, 0, 0, redactbook,
- errbuf);
+ errbuf, &size);
if (err != 0)
return (err);
}
@@ -2506,12 +2536,15 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
* If progress reporting is requested, spawn a new thread to poll
* ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (flags->progress) {
+ if (flags->progress || flags->progressastitle) {
pa.pa_zhp = zhp;
pa.pa_fd = fd;
pa.pa_parsable = flags->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = flags->verbosity;
+ pa.pa_size = size;
+ pa.pa_astitle = flags->progressastitle;
+ pa.pa_progress = flags->progress;
err = pthread_create(&ptid, NULL,
send_progress_thread, &pa);
@@ -2525,7 +2558,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
err = lzc_send_redacted(name, from, fd,
lzc_flags_from_sendflags(flags), redactbook);
- if (flags->progress) {
+ if (flags->progress || flags->progressastitle) {
void *status = NULL;
(void) pthread_cancel(ptid);
(void) pthread_join(ptid, &status);
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c
index 8eb7582ba09a..7c4d310782eb 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c
@@ -2027,7 +2027,7 @@ zfs_version_print(void)
* Return 1 if the user requested ANSI color output, and our terminal supports
* it. Return 0 for no color.
*/
-static int
+int
use_color(void)
{
static int use_color = -1;
@@ -2073,10 +2073,11 @@ use_color(void)
}
/*
- * color_start() and color_end() are used for when you want to colorize a block
- * of text. For example:
+ * The functions color_start() and color_end() are used for when you want
+ * to colorize a block of text.
*
- * color_start(ANSI_RED_FG)
+ * For example:
+ * color_start(ANSI_RED)
* printf("hello");
* printf("world");
* color_end();
@@ -2084,7 +2085,7 @@ use_color(void)
void
color_start(const char *color)
{
- if (use_color()) {
+ if (color && use_color()) {
fputs(color, stdout);
fflush(stdout);
}
@@ -2099,7 +2100,9 @@ color_end(void)
}
}
-/* printf() with a color. If color is NULL, then do a normal printf. */
+/*
+ * printf() with a color. If color is NULL, then do a normal printf.
+ */
int
printf_color(const char *color, char *format, ...)
{
diff --git a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi
index c15cb3afbfca..1b03a5c42ef4 100644
--- a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi
+++ b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi
@@ -272,6 +272,8 @@
<elf-symbol name='zfs_niceraw' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_nicetime' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_resolve_shortname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_setproctitle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_setproctitle_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strcmp_pathname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -3340,6 +3342,30 @@
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
+ <abi-instr address-size='64' path='os/linux/zutil_setproctitle.c' language='LANG_C99'>
+ <function-decl name='warnx' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='setenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_setproctitle_init' mangled-name='zfs_setproctitle_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle_init'>
+ <parameter type-id='95e97e5e' name='argc'/>
+ <parameter type-id='9b23c9ad' name='argv'/>
+ <parameter type-id='9b23c9ad' name='envp'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_setproctitle' mangled-name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle'>
+ <parameter type-id='80f4b756' name='fmt'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ </abi-instr>
<abi-instr address-size='64' path='zutil_device_path.c' language='LANG_C99'>
<qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
diff --git a/sys/contrib/openzfs/lib/libzutil/Makefile.am b/sys/contrib/openzfs/lib/libzutil/Makefile.am
index f55b7798f1c0..0ddc241d6df9 100644
--- a/sys/contrib/openzfs/lib/libzutil/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzutil/Makefile.am
@@ -18,6 +18,7 @@ USER_C = \
if BUILD_LINUX
USER_C += \
+ os/linux/zutil_setproctitle.c \
os/linux/zutil_device_path_os.c \
os/linux/zutil_import_os.c \
os/linux/zutil_compat.c
diff --git a/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c b/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c
new file mode 100644
index 000000000000..4a6d12cf70cf
--- /dev/null
+++ b/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2013 Guillem Jover <guillem@hadrons.org>
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 <errno.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/param.h>
+#include <libzutil.h>
+
+static struct {
+ /* Original value. */
+ const char *arg0;
+
+ /* Title space available. */
+ char *base, *end;
+
+ /* Pointer to original nul character within base. */
+ char *nul;
+
+ boolean_t warned;
+ boolean_t reset;
+ int error;
+} SPT;
+
+#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/')
+#define SPT_MAXTITLE 255
+
+extern const char *__progname;
+
+static const char *
+getprogname(void)
+{
+ return (__progname);
+}
+
+static void
+setprogname(const char *progname)
+{
+ size_t i;
+
+ for (i = strlen(progname); i > 0; i--) {
+ if (LIBBSD_IS_PATHNAME_SEPARATOR(progname[i - 1])) {
+ __progname = progname + i;
+ return;
+ }
+ }
+ __progname = progname;
+}
+
+
+static inline size_t
+spt_min(size_t a, size_t b)
+{
+ return ((a < b) ? a : b);
+}
+
+/*
+ * For discussion on the portability of the various methods, see
+ * https://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
+ */
+static int
+spt_clearenv(void)
+{
+ char **tmp;
+
+ tmp = malloc(sizeof (*tmp));
+ if (tmp == NULL)
+ return (errno);
+
+ tmp[0] = NULL;
+ environ = tmp;
+
+ return (0);
+}
+
+static int
+spt_copyenv(int envc, char *envp[])
+{
+ char **envcopy;
+ char *eq;
+ int envsize;
+ int i, error;
+
+ if (environ != envp)
+ return (0);
+
+ /*
+ * Make a copy of the old environ array of pointers, in case
+ * clearenv() or setenv() is implemented to free the internal
+ * environ array, because we will need to access the old environ
+ * contents to make the new copy.
+ */
+ envsize = (envc + 1) * sizeof (char *);
+ envcopy = malloc(envsize);
+ if (envcopy == NULL)
+ return (errno);
+ memcpy(envcopy, envp, envsize);
+
+ error = spt_clearenv();
+ if (error) {
+ environ = envp;
+ free(envcopy);
+ return (error);
+ }
+
+ for (i = 0; envcopy[i]; i++) {
+ eq = strchr(envcopy[i], '=');
+ if (eq == NULL)
+ continue;
+
+ *eq = '\0';
+ if (setenv(envcopy[i], eq + 1, 1) < 0)
+ error = errno;
+ *eq = '=';
+
+ if (error) {
+ environ = envp;
+ free(envcopy);
+ return (error);
+ }
+ }
+
+ /*
+ * Dispose of the shallow copy, now that we've finished transfering
+ * the old environment.
+ */
+ free(envcopy);
+
+ return (0);
+}
+
+static int
+spt_copyargs(int argc, char *argv[])
+{
+ char *tmp;
+ int i;
+
+ for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
+ if (argv[i] == NULL)
+ continue;
+
+ tmp = strdup(argv[i]);
+ if (tmp == NULL)
+ return (errno);
+
+ argv[i] = tmp;
+ }
+
+ return (0);
+}
+
+void
+zfs_setproctitle_init(int argc, char *argv[], char *envp[])
+{
+ char *base, *end, *nul, *tmp;
+ int i, envc, error;
+
+ /* Try to make sure we got called with main() arguments. */
+ if (argc < 0)
+ return;
+
+ base = argv[0];
+ if (base == NULL)
+ return;
+
+ nul = base + strlen(base);
+ end = nul + 1;
+
+ for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
+ if (argv[i] == NULL || argv[i] != end)
+ continue;
+
+ end = argv[i] + strlen(argv[i]) + 1;
+ }
+
+ for (i = 0; envp[i]; i++) {
+ if (envp[i] != end)
+ continue;
+
+ end = envp[i] + strlen(envp[i]) + 1;
+ }
+ envc = i;
+
+ SPT.arg0 = strdup(argv[0]);
+ if (SPT.arg0 == NULL) {
+ SPT.error = errno;
+ return;
+ }
+
+ tmp = strdup(getprogname());
+ if (tmp == NULL) {
+ SPT.error = errno;
+ return;
+ }
+ setprogname(tmp);
+
+ error = spt_copyenv(envc, envp);
+ if (error) {
+ SPT.error = error;
+ return;
+ }
+
+ error = spt_copyargs(argc, argv);
+ if (error) {
+ SPT.error = error;
+ return;
+ }
+
+ SPT.nul = nul;
+ SPT.base = base;
+ SPT.end = end;
+}
+
+void
+zfs_setproctitle(const char *fmt, ...)
+{
+ /* Use buffer in case argv[0] is passed. */
+ char buf[SPT_MAXTITLE + 1];
+ va_list ap;
+ char *nul;
+ int len;
+ if (SPT.base == NULL) {
+ if (!SPT.warned) {
+ warnx("setproctitle not initialized, please"
+ "call zfs_setproctitle_init()");
+ SPT.warned = B_TRUE;
+ }
+ return;
+ }
+
+ if (fmt) {
+ if (fmt[0] == '-') {
+ /* Skip program name prefix. */
+ fmt++;
+ len = 0;
+ } else {
+ /* Print program name heading for grep. */
+ snprintf(buf, sizeof (buf), "%s: ", getprogname());
+ len = strlen(buf);
+ }
+
+ va_start(ap, fmt);
+ len += vsnprintf(buf + len, sizeof (buf) - len, fmt, ap);
+ va_end(ap);
+ } else {
+ len = snprintf(buf, sizeof (buf), "%s", SPT.arg0);
+ }
+
+ if (len <= 0) {
+ SPT.error = errno;
+ return;
+ }
+
+ if (!SPT.reset) {
+ memset(SPT.base, 0, SPT.end - SPT.base);
+ SPT.reset = B_TRUE;
+ } else {
+ memset(SPT.base, 0, spt_min(sizeof (buf), SPT.end - SPT.base));
+ }
+
+ len = spt_min(len, spt_min(sizeof (buf), SPT.end - SPT.base) - 1);
+ memcpy(SPT.base, buf, len);
+ nul = SPT.base + len;
+
+ if (nul < SPT.nul) {
+ *SPT.nul = '.';
+ } else if (nul == SPT.nul && nul + 1 < SPT.end) {
+ *SPT.nul = ' ';
+ *++nul = '\0';
+ }
+}