File s390-tools-sles15sp4-08-libutil-add-example-for-util_lockfile.patch of Package s390-tools.30980
Subject: [PATCH] [FEAT VS1822] libutil: add example for util_lockfile
From: Matthew Rosato <mjrosato@linux.ibm.com>
Summary: ap_tools: add ap-check and the ap device type to zdev
Description: This feature adds multiple components in support of persistent
configuration of vfio-ap mediated devices.
The ap-check utility is added as a callout function for the
mdevctl utility. This allows for meaningful error messages to be
presented to end-users when vfio-ap configuration errors are
detected while using mdevctl to create/modify vfio-ap mediated
devices.
Additionally, the 'ap' device type is added to zdev, providing a
command-line interface for managing the apmask and aqmask, which
determine what AP resources are available for vfio-ap usage.
'chzdev' is updated to allow for modifying the active masks as
well as to specify persistent mask values via a udev rule.
'lszdev' is updated to allow for querying of the active and
persistent mask values.
Upstream-ID: 6235a51d7c8c6019210e9be77973ff016c6d03e8
Problem-ID: VS1822
Upstream-Description:
libutil: add example for util_lockfile
Adds util_lockfile_example.c, which can be used to sample
util_lockfile support.
To acquire a lock using a parent PID (e.g. your shell instance):
util_lockfile_exmample -f <path> -l <retries>
To release the lock using the parent PID:
util_lockfile_example -f <path> -r
To acquire the lock, sleep briefly, and then release the lock
using the PID of the util_lockfile_example process:
util_lockfile_example -f <path> -L <retries>
In each example, the <path> is the location of the desired lockfile
and <retries> is the number of times to retry acquiring the lock
if it fails.
GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/issues/142
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
---
libutil/util_lockfile_example.c | 232 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 232 insertions(+)
--- /dev/null
+++ b/libutil/util_lockfile_example.c
@@ -0,0 +1,232 @@
+/**
+ * util_lockfile_example - Example program for util_lockfile
+ *
+ * Copyright IBM Corp. 2022
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+//! [code]
+#include <stdio.h>
+#include <stdlib.h>
+#include "lib/util_opt.h"
+#include "lib/util_prg.h"
+#include "lib/util_lockfile.h"
+
+static const struct util_prg prg = {
+ .desc = "Example for util_lockfile.",
+ .copyright_vec = { {
+ .owner = "IBM Corp.",
+ .pub_first = 2022,
+ .pub_last = 2022,
+ },
+ UTIL_PRG_COPYRIGHT_END }
+};
+
+static struct util_opt opt_vec[] = {
+ UTIL_OPT_SECTION("OPTIONS"),
+ {
+ .option = { "file", required_argument, NULL, 'f' },
+ .argument = "PATH",
+ .desc = "Use the specified path for a lockfile.",
+ },
+ {
+ .option = { "lock", required_argument, NULL, 'l' },
+ .argument = "RETRIES",
+ .desc = "Acquire the specified file lock using the parent "
+ "process id of this process. If not immediately "
+ "successful, retry for the specified number of times",
+ },
+ {
+ .option = { "release", 0, NULL, 'r' },
+ .desc = "Release the specified lock file using the parent "
+ "process id",
+ },
+ {
+ .option = { "lock-and-release", required_argument, NULL, 'L' },
+ .argument = "RETRIES",
+ .desc = "Acquire the specified file lock using this process "
+ "id, then release it. If not immediately successful, "
+ "retry for the specified number of times.",
+ },
+ UTIL_OPT_HELP,
+ UTIL_OPT_VERSION,
+ UTIL_OPT_END
+};
+
+enum prg_action {
+ ACTION_NONE = 0,
+ ACTION_LOCK,
+ ACTION_RELEASE,
+ ACTION_LOCK_AND_RELEASE,
+};
+
+static void print_single_action_error(void)
+{
+ warnx("Only a single action (--lock, --lock-parent, --release, "
+ "--release-parent) is allowed");
+}
+
+int main(int argc, char *argv[])
+{
+ enum prg_action action_id = ACTION_NONE;
+ int opt, rc, retries = 0;
+ char *endp, *path = NULL;
+
+ util_prg_init(&prg);
+ util_opt_init(opt_vec, NULL);
+
+ while (1) {
+ opt = util_opt_getopt_long(argc, argv);
+ if (opt == -1)
+ break;
+ switch (opt) {
+ case 'f':
+ path = optarg;
+ break;
+ case 'L':
+ if (action_id != ACTION_NONE) {
+ print_single_action_error();
+ return EXIT_FAILURE;
+ }
+ retries = strtol(optarg, &endp, 0);
+ if (*optarg == '\0' || *endp != '\0' || retries < 0) {
+ warnx("Invalid retry value for "
+ "--lock-and-release: '%s'",
+ optarg);
+ util_prg_print_parse_error();
+ return EXIT_FAILURE;
+ }
+ action_id = ACTION_LOCK_AND_RELEASE;
+ break;
+ case 'l':
+ if (action_id != ACTION_NONE) {
+ print_single_action_error();
+ return EXIT_FAILURE;
+ }
+ retries = strtol(optarg, &endp, 0);
+ if (*optarg == '\0' || *endp != '\0' || retries < 0) {
+ warnx("Invalid retry value for "
+ "--parent-lock: '%s'",
+ optarg);
+ util_prg_print_parse_error();
+ return EXIT_FAILURE;
+ }
+ action_id = ACTION_LOCK;
+ break;
+ case 'r':
+ if (action_id != ACTION_NONE) {
+ print_single_action_error();
+ return EXIT_FAILURE;
+ }
+ action_id = ACTION_RELEASE;
+ break;
+ case 'h':
+ util_prg_print_help();
+ util_opt_print_help();
+ exit(EXIT_SUCCESS);
+ case 'v':
+ util_prg_print_version();
+ exit(EXIT_SUCCESS);
+ default:
+ util_opt_print_parse_error(opt, argv);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (!path) {
+ warnx("--file is required, see --help for more information");
+ return EXIT_FAILURE;
+ }
+
+ if (action_id == ACTION_NONE) {
+ warnx("One of the following actions must be specified: "
+ "--lock, --release, --lock-and-release");
+ return EXIT_FAILURE;
+ }
+
+ /* Determine which util_lockfile function to call */
+ switch (action_id) {
+ case ACTION_LOCK:
+ rc = util_lockfile_parent_lock(path, retries);
+ switch (rc) {
+ case UTIL_LOCKFILE_OK:
+ printf("lock acquired successfully\n");
+ break;
+ case UTIL_LOCKFILE_LOCK_FAIL:
+ warnx("lock was not acquired; already held");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_ERR:
+ warnx("lock was not acquired; file error");
+ return EXIT_FAILURE;
+ default:
+ warnx("Unknown util_lockfile rc %d", rc);
+ return EXIT_FAILURE;
+ }
+ break;
+ case ACTION_RELEASE:
+ rc = util_lockfile_parent_release(path);
+ switch (rc) {
+ case UTIL_LOCKFILE_OK:
+ printf("lock released successfully\n");
+ break;
+ case UTIL_LOCKFILE_RELEASE_NONE:
+ warnx("lock file did not exist");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_RELEASE_FAIL:
+ warnx("lock was not held by the specified pid");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_ERR:
+ warnx("lock was not released; file error");
+ return EXIT_FAILURE;
+ default:
+ warnx("Unknown util_lockfile rc %d", rc);
+ return EXIT_FAILURE;
+ }
+ break;
+ case ACTION_LOCK_AND_RELEASE:
+ rc = util_lockfile_lock(path, retries);
+ switch (rc) {
+ case UTIL_LOCKFILE_OK:
+ printf("lock acquired successfully, holding for 2 seconds\n");
+ break;
+ case UTIL_LOCKFILE_LOCK_FAIL:
+ warnx("lock was not acquired; already held");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_ERR:
+ warnx("lock was not acquired; file error");
+ return EXIT_FAILURE;
+ default:
+ warnx("Unknown util_lockfile rc %d", rc);
+ return EXIT_FAILURE;
+ }
+ /* Briefly sleep while holding the lock */
+ sleep(2);
+ rc = util_lockfile_release(path);
+ switch (rc) {
+ case UTIL_LOCKFILE_OK:
+ printf("lock released successfully\n");
+ break;
+ case UTIL_LOCKFILE_RELEASE_NONE:
+ warnx("lock file did not exist");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_RELEASE_FAIL:
+ warnx("lock was not held by the specified pid");
+ return EXIT_FAILURE;
+ case UTIL_LOCKFILE_ERR:
+ warnx("lock was not released; file error");
+ return EXIT_FAILURE;
+ default:
+ warnx("Unknown util_lockfile rc %d", rc);
+ return EXIT_FAILURE;
+ }
+ break;
+ default:
+ warnx("Unknown util_lockfile action");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+//! [code]