diff options
Diffstat (limited to 'sys/contrib/openzfs/lib')
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs.abi | 32 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs_diff.c | 6 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs_pool.c | 36 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c | 63 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs_util.c | 15 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi | 26 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzutil/Makefile.am | 1 | ||||
| -rw-r--r-- | sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c | 299 |
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'; + } +} |
