Whamcloud - gitweb
EX-8543 tools: remove laudit/laudit-report
authorSebastien Buisson <sbuisson@ddn.com>
Tue, 7 Nov 2023 16:00:37 +0000 (17:00 +0100)
committerAndreas Dilger <adilger@whamcloud.com>
Thu, 9 Nov 2023 08:38:59 +0000 (08:38 +0000)
laudit/laudit-report is a demonstration tool for what is possible in
terms of Lustre audit. It is not meant to be used in production
because it stores the audit data as plaintext flat files, which is
both not secure and not scalable. And it is largely untested at scale.

So remove laudit/laudit-report from lipe sources, and fix build and
packaging mechanisms accordingly.

Test-Parameters: trivial
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I36fbd50cd4485f2cc7b0ee91922e58f92e008255
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/53015
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
14 files changed:
lipe/.gitignore
lipe/Makefile.am
lipe/configure.ac
lipe/laudit.conf.example [deleted file]
lipe/lipe.spec.in
lipe/man/laudit-report.1 [deleted file]
lipe/man/laudit.1 [deleted file]
lipe/man/laudit.conf.5 [deleted file]
lipe/src/Makefile.am
lipe/src/laudit-report.c [deleted file]
lipe/src/laudit.c [deleted file]
lustre/tests/Makefile.am
lustre/tests/sanity-laudit.sh [deleted file]
lustre/tests/test-groups/regression

index 07d48e8..da4922f 100644 (file)
@@ -12,8 +12,6 @@
 /src/ext4_inode2path
 /src/generate_definition
 /src/lamigo
-/src/laudit
-/src/laudit-report
 /src/ldumpstripe
 /src/lfill
 /src/lipe_expression_test
index 6398579..b98a119 100644 (file)
@@ -6,12 +6,6 @@ rpmbuild_opt =
 AUTOMAKE_OPTIONS = -Wall foreign
 ACLOCAL_AMFLAGS = ${ALOCAL_FLAGS}
 
-if BUILD_LAUDIT
-rpmbuild_opt += --with laudit
-else
-rpmbuild_opt += --without laudit
-endif
-
 if BUILD_SERVER
 rpmbuild_opt += --with server
 else
@@ -58,7 +52,6 @@ EXTRA_DIST= \
        lipe_purge \
        lipe-func.sh \
        lpcc.conf \
-       laudit.conf.example \
        pybuild/*.py \
        pylipe/.pylintrc \
        pylipe/*.py \
index c90947f..3851f00 100644 (file)
@@ -130,50 +130,6 @@ LIBS=$saved_libs
 AC_MSG_RESULT([$have_llapi_changelog_in_buf])
 AM_CONDITIONAL([BUILD_HOTPOOL_UTILS], [test x$have_llapi_changelog_in_buf = xyes])
 
-# -------- check for build laudit --------
-BUILD_LAUDIT="yes"
-NIDSTR=""
-AC_CHECK_HEADER([lnet/nidstr.h], NIDSTR="lnet", [], [
-AC_INCLUDES_DEFAULT
-#include <stdbool.h>
-])
-AS_IF([test "x$NIDSTR" = "xlnet" ],
-      [AC_DEFINE([HAVE_LNET_NIDSTR], [1], [lnet/nidstr.h exists]) lustre_user_dir="lustre"],
-      [AC_CHECK_HEADER([linux/lnet/nidstr.h], NIDSTR="linux", [], [
-AC_INCLUDES_DEFAULT
-#include <stdbool.h>
-])])
-AS_IF([test "x$NIDSTR" = "xlinux" ],
-      [AC_DEFINE([HAVE_LINUX_NIDSTR], [1], [linux/lnet/nidstr.h exists])] lustre_user_dir="linux/lustre")
-if test "x$NIDSTR" = "x"; then
-       AC_MSG_WARN([])
-       AC_MSG_WARN([nidstr include is needed for laudit. laudit will not be built.])
-       AC_MSG_WARN([])
-       BUILD_LAUDIT="no"
-fi
-
-if test "x$BUILD_LAUDIT" = "xyes"; then
-AC_MSG_CHECKING([whether Lustre is audit-capable])
-AC_COMPILE_IFELSE([AC_LANG_SOURCE([
-       #include <$lustre_user_dir/lustre_user.h>
-
-       int main(void) {
-               enum changelog_rec_type type1 = CL_GETXATTR;
-               enum changelog_rec_type type2 = CL_DN_OPEN;
-       }
-])],[audit_capable="yes"],[audit_capable="no"])
-AC_MSG_RESULT([$audit_capable])
-if test "x$audit_capable" = "xno"; then
-       AC_MSG_WARN([])
-       AC_MSG_WARN([Lustre must be audit-capable for laudit. laudit will not be built.])
-       AC_MSG_WARN([])
-       BUILD_LAUDIT="no"
-fi
-fi
-
-AC_SUBST(BUILD_LAUDIT)
-AM_CONDITIONAL(BUILD_LAUDIT, test "$BUILD_LAUDIT" = "yes")
-
 # -------- check for distro version --------
 AC_MSG_CHECKING([for distro version])
 DISTRO=$(sh detect-distro.sh)
diff --git a/lipe/laudit.conf.example b/lipe/laudit.conf.example
deleted file mode 100644 (file)
index aca7eb8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "fs_name": "testfs",
-    "mount": "/mnt/lustre/testfs",
-    "dump_path": "/mnt/audit",
-    "mdts": [
-      {"mdt_idx": 0, "reader_id": "cl1"},
-      {"mdt_idx": 1, "reader_id": "cl1"}
-    ],
-    "parse_interval_sec": 10,
-    "sync_every_n_entries": 1000,
-    "max_syncs_before_sleep": 10
-}
index ccaf3f6..9f2074a 100644 (file)
@@ -1,7 +1,6 @@
 # LIPE specfile
 
 # Declare rpmbuild --with/--without parameters
-%bcond_with laudit
 %bcond_with server
 %bcond_with zfs
 %bcond_with hotpool
@@ -232,12 +231,6 @@ cp \
 cp -a src/lipe_find3/lipe $RPM_BUILD_ROOT%{guile_site_dir}
 cp -a src/lipe_scan3/lipe $RPM_BUILD_ROOT%{guile_site_dir}
 
-%if %{with laudit}
-cp src/laudit \
-       src/laudit-report \
-       $RPM_BUILD_ROOT%{_bindir}
-%endif # laudit
-
 %if %{with hotpool}
 cp src/lamigo \
        src/lpurge \
@@ -257,11 +250,6 @@ cp -a \
        lipe.conf \
        $RPM_BUILD_ROOT%{_sysconfdir}
 
-%if %{with laudit}
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/laudit
-cp -a laudit.conf.example $RPM_BUILD_ROOT%{_sysconfdir}/laudit
-%endif # laudit
-
 %if %{with hotpool}
 cp -a example_configs/hotpool/* $RPM_BUILD_ROOT%{_sysconfdir}/
 %endif # hotpool
@@ -293,11 +281,6 @@ install -m 0644 man/lipe_find.1 $RPM_BUILD_ROOT%{_mandir}/man1/
 install -m 0644 man/lipe_scan.1 $RPM_BUILD_ROOT%{_mandir}/man1/
 install -m 0644 man/lipe_find3.1 $RPM_BUILD_ROOT%{_mandir}/man1/
 install -m 0644 man/lfill.1 $RPM_BUILD_ROOT%{_mandir}/man1/
-%if %{with laudit}
-install -m 0644 man/laudit.1 $RPM_BUILD_ROOT%{_mandir}/man1/
-install -m 0644 man/laudit-report.1 $RPM_BUILD_ROOT%{_mandir}/man1/
-install -m 0644 man/laudit.conf.5 $RPM_BUILD_ROOT%{_mandir}/man5/
-%endif # laudit
 %endif # server
 
 
@@ -348,14 +331,6 @@ rm -rf $RPM_BUILD_ROOT
 %files client
 %defattr(-,root,root)
 %{_bindir}/lipe_run_action
-%if %{with laudit}
-%{_bindir}/laudit
-%{_bindir}/laudit-report
-%{_sysconfdir}/laudit/laudit.conf.example
-%{_mandir}/man1/laudit.1*
-%{_mandir}/man1/laudit-report.1*
-%{_mandir}/man5/laudit.conf.5*
-%endif # laudit
 
 %files scan
 %defattr(-,root,root)
diff --git a/lipe/man/laudit-report.1 b/lipe/man/laudit-report.1
deleted file mode 100644 (file)
index 435d806..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" Manpage for laudit-report.
-.TH laudit 1 "7 March 2018" "1.0" "laudit-report man page"
-
-.SH NAME
-laudit-report \- Lustre audit report
-
-.SH SYNOPSIS
-.B laudit-report
-[ options ] <config file>
-
-.SH DESCRIPTION
-.B laudit-report
-is a command-line utility for Lustre audit report. More specifically,
-.B laudit-report
-is used to trigger typical queries on audit logs generated by laudit, like:
-.RS
-- What is the history of a given file: who created, then accessed the file?
-.PP
-- What data is manipulated by a given user: which files did the user access?
-.RE
-.PP
-.B laudit-report
-gives the ability to filter results by date, to speed up queries and limit the amount of information returned.
-.PP
-config file describes how to retrieve audit records to query. An example can be found at
-.I /etc/laudit/laudit.conf.example
-Please see the
-.BR laudit.conf (1)
-man page for details.
-
-.SH OPTIONS
-.TP
-.B -f, --file FILE
-Build report for given FILE
-.PP
-.RS
-You can provide file path or FID, and also simple file or directory name.
-.RE
-.TP
-.B -u, --user UID:GID
-Build report for given UID:GID.
-.TP
-.B -b, --before TIME
-Only consider events occurring before TIME, included.
-.PP
-.RS
-Time expected in the form 'yyyy.mm.dd HH:MM'.
-.RE
-.TP
-.B -a, --after TIME
-Only consider events occurring after TIME, included.
-.PP
-.RS
-Time expected in the form 'yyyy.mm.dd HH:MM'.
-.RE
-.TP
-.B -v, --verbose
-Output some debug info; repeat for more details.
-.TP
-.B -h,--help
-Print the usage
-
-.SH "SEE ALSO"
-.BR laudit (1)
-.BR laudit.conf (5)
-
-.SH BUGS
-No known bugs.
-
-.SH AUTHOR
-Sebastien Buisson <sbuisson@ddn.com>
diff --git a/lipe/man/laudit.1 b/lipe/man/laudit.1
deleted file mode 100644 (file)
index a816693..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" Manpage for laudit.
-.TH laudit 1 "7 March 2018" "1.0" "laudit man page"
-
-.SH NAME
-laudit \- Lustre audit
-
-.SH SYNOPSIS
-.B laudit
-[ options ] <config file>
-
-.SH DESCRIPTION
-.B laudit
-is a command-line utility for Lustre audit. More specifically,
-.B laudit
-is a dedicated Lustre Changelogs consumer, specific for auditing.
-.B laudit
-has to be launched from a Lustre client, and can run in the background. It processes Changelog entries (freeing space on Lustre metadata targets), and stores relevant audit logs under a predefined local directory, as flat files. So
-.B laudit
-does not rely on any complicated database schema.
-.PP
-Information is organized to ease two typical audit queries:
-.RS
-- What is the history of a given file: who created, then accessed the file?
-.PP
-- What data is manipulated by a given user: which files did the user access?
-.RE
-.PP
-.B laudit
-config file describes how to reach Lustre, as well as how to store audit records. An example can be found at
-.I /etc/laudit/laudit.conf.example
-Please see the
-.BR laudit.conf (1)
-man page for details.
-
-.SH OPTIONS
-.TP
-.B -d, --daemon
-Launch in daemon mode
-.PP
-.RS
-If specified, parse Changelogs regularly in the background, according to the interval specified in the config file.
-If not specified, just parse Changelogs once in the foreground.
-.RE
-.TP
-.B -p, --path
-Build path-to-fid info
-.PP
-.RS
-Resolve FID to path when parsing Changelogs, and dump info along with entry.
-.PP
-WARNING! This can cost extra time to process.
-.RE
-.TP
-.B -v, --verbose
-Output some debug info; repeat for more details.
-.TP
-.B -h,--help
-Print the usage
-
-.SH "SEE ALSO"
-.BR laudit-report (1)
-.BR laudit.conf (5)
-
-.SH BUGS
-No known bugs.
-
-.SH AUTHOR
-Sebastien Buisson <sbuisson@ddn.com>
diff --git a/lipe/man/laudit.conf.5 b/lipe/man/laudit.conf.5
deleted file mode 100644 (file)
index 2f4388e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" Manpage for laudit.conf.
-.TH laudit 1 "7 March 2018" "1.0" "laudit.conf man page"
-
-.SH NAME
-laudit.conf \- Lustre audit configuration file
-
-.SH DESCRIPTION
-.B laudit.conf
-is the laudit utility configuration file. It describes how to reach Lustre, as well as how to store audit records.
-Please see the
-.BR laudit (1)
-man page for more information.
-
-.SH SYNTAX
-.B laudit.conf
-is in JSON format.
-.PP
-.B fs_name
-gives the name of the file system to retrieve audit information from.
-.PP
-.B mount
-gives the mount path of the file system to retrieve audit information from.
-.PP
-.B dump_path
-is the path where to dump audit records.
-.PP
-.B mdts
-is a list of Lustre MDTs for the file system fs_name.
-.RS
-.B mdt_idx
-is the MDT index
-.PP
-.B reader_id
-is the Changelogs consumer name for this MDT.
-.RE
-.PP
-.B parse_interval_sec
-defines the interval in seconds at which the Changelogs are consumed when laudit is run in daemon mode.
-.PP
-.B sync_every_n_entries
-is the maximum number of Changelog entries that are processed before syncing to disk audit records stored under dump_path.
-.PP
-.B max_syncs_before_sleep
-limits the number of entries processed before interrupting the daemon. Process will resume after parse_interval_sec.
-
-.SH EXAMPLE
-Here is an example of laudit configuration file:
-.RS
-{
-    "fs_name": "testfs",
-    "mount": "/mnt/lustre/testfs",
-    "dump_path": "/mnt/audit",
-    "mdts": [
-      {"mdt_idx": 0, "reader_id": "cl1"},
-      {"mdt_idx": 1, "reader_id": "cl1"}
-    ],
-    "parse_interval_sec": 10,
-    "sync_every_n_entries": 1000,
-    "max_syncs_before_sleep": 10
-
-}
-.RE
-
-.SH "SEE ALSO"
-.BR laudit (1)
-.BR laudit-report (1)
-
-.SH AUTHOR
-Sebastien Buisson <sbuisson@ddn.com>
index 2be68ed..c27c8d8 100644 (file)
@@ -27,10 +27,6 @@ bin_PROGRAMS += \
 
 noinst_PROGRAMS += lipe_expression_test
 
-if BUILD_LAUDIT
-bin_PROGRAMS += laudit laudit-report
-endif
-
 if BUILD_HOTPOOL_UTILS
 bin_PROGRAMS += lamigo lpurge
 endif
@@ -90,12 +86,6 @@ lfill_LDADD = $(LIPE_LDADD)
 ldumpstripe_SOURCES = ldumpstripe.c lustre_ea.h lustre_ea.c debug.c debug.h
 ldumpstripe_LDADD = $(liblustre_LIBS)
 
-laudit_SOURCES = laudit.c
-laudit_LDADD = $(json_c_LIBS) $(liblustre_LIBS)
-
-laudit_report_SOURCES = laudit-report.c
-laudit_report_LDADD = $(json_c_LIBS) $(liblustre_LIBS)
-
 lipe_ssh_SOURCES = lipe_ssh.c lipe_ssh.h
 
 lamigo_SOURCES = lx_log.h lamigo.c lamigo.h lamigo_alr.c lamigo_hash.c lamigo_hash.h \
diff --git a/lipe/src/laudit-report.c b/lipe/src/laudit-report.c
deleted file mode 100644 (file)
index a21ca1b..0000000
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
- * Copyright (c) 2018 DDN Storage, Inc
- *
- * Author: Sebastien Buisson sbuisson@ddn.com
- */
-
-/*
- * lustre/utils/laudit-report.c
- * Report tool for audit.
- */
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dirent.h>
-
-#include <json-c/json.h>
-
-#include <lustre/lustreapi.h>
-
-#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
-#endif /* !ARRAY_SIZE */
-
-#define MDD_NAME_LEN 16
-
-struct mdt_desc {
-       char  reader_id[8];
-       char  mdd_name[MDD_NAME_LEN + 1];
-};
-
-#define MAX_MDTS 256
-struct audit_config {
-       char            fs_name[9];
-       char            mount[PATH_MAX + 1];
-       char            dump_path[PATH_MAX + 1];
-       int             parse_interval_sec;
-       int             sync_every_n_entries;
-       int             max_syncs_before_sleep;
-       int             nb_mdts;
-       struct mdt_desc mdts[MAX_MDTS];
-};
-
-static const char *progname;
-static struct audit_config cfg = { .mdts = { { .reader_id = "" } } };
-static bool config_init;
-static int verbose;
-static char config_file[PATH_MAX + 1];
-
-static unsigned int dir_level;
-static char *file_to_audit, *user_to_audit;
-static struct tm ts_before, ts_after;
-static bool check_before, check_after;
-
-void laudit_report_usage(void)
-{
-       printf("usage: %s [options] <config file>\n\n", progname);
-       printf("\toptions:\n");
-       printf("\t\t-f|--file <file>: build report for given file\n");
-       printf("\t\t\tYou can provide file path or FID, and also simple");
-       printf("file or directory name.\n");
-       printf("\t\t-u|--user <uid:gid>: build report for given user\n");
-       printf("\t\t-b|--before <time>: only consider events occurring ");
-       printf("before this time, included.\n");
-       printf("\t\t-a|--after <time>: only consider events occurring ");
-       printf("after this time, included.\n");
-       printf("\t\t\tTime expected in the form 'yyyy.mm.dd HH:MM'.\n");
-       printf("\t\t-v|--verbose: output some debug info; repeat for ");
-       printf("more details.\n");
-}
-
-void printerr(char *format, ...)
-{
-       va_list args;
-       char *fullpath = getcwd(NULL, 0);
-
-       va_start(args, format);
-
-       fprintf(stderr, "%s in %s: ", progname, fullpath);
-       vfprintf(stderr, format, args);
-
-       va_end(args);
-       free(fullpath);
-}
-
-void printinfo(char *format, ...)
-{
-       va_list args;
-
-       va_start(args, format);
-
-       vfprintf(stdout, format, args);
-
-       va_end(args);
-}
-
-/* config file is in JSON format, of the form:
- *   {
- *   "fs_name": "testfs",
- *   "mount": "/mnt/lustre/testfs",
- *   "dump_path": "/mnt/audit1",
- *   "mdts": [
- *     {"mdt_idx": "0", "reader_id": "cl1"},
- *     {"mdt_idx": "1", "reader_id": "cl2"}
- *   ],
- *   "parse_interval_sec": 60,
- *   "sync_every_n_entries": 500,
- *   "max_syncs_before_sleep": 10
- *   }
- */
-static int get_config(char *cfg_file)
-{
-       struct json_object *root, *fs_name, *mount, *dump_path, *mdts;
-       struct json_object *parse_interval_sec, *sync_every_n_entries;
-       struct json_object *max_syncs_before_sleep;
-       int i;
-       int rc = -EINVAL;
-
-       root = json_object_from_file(cfg_file);
-       if (!root) {
-               fprintf(stderr,
-                       "%s config error: %s is not in valid JSON format\n",
-                       progname, cfg_file);
-               return -EINVAL;
-       }
-
-       rc = json_object_object_get_ex(root, "fs_name", &fs_name);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a fs_name entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(fs_name, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: fs_name is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.fs_name, sizeof(cfg.fs_name), "%s",
-                    json_object_get_string(fs_name)) >= sizeof(cfg.fs_name)) {
-               fprintf(stderr,
-                       "%s config error: fs_name is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "mount", &mount);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a mount entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(mount, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: mount is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.mount, sizeof(cfg.mount), "%s",
-                    json_object_get_string(mount)) >= sizeof(cfg.mount)) {
-               fprintf(stderr,
-                       "%s config error: mount is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "dump_path", &dump_path);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a dump_path entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(dump_path, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: dump_path is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.dump_path, sizeof(cfg.dump_path), "%s",
-                    json_object_get_string(dump_path))
-           >= sizeof(cfg.dump_path)) {
-               fprintf(stderr,
-                       "%s config error: dump_path is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "mdts", &mdts);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have an mdts entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(mdts, json_type_array)) {
-               fprintf(stderr,
-                       "%s config error: mdts is not an array\n",
-                       progname);
-               goto out;
-       }
-
-       cfg.nb_mdts = json_object_array_length(mdts);
-       if (cfg.nb_mdts > ARRAY_SIZE(cfg.mdts)) {
-               fprintf(stderr,
-                       "%s error: mdts array is larger than %lu\n",
-                       progname,
-                       ARRAY_SIZE(cfg.mdts));
-               goto out;
-       }
-
-       for (i = 0; i < cfg.nb_mdts; i++) {
-               struct json_object *data, *mdt_idx, *reader_id;
-               int mdt_id;
-
-               data = json_object_array_get_idx(mdts, i);
-               if (!data) {
-                       fprintf(stderr,
-                               "%s config error: mdt %d is not an object\n",
-                               progname, i);
-                       goto out;
-               }
-
-               rc = json_object_object_get_ex(data, "mdt_idx", &mdt_idx);
-               if (!rc) {
-                       fprintf(stderr,
-                               "%s config error: %s does not have an mdt_idx entry\n",
-                               progname, cfg_file);
-                       goto out;
-               }
-               if (!json_object_is_type(mdt_idx, json_type_int)) {
-                       fprintf(stderr,
-                               "%s config error: mdt_idx is not an int\n",
-                               progname);
-                       goto out;
-               }
-               mdt_id = json_object_get_int(mdt_idx);
-               if (mdt_id < 0 || mdt_id >= MAX_MDTS) {
-                       fprintf(stderr,
-                               "%s config error: mdt_idx %d out of range\n",
-                               progname, mdt_id);
-                       goto out;
-               }
-
-               rc = json_object_object_get_ex(data, "reader_id", &reader_id);
-               if (!rc) {
-                       fprintf(stderr,
-                               "%s config error: %s does not have a reader_id entry\n",
-                               progname, cfg_file);
-                       goto out;
-               }
-               if (!json_object_is_type(reader_id, json_type_string)) {
-                       fprintf(stderr,
-                               "%s config error: reader_id is not a string\n",
-                               progname);
-                       goto out;
-               }
-               if (cfg.mdts[mdt_id].reader_id[0] != '\0') {
-                       fprintf(stderr,
-                               "%s config error: duplicate mdt index %d\n",
-                               progname, mdt_id);
-                       goto out;
-               }
-               if (snprintf(cfg.mdts[mdt_id].reader_id,
-                            sizeof(cfg.mdts[mdt_id].reader_id), "%s",
-                            json_object_get_string(reader_id)) >=
-                   sizeof(cfg.mdts[mdt_id].reader_id)) {
-                       fprintf(stderr,
-                               "%s config error: reader_id is too long\n",
-                               progname);
-                       goto out;
-               }
-       }
-
-       rc = json_object_object_get_ex(root, "parse_interval_sec",
-                                      &parse_interval_sec);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a parse_interval_sec entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(parse_interval_sec, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: parse_interval_sec is not an int\n",
-                       progname);
-               goto out;
-       }
-       cfg.parse_interval_sec = json_object_get_int(parse_interval_sec);
-
-       rc = json_object_object_get_ex(root, "sync_every_n_entries",
-                                      &sync_every_n_entries);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a sync_every_n_entries entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(sync_every_n_entries, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: sync_every_n_entries is not an int\n",
-                       progname);
-               goto out;
-       }
-       cfg.sync_every_n_entries = json_object_get_int(sync_every_n_entries);
-
-       rc = json_object_object_get_ex(root, "max_syncs_before_sleep",
-                                      &max_syncs_before_sleep);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a max_syncs_before_sleep entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(max_syncs_before_sleep, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: max_syncs_before_sleep is not an int\n",
-                       progname);
-               goto out;
-       }
-
-       cfg.max_syncs_before_sleep =
-               json_object_get_int(max_syncs_before_sleep);
-
-       rc = 0;
-out:
-       json_object_put(root);
-       return rc;
-}
-
-static void dump_config(void)
-{
-       int idx;
-
-       if (!config_init)
-               return;
-
-       printf("FS name: %s\n", cfg.fs_name);
-       printf("Mount path: %s\n", cfg.mount);
-       printf("Dump path: %s\n", cfg.dump_path);
-
-       for (idx = 0; idx < MAX_MDTS; idx++) {
-               if (cfg.mdts[idx].reader_id[0] == '\0')
-                       continue;
-               printf("MDT index: %d, reader ID %s\n",
-                      idx, cfg.mdts[idx].reader_id);
-       }
-
-       printf("Parse interval: %d\n", cfg.parse_interval_sec);
-       printf("Sync: every %d entries\n", cfg.sync_every_n_entries);
-       printf("Max syncs before sleep: %d\n", cfg.max_syncs_before_sleep);
-}
-
-static int sanity_config(void)
-{
-       struct stat s;
-       char path[PATH_MAX + 1];
-       int rc;
-
-       if (!config_init)
-               return -1;
-
-       /* check dump_path */
-       rc = stat(cfg.dump_path, &s);
-       if (rc == -1) {
-               fprintf(stderr, "%s: cannot stat %s: %s\n", progname,
-                       cfg.dump_path, strerror(errno));
-               return rc;
-       }
-       if (!S_ISDIR(s.st_mode)) {
-               fprintf(stderr, "%s: dump path %s: %s\n",
-                       progname, cfg.dump_path, strerror(errno = ENOTDIR));
-               return -1;
-       }
-
-       /* create /files and /users directories if necessary */
-       rc = snprintf(path, sizeof(path), "%s/files", cfg.dump_path);
-       if (rc >= sizeof(path))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc && errno != EEXIST) {
-               fprintf(stderr, "%s cannot mkdir %s: %s\n", progname,
-                       path, strerror(errno));
-               return rc;
-       }
-       rc = snprintf(path, sizeof(path), "%s/users", cfg.dump_path);
-       if (rc >= sizeof(path))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc && errno != EEXIST) {
-               fprintf(stderr, "%s cannot mkdir %s: %s\n", progname,
-                       path, strerror(errno));
-               return rc;
-       }
-
-       /* check parse_interval_sec */
-       if (cfg.parse_interval_sec <= 0) {
-               fprintf(stderr, "%s: parse_interval_sec %d invalid\n",
-                       progname, cfg.parse_interval_sec);
-               return -1;
-       }
-
-       /* sync_every_n_entries */
-       if (cfg.sync_every_n_entries <= 0) {
-               fprintf(stderr, "%s: sync_every_n_entries %d invalid\n",
-                       progname, cfg.sync_every_n_entries);
-               return -1;
-       }
-
-       /* max_syncs_before_sleep */
-       if (cfg.max_syncs_before_sleep <= 0) {
-               fprintf(stderr, "%s: max_syncs_before_sleep %d invalid\n",
-                       progname, cfg.max_syncs_before_sleep);
-               return -1;
-       }
-
-       return 0;
-}
-
-/* look for requested uid/gid in buffer */
-int filter_write(char *file_path, char *buf, size_t *buf_sz, char *uidgid)
-{
-       char *nl = NULL, *user = NULL, *remainder = NULL;
-       char *ptr = buf;
-       size_t len;
-       int rc;
-
-       /* first, find end of line */
-       while ((nl = memchr(ptr, '\n', *buf_sz)) != NULL) {
-               /* then, find u=uid:gid */
-               *nl = '\0';
-               user = strstr(ptr, "u=");
-               if (user == NULL) {
-                       printerr("malformed audit log in %s\n", file_path);
-                       return -EINVAL;
-               }
-               remainder = strchr(user + 2, ' ');
-               if (remainder == NULL) {
-                       printerr("malformed audit log in %s\n", file_path);
-                       return -EINVAL;
-               }
-               *remainder = '\0';
-               if (strcmp(user + 2, uidgid) == 0) {
-                       /* matches requested user, so dump entry
-                        * without uidgid info
-                        */
-                       *nl = '\n';
-                       len = user - ptr;
-                       rc = write(STDOUT_FILENO, ptr, len);
-                       if (rc != len) {
-                               printerr("cannot print %s content: %s\n",
-                                        file_path, strerror(errno));
-                               return -errno;
-                       }
-                       len = nl - remainder;
-                       rc = write(STDOUT_FILENO, remainder + 1, len);
-                       if (rc != len) {
-                               printerr("cannot print %s content: %s\n",
-                                        file_path, strerror(errno));
-                               return -errno;
-                       }
-               }
-               *buf_sz -= nl - ptr + 1;
-               ptr = nl + 1;
-       }
-
-       /* copy end of buffer into buf for future use */
-       if (*buf_sz != 0)
-               memcpy(buf, ptr, *buf_sz);
-
-       return 0;
-}
-
-int cat_file(char *file_path, char *uidgid)
-{
-       int fd;
-       char buf[4096];
-       size_t read_sz = 0;
-       int rc = 0;
-
-       fd = open(file_path, O_RDONLY);
-       if (fd == -1) {
-               printerr("cannot open %s: %s\n", file_path, strerror(errno));
-               return -1;
-       }
-
-       posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
-
-       while (true) {
-               rc = read(fd, buf + read_sz, sizeof(buf) - read_sz);
-               if (rc == -1) {
-                       printerr("cannot read from file %s: %s\n",
-                                file_path, strerror(errno));
-                       rc = -errno;
-                       break;
-               }
-
-               if (rc == 0)
-                       /* end of file */
-                       break;
-
-               read_sz += rc;
-
-               if (uidgid) {
-                       /* filter based on uid/gid */
-                       rc = filter_write(file_path, buf, &read_sz, uidgid);
-                       if (rc)
-                               break;
-               } else {
-                       /* bulk write */
-                       rc = write(STDOUT_FILENO, buf, read_sz);
-                       if (rc != read_sz) {
-                               printerr("cannot print %s content: %s\n",
-                                        file_path, strerror(errno));
-                               rc = -errno;
-                               break;
-                       }
-                       read_sz = 0;
-               }
-       }
-
-       close(fd);
-       return rc;
-}
-
-int filter_out_files_for_time(const struct dirent *de)
-{
-       int n, ret;
-
-       ret = sscanf(de->d_name, "%02d", &n);
-       if (ret < 0)
-               return 0;
-       return ret;
-}
-
-int browse_dir_depth_first(char *dir, char *uidgid)
-{
-       struct dirent **namelist;
-       struct stat s;
-       int n, idx = 0;
-       bool check_before_orig = check_before;
-       bool check_after_orig = check_after;
-       int rc = 0;
-
-       if (chdir(dir)) {
-               printerr("cannot chdir to %s: %s\n", dir, strerror(errno));
-               rc = -errno;
-               return rc;
-       }
-
-       n = scandir(".", &namelist, filter_out_files_for_time, alphasort);
-       if (n < 0) {
-               printerr("cannot scan dir %s: %s\n", dir, strerror(errno));
-               rc = -errno;
-               return rc;
-       }
-
-       dir_level++;
-
-       for (idx = 0; idx < n; idx++) {
-               /* In case of error, need to go through whole loop
-                * to free memory.
-                */
-               if (rc)
-                       goto loop_free;
-
-               rc = stat(namelist[idx]->d_name, &s);
-               if (rc == -1) {
-                       printerr("cannot stat %s: %s\n", namelist[idx]->d_name,
-                                strerror(errno));
-                       rc = -errno;
-                       goto loop_free;
-               }
-
-               if (S_ISDIR(s.st_mode)) {
-                       if (check_before || check_after) {
-                               int val, val_before, val_after;
-
-                               val = atoi(namelist[idx]->d_name);
-                               switch (dir_level) {
-                               case 1:
-                                       val_before = ts_before.tm_year + 1900;
-                                       val_after = ts_after.tm_year + 1900;
-                                       break;
-                               case 2:
-                                       val_before = ts_before.tm_mon + 1;
-                                       val_after = ts_after.tm_mon + 1;
-                                       break;
-                               case 3:
-                                       val_before = ts_before.tm_mday;
-                                       val_after = ts_after.tm_mday;
-                                       break;
-                               case 4:
-                                       val_before = ts_before.tm_hour * 100 +
-                                               ts_before.tm_min;
-                                       val_after = ts_after.tm_hour * 100 +
-                                               ts_after.tm_min;
-                                       break;
-                               default:
-                                       /* unknown dir level */
-                                       printerr("unknown dir lvl %d for %s\n",
-                                                dir_level,
-                                                namelist[idx]->d_name);
-                                       rc = -EINVAL;
-                                       goto loop_free;
-                               }
-
-                               if (check_before) {
-                                       if (val < val_before)
-                                               /* time constraint is validated,
-                                                * no need to check sub levels
-                                                */
-                                               check_before = false;
-                                       else if (val > val_before)
-                                               /* time does not fit constraint,
-                                                * skip
-                                                */
-                                               goto loop_free;
-                               }
-                               if (check_after) {
-                                       if (val > val_after)
-                                               /* time constraint is validated,
-                                                * no need to check sub levels
-                                                */
-                                               check_after = false;
-                                       else if (val < val_after)
-                                               /* time does not fit constraint,
-                                                * skip
-                                                */
-                                               goto loop_free;
-                               }
-                       }
-
-                       /* recursively call browse_dir */
-                       rc = browse_dir_depth_first(namelist[idx]->d_name,
-                                                   uidgid);
-               } else if (S_ISREG(s.st_mode)) {
-                       /* display content of file */
-                       rc = cat_file(namelist[idx]->d_name, uidgid);
-               }
-
-loop_free:
-               /* restore original check values */
-               check_before = check_before_orig;
-               check_after = check_after_orig;
-
-               free(namelist[idx]);
-       }
-       free(namelist);
-
-       if (!rc && chdir("..")) {
-               printerr("cannot chdir to .. : %s\n", strerror(errno));
-               rc = -errno;
-       }
-
-       dir_level--;
-       return rc;
-}
-
-static int get_audit_for_file(char *fid, char *uidgid)
-{
-       char main_dir[PATH_MAX + 1];
-       struct stat s;
-       int rc;
-
-       /* directory structure for easy file history:
-        * files/$FID/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/files/%s",
-                     cfg.dump_path, fid);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-
-       rc = stat(main_dir, &s);
-       if (rc == -1) {
-               fprintf(stderr, "%s: file %s does not exist in history\n",
-                       progname, fid);
-               rc = -errno;
-               return rc;
-       }
-
-       /* directory structure is like:
-        * main_dir/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-       printinfo("\nHistory of file %s", fid);
-       if (uidgid)
-               printinfo(" by user %s:\n", uidgid);
-       else
-               printinfo(":\n");
-       return browse_dir_depth_first(main_dir, uidgid);
-}
-
-static int get_audit_for_user(char *uidgid)
-{
-       char main_dir[PATH_MAX + 1];
-       struct stat s;
-       int rc;
-
-       /* directory structure for easy file history:
-        * files/$FID/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/users/%s",
-                     cfg.dump_path, uidgid);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-
-       rc = stat(main_dir, &s);
-       if (rc == -1) {
-               fprintf(stderr, "%s: user %s does not exist in history\n",
-                       progname, uidgid);
-               rc = -errno;
-               return rc;
-       }
-
-       /* directory structure is like:
-        * main_dir/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-       printinfo("\nHistory of user %s:\n", uidgid);
-       return browse_dir_depth_first(main_dir, NULL);
-}
-
-int browse_files_fid(char *file_to_audit, bool use_as_basename)
-{
-       char main_dir[PATH_MAX + 1];
-       DIR *dp;
-       struct dirent *ep;
-       bool matches = false;
-       FILE *fp;
-       char *line = NULL;
-       size_t len = 0;
-       ssize_t read;
-       int rc = 0;
-
-       if (use_as_basename)
-               printinfo("Possible matches:\n");
-
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/files", cfg.dump_path);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("error with snprintf: %d\n", strerror(-rc));
-               return rc;
-       }
-       rc = 0;
-
-       if (chdir(main_dir)) {
-               printerr("cannot chdir to %s: %s\n", main_dir, strerror(errno));
-               rc = errno;
-               return rc;
-       }
-
-       dp = opendir(".");
-       if (dp == NULL) {
-               printerr("cannot open dir %s: %s\n", main_dir, strerror(errno));
-               rc = errno;
-               return rc;
-       }
-
-       while ((ep = readdir(dp)) != NULL) {
-               if (strcmp(ep->d_name, ".") == 0 ||
-                   strcmp(ep->d_name, "..") == 0)
-                       continue;
-
-               if (chdir(ep->d_name))
-                       continue;
-
-               fp = fopen("paths", "r");
-               if (fp == NULL) {
-                       chdir(main_dir);
-                       continue;
-               }
-
-               while ((read = getline(&line, &len, fp)) != -1) {
-                       if (line[read - 1] == '\n')
-                               line[read - 1] = '\0';
-                       if (strlen(line) == 0)
-                               continue;
-
-                       if (use_as_basename) {
-                               char *base = basename(line);
-
-                               if (strcmp(file_to_audit, base) == 0) {
-                                       matches = true;
-                                       printinfo("\t%s %s/%s\n", ep->d_name,
-                                                 cfg.mount, line);
-                                       break;
-                               }
-                       } else {
-                               if (strcmp(line, file_to_audit +
-                                          strlen(cfg.mount) + 1) == 0) {
-                                       rc = get_audit_for_file(ep->d_name,
-                                                               user_to_audit);
-                                       break;
-                               }
-                       }
-               }
-
-               fclose(fp);
-               if (line) {
-                       free(line);
-                       line = NULL;
-               }
-
-               chdir(main_dir);
-       }
-       closedir(dp);
-
-       if (use_as_basename && !matches)
-               printinfo("\tNone\n");
-
-       return rc;
-}
-
-/* need to resolve path to fid */
-/* strategy:
- * 1. resolve using path2fid: works for current path of
- *    existing file
- * 2. look into 'paths' files under files/$FID/ : works
- *    for path at create or mv or rm time
- * 3. look into 'paths' files for basename of file to find,
- *    and display a list of possibilities with full path and FID
- */
-int find_fid_and_get_audit(char *file_to_audit, char *user_to_audit)
-{
-       struct lu_fid fid;
-       char fid_to_audit[PATH_MAX];
-       char main_dir[PATH_MAX + 1];
-       int rc = 0;
-
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/", cfg.mount);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("error with snprintf: %d\n", strerror(-rc));
-               goto out_audit;
-       }
-
-       if (strlen(file_to_audit) >= strlen(main_dir) &&
-           strncmp(file_to_audit, main_dir, strlen(main_dir)) == 0) {
-               /* 1. resolve using path2fid */
-               rc = llapi_path2fid(file_to_audit, &fid);
-               if (rc == 0) {
-                       snprintf(fid_to_audit, sizeof(fid_to_audit), DFID,
-                                PFID(&fid));
-                       rc = get_audit_for_file(fid_to_audit, user_to_audit);
-                       if (rc)
-                               goto out_audit;
-               }
-
-               /* 2. look into 'paths' files under files/$FID/ */
-               rc = browse_files_fid(file_to_audit, false);
-       } else {
-               if (file_to_audit[0] == '/') {
-                       printerr("Invalid parameter for '--file' option: %s\n",
-                                file_to_audit);
-                       rc = EINVAL;
-               } else {
-                       /* 3. look into basename of 'paths' files for file to
-                        *    find, and display a list of possibilities with
-                        *    full path and FID
-                        */
-                       /* Consider file_to_audit as a filename or dirname
-                        * without path
-                        */
-                       rc = browse_files_fid(file_to_audit, true);
-               }
-       }
-
-out_audit:
-       return rc;
-}
-
-int get_opts(int argc, char *const argv[])
-{
-       static struct option long_opts[] = {
-               { .val = 'f', .name =  "file",    .has_arg = required_argument},
-               { .val = 'u', .name =  "user",    .has_arg = required_argument},
-               { .val = 'b', .name =  "before",  .has_arg = required_argument},
-               { .val = 'a', .name =  "after",   .has_arg = required_argument},
-               { .val = 'v', .name =  "verbose", .has_arg = no_argument},
-               { .name = NULL } };
-       char *short_opts = "f:u:b:a:v";
-       int opt;
-       int longidx;
-       unsigned int uid, gid;
-       char *time_before = NULL, *time_after = NULL;
-
-       optind = 0;
-       while ((opt = getopt_long(argc, argv, short_opts, long_opts,
-                                 &longidx)) != EOF) {
-               switch (opt) {
-               case 'f':
-                       file_to_audit = optarg;
-                       break;
-               case 'u':
-                       user_to_audit = optarg;
-                       break;
-               case 'b':
-                       time_before = optarg;
-                       break;
-               case 'a':
-                       time_after = optarg;
-                       break;
-               case 'v':
-                       verbose++;
-                       break;
-               default:
-                       if (opt != '?')
-                               fprintf(stderr, "Unknown option '%c'\n", opt);
-                       return -EINVAL;
-               }
-       }
-
-       if (optind == argc ||
-           (file_to_audit == NULL && user_to_audit == NULL)) {
-               /* The user didn't specify config file */
-               fprintf(stderr, "Not enough arguments\n");
-               return -EINVAL;
-       }
-
-       /*  The config file */
-       strncpy(config_file, argv[argc - 1], sizeof(config_file) - 1);
-       config_file[sizeof(config_file) - 1] = '\0';
-
-       if (user_to_audit && sscanf(user_to_audit, "%u:%u", &uid, &gid) != 2) {
-               /* incorrect uid:gid provided */
-               fprintf(stderr, "Incorrect uid:gid provided\n");
-               return -EINVAL;
-       }
-
-       if (time_before) {
-               if (!strptime(time_before, "%Y.%m.%d %H:%M", &ts_before)) {
-                       /* incorrect 'before time' provided */
-                       fprintf(stderr, "Incorrect 'before time' provided\n");
-                       return -EINVAL;
-               }
-               check_before = true;
-       }
-
-       if (time_after) {
-               if (!strptime(time_after, "%Y.%m.%d %H:%M", &ts_after)) {
-                       /* incorrect 'after time' provided */
-                       fprintf(stderr, "Incorrect 'after time' provided\n");
-                       return -EINVAL;
-               }
-               check_after = true;
-       }
-
-       if (time_before && time_after &&
-           mktime(&ts_before) < mktime(&ts_after)) {
-               /* incorrect time range provided */
-               fprintf(stderr, "Incorrect time range provided\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int main(int argc, char **argv)
-{
-       int idx;
-       int rc;
-
-       progname = argv[0]; /* Used in error messages */
-
-       if (argc < 3 || argv[argc - 1][0] == '-') {
-               fprintf(stderr, "%s, missing options\n", argv[0]);
-               laudit_report_usage();
-               return -EINVAL;
-       }
-
-       setlinebuf(stdout);
-
-       rc = get_opts(argc, argv);
-       if (rc) {
-               laudit_report_usage();
-               goto out_main;
-       }
-
-       rc = get_config(config_file);
-       if (rc)
-               goto out_main;
-       config_init = true;
-
-       if (verbose)
-               dump_config();
-
-       rc = sanity_config();
-       if (rc)
-               goto out_main;
-
-       for (idx = 0; idx < MAX_MDTS; idx++) {
-               if (cfg.mdts[idx].reader_id[0] == '\0')
-                       continue;
-               rc = snprintf(cfg.mdts[idx].mdd_name, MDD_NAME_LEN + 1,
-                             "%s-MDT%04x", cfg.fs_name, idx);
-               if (rc >= MDD_NAME_LEN + 1) {
-                       rc = EINVAL;
-                       break;
-               }
-               if (rc < 0)
-                       break;
-       }
-
-       if (file_to_audit) {
-               if (*file_to_audit == '[') {
-                       struct lu_fid fid;
-
-                       rc = sscanf(file_to_audit, "["SFID"]", RFID(&fid));
-                       if (rc != 3) {
-                               printerr("'%s' is not a valid FID\n",
-                                        file_to_audit);
-                               rc = EINVAL;
-                       } else {
-                               rc = get_audit_for_file(file_to_audit,
-                                                       user_to_audit);
-                       }
-               } else {
-                       rc = find_fid_and_get_audit(file_to_audit,
-                                                   user_to_audit);
-               }
-       } else if (user_to_audit) {
-               rc = get_audit_for_user(user_to_audit);
-       }
-
-out_main:
-       return rc < 0 ? -rc : rc;
-}
diff --git a/lipe/src/laudit.c b/lipe/src/laudit.c
deleted file mode 100644 (file)
index 23c43a8..0000000
+++ /dev/null
@@ -1,1579 +0,0 @@
-/*
- * Copyright (c) 2018 DDN Storage, Inc
- *
- * Author: Sebastien Buisson sbuisson@ddn.com
- */
-
-/*
- * lustre/utils/laudit.c
- * Changelogs consumer for audit.
- */
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <time.h>
-#include <signal.h>
-#include <syslog.h>
-
-#include <json-c/json.h>
-
-#include <lustre/lustreapi.h>
-#ifdef HAVE_LNET_NIDSTR
-#include <lnet/nidstr.h>
-#elif defined(HAVE_LINUX_NIDSTR)
-#include <linux/lnet/nidstr.h>
-#endif
-
-#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
-#endif /* !ARRAY_SIZE */
-
-#define MDD_NAME_LEN 16
-
-/* If we have include under $includedir/lnet, it means we are building against
- * Lustre 2.10 or earlier, so MDS_FMODE_{READ,WRITE} is not defined.
- */
-#ifdef HAVE_LNET_NIDSTR
-#define MDS_FMODE_READ FMODE_READ
-#define MDS_FMODE_WRITE FMODE_WRITE
-#endif
-
-struct mdt_desc {
-       char  reader_id[8];
-       char  mdd_name[MDD_NAME_LEN + 1];
-};
-
-#define MAX_MDTS 256
-struct audit_config {
-       char            fs_name[9];
-       char            mount[PATH_MAX + 1];
-       char            dump_path[PATH_MAX + 1];
-       int             parse_interval_sec;
-       int             sync_every_n_entries;
-       int             max_syncs_before_sleep;
-       int             nb_mdts;
-       struct mdt_desc mdts[MAX_MDTS];
-};
-
-static const char *progname;
-static struct audit_config cfg = { .mdts = { { .reader_id = "" } } };
-static bool config_init;
-static int verbose;
-static char config_file[PATH_MAX + 1];
-static int daemon_mode;
-static bool path2fid;
-/* __atomic_always_lock_free returns true for bool */
-static bool stop_now;
-static bool warn_possible_fid2path_error;
-
-void laudit_usage(void)
-{
-       printf("usage: %s [options] <config file>\n\n", progname);
-       printf("\toptions:\n");
-       printf("\t\t-d|--daemon: launch in daemon mode\n");
-       printf("\t\t\tIf specified, parse Changelogs regularly in the ");
-       printf("background,\n\t\t\taccording to the interval specified ");
-       printf("in the config file.\n");
-       printf("\t\t\tIf not specified, just parse Changelogs once in ");
-       printf("the foreground.\n");
-       printf("\t\t-p|--path: build path-to-fid info\n");
-       printf("\t\t\tIf specified, resolve FID to path when parsing ");
-       printf("Changelogs,\n\t\t\tand dump info along with entry.\n");
-       printf("\t\t-v|--verbose: output some debug info; repeat for ");
-       printf("more details.\n");
-}
-
-void printerr(char *format, ...)
-{
-       va_list args;
-
-       va_start(args, format);
-
-       if (daemon_mode)
-               vsyslog(LOG_ERR, format, args);
-       else
-               vfprintf(stderr, format, args);
-
-       va_end(args);
-}
-
-void printinfo(char *format, ...)
-{
-       va_list args;
-
-       va_start(args, format);
-
-       if (daemon_mode)
-               vsyslog(LOG_INFO, format, args);
-       else
-               vfprintf(stdout, format, args);
-
-       va_end(args);
-}
-
-int sync_audit(void)
-{
-       int rc = 0;
-       int root = open(cfg.dump_path, O_RDONLY);
-
-       if (root == -1) {
-               printerr("%s cannot open %s for sync: %s\n",
-                        progname, cfg.dump_path, strerror(errno));
-               return -errno;
-       }
-
-       if (syncfs(root) < 0) {
-               printerr("%s cannot sync %s: %s\n",
-                        progname, cfg.dump_path, strerror(errno));
-               rc = -errno;
-       }
-
-       close(root);
-       return rc;
-}
-
-int sync_n_clear(int idx, __u64 last_cr_index)
-{
-       int rc;
-
-       /* sanity check */
-       if (cfg.mdts[idx].reader_id[0] == '\0')
-               return 0;
-
-       /* sync audit dump device */
-       rc = sync_audit();
-       if (rc) {
-               printerr("%s error: cannot sync %s\n",
-                        progname, cfg.dump_path);
-               return rc;
-       }
-
-       /* clear entry */
-       rc = llapi_changelog_clear(cfg.mdts[idx].mdd_name,
-                                  cfg.mdts[idx].reader_id,
-                                  last_cr_index);
-       if (rc == -EINVAL)
-               printerr("%s: %s: record out of range: %u\n",
-                        progname, cfg.mdts[idx].mdd_name, 0);
-       else if (rc == -ENOENT)
-               printerr("%s: %s: no changelog user: %s\n",
-                        progname, cfg.mdts[idx].mdd_name,
-                        cfg.mdts[idx].reader_id);
-       else if (rc)
-               printerr("%s error: %s: %s\n", progname,
-                        cfg.mdts[idx].mdd_name, strerror(-rc));
-
-       if (verbose)
-               printinfo("%s cleared record %d on %s\n", progname,
-                         last_cr_index, cfg.mdts[idx].mdd_name);
-       return rc;
-}
-
-void sig_ignore(int signal)
-{
-       /* don't exit on signal */
-       printinfo("%s %s received signal %d... Ignoring.\n", progname,
-                 (signal == SIGINT || signal == SIGTERM) ? "child" : "",
-                 signal);
-}
-
-void sig_stop_parsing(int signal)
-{
-       /* just indicate we have to stop */
-       printinfo("%s received signal %d, will stop after current entry is processed...\n",
-                 progname, signal);
-
-       stop_now = true;
-}
-
-/* config file is in JSON format, of the form:
- *   {
- *   "fs_name": "mylustre",
- *   "mount": "/mnt/lustre/testfs",
- *   "dump_path": "/mnt/audit1",
- *   "mdts": [
- *     {"mdt_idx": "0", "reader_id": "cl1"},
- *     {"mdt_idx": "1", "reader_id": "cl2"}
- *   ],
- *   "parse_interval_sec": 60,
- *   "sync_every_n_entries": 500,
- *   "max_syncs_before_sleep": 10
- *   }
- */
-static int get_config(char *cfg_file)
-{
-       struct json_object *root, *fs_name, *mount, *dump_path, *mdts;
-       struct json_object *parse_interval_sec, *sync_every_n_entries;
-       struct json_object *max_syncs_before_sleep;
-       int i;
-       int rc = -EINVAL;
-
-       root = json_object_from_file(cfg_file);
-       if (!root) {
-               fprintf(stderr,
-                       "%s config error: %s is not in valid JSON format\n",
-                       progname, cfg_file);
-               return -EINVAL;
-       }
-
-       rc = json_object_object_get_ex(root, "fs_name", &fs_name);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a fs_name entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(fs_name, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: fs_name is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.fs_name, sizeof(cfg.fs_name), "%s",
-                    json_object_get_string(fs_name)) >= sizeof(cfg.fs_name)) {
-               fprintf(stderr,
-                       "%s config error: fs_name is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "mount", &mount);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a mount entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(mount, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: mount is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.mount, sizeof(cfg.mount), "%s",
-                    json_object_get_string(mount)) >= sizeof(cfg.mount)) {
-               fprintf(stderr,
-                       "%s config error: mount is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "dump_path", &dump_path);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a dump_path entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(dump_path, json_type_string)) {
-               fprintf(stderr,
-                       "%s config error: dump_path is not a string\n",
-                       progname);
-               goto out;
-       }
-       if (snprintf(cfg.dump_path, sizeof(cfg.dump_path), "%s",
-                    json_object_get_string(dump_path))
-           >= sizeof(cfg.dump_path)) {
-               fprintf(stderr,
-                       "%s config error: dump_path is too long\n",
-                       progname);
-               goto out;
-       }
-
-       rc = json_object_object_get_ex(root, "mdts", &mdts);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have an mdts entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(mdts, json_type_array)) {
-               fprintf(stderr,
-                       "%s config error: mdts is not an array\n",
-                       progname);
-               goto out;
-       }
-
-       cfg.nb_mdts = json_object_array_length(mdts);
-       if (cfg.nb_mdts > ARRAY_SIZE(cfg.mdts)) {
-               fprintf(stderr,
-                       "%s error: mdts array is larger than %lu\n",
-                       progname,
-                       ARRAY_SIZE(cfg.mdts));
-               goto out;
-       }
-
-       for (i = 0; i < cfg.nb_mdts; i++) {
-               struct json_object *data, *mdt_idx, *reader_id;
-               int mdt_id;
-
-               data = json_object_array_get_idx(mdts, i);
-               if (!data) {
-                       fprintf(stderr,
-                               "%s config error: mdt %d is not an object\n",
-                               progname, i);
-                       goto out;
-               }
-
-               rc = json_object_object_get_ex(data, "mdt_idx", &mdt_idx);
-               if (!rc) {
-                       fprintf(stderr,
-                               "%s config error: %s does not have an mdt_idx entry\n",
-                               progname, cfg_file);
-                       goto out;
-               }
-               if (!json_object_is_type(mdt_idx, json_type_int)) {
-                       fprintf(stderr,
-                               "%s config error: mdt_idx is not an int\n",
-                               progname);
-                       goto out;
-               }
-               mdt_id = json_object_get_int(mdt_idx);
-               if (mdt_id < 0 || mdt_id >= MAX_MDTS) {
-                       fprintf(stderr,
-                               "%s config error: mdt_idx %d out of range\n",
-                               progname, mdt_id);
-                       goto out;
-               }
-
-               rc = json_object_object_get_ex(data, "reader_id", &reader_id);
-               if (!rc) {
-                       fprintf(stderr,
-                               "%s config error: %s does not have a reader_id entry\n",
-                               progname, cfg_file);
-                       goto out;
-               }
-               if (!json_object_is_type(reader_id, json_type_string)) {
-                       fprintf(stderr,
-                               "%s config error: reader_id is not a string\n",
-                               progname);
-                       goto out;
-               }
-               if (cfg.mdts[mdt_id].reader_id[0] != '\0') {
-                       fprintf(stderr,
-                               "%s config error: duplicate mdt index %d\n",
-                               progname, mdt_id);
-                       goto out;
-               }
-               if (snprintf(cfg.mdts[mdt_id].reader_id,
-                            sizeof(cfg.mdts[mdt_id].reader_id), "%s",
-                            json_object_get_string(reader_id)) >=
-                   sizeof(cfg.mdts[mdt_id].reader_id)) {
-                       fprintf(stderr,
-                               "%s config error: reader_id is too long\n",
-                               progname);
-                       goto out;
-               }
-       }
-
-       rc = json_object_object_get_ex(root, "parse_interval_sec",
-                                      &parse_interval_sec);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a parse_interval_sec entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(parse_interval_sec, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: parse_interval_sec is not an int\n",
-                       progname);
-               goto out;
-       }
-       cfg.parse_interval_sec = json_object_get_int(parse_interval_sec);
-
-       rc = json_object_object_get_ex(root, "sync_every_n_entries",
-                                      &sync_every_n_entries);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a sync_every_n_entries entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(sync_every_n_entries, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: sync_every_n_entries is not an int\n",
-                       progname);
-               goto out;
-       }
-       cfg.sync_every_n_entries = json_object_get_int(sync_every_n_entries);
-
-       rc = json_object_object_get_ex(root, "max_syncs_before_sleep",
-                                      &max_syncs_before_sleep);
-       if (!rc) {
-               fprintf(stderr,
-                       "%s config error: %s does not have a max_syncs_before_sleep entry\n",
-                       progname, cfg_file);
-               goto out;
-       }
-       if (!json_object_is_type(max_syncs_before_sleep, json_type_int)) {
-               fprintf(stderr,
-                       "%s config error: max_syncs_before_sleep is not an int\n",
-                       progname);
-               goto out;
-       }
-       cfg.max_syncs_before_sleep =
-               json_object_get_int(max_syncs_before_sleep);
-
-       rc = 0;
-out:
-       json_object_put(root);
-       return rc;
-}
-
-static void dump_config(void)
-{
-       int idx;
-
-       if (!config_init)
-               return;
-
-       printf("FS name: %s\n", cfg.fs_name);
-       printf("Mount path: %s\n", cfg.mount);
-       printf("Dump path: %s\n", cfg.dump_path);
-
-       for (idx = 0; idx < MAX_MDTS; idx++) {
-               if (cfg.mdts[idx].reader_id[0] == '\0')
-                       continue;
-               printf("MDT index: %d, reader ID %s\n",
-                      idx, cfg.mdts[idx].reader_id);
-       }
-
-       printf("Parse interval: %d\n", cfg.parse_interval_sec);
-       printf("Sync: every %d entries\n", cfg.sync_every_n_entries);
-       printf("Max syncs before sleep: %d\n", cfg.max_syncs_before_sleep);
-}
-
-static int sanity_config(void)
-{
-       struct stat s;
-       char path[PATH_MAX + 1];
-       int rc;
-
-       if (!config_init)
-               return -1;
-
-       /* check dump_path */
-       rc = stat(cfg.dump_path, &s);
-       if (rc == -1) {
-               fprintf(stderr, "%s: cannot stat %s: %s\n", progname,
-                       cfg.dump_path, strerror(errno));
-               return rc;
-       }
-       if (!S_ISDIR(s.st_mode)) {
-               fprintf(stderr, "%s: dump path %s: %s\n",
-                       progname, cfg.dump_path, strerror(errno = ENOTDIR));
-               return -1;
-       }
-
-       /* create /files and /users directories if necessary */
-       rc = snprintf(path, sizeof(path), "%s/files", cfg.dump_path);
-       if (rc >= sizeof(path))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc && errno != EEXIST) {
-               fprintf(stderr, "%s cannot mkdir %s: %s\n", progname,
-                       path, strerror(errno));
-               return rc;
-       }
-       rc = snprintf(path, sizeof(path), "%s/users", cfg.dump_path);
-       if (rc >= sizeof(path))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc && errno != EEXIST) {
-               fprintf(stderr, "%s cannot mkdir %s: %s\n", progname,
-                       path, strerror(errno));
-               return rc;
-       }
-
-       /* create files/<FID> directory of root dir and associated name and
-        * paths files
-        */
-       if (path2fid) {
-               struct lu_fid fid;
-               char rootpath[NAME_MAX + 2];
-               int sz_max;
-               FILE *fp;
-
-               rc = snprintf(rootpath, sizeof(rootpath), "%s", cfg.mount);
-               if (rc >= sizeof(rootpath))
-                       rc = -ENAMETOOLONG;
-               if (rc < 0)
-                       return rc;
-               rc = llapi_path2fid(rootpath, &fid);
-               if (rc) {
-                       fprintf(stderr, "%s path2fid failed for %s: %s\n",
-                               progname, rootpath, strerror(-rc));
-                       return rc;
-               }
-
-               rc = snprintf(path, sizeof(path), "%s/files/"DFID,
-                             cfg.dump_path, PFID(&fid));
-               if (rc >= sizeof(path))
-                       rc = -ENAMETOOLONG;
-               if (rc < 0)
-                       return rc;
-               rc = mkdir(path, 0700);
-               if (rc && errno != EEXIST) {
-                       fprintf(stderr, "%s cannot mkdir %s: %s\n", progname,
-                               path, strerror(errno));
-                       return rc;
-               }
-
-               if (rc == 0) {
-                       sz_max = sizeof(path) - strlen(path);
-                       rc = snprintf(path + strlen(path), sz_max, "/name");
-                       if (rc >= sz_max)
-                               rc = -ENAMETOOLONG;
-                       if (rc < 0)
-                               return rc;
-                       fp = fopen(path, "w");
-                       if (fp == NULL) {
-                               printerr("cannot open %s: %s\n",
-                                        path, strerror(errno));
-                               return -errno;
-                       }
-                       rc = fprintf(fp, "/");
-                       fclose(fp);
-                       if (rc != 1) {
-                               printerr("cannot write name info in %s: %s\n",
-                                        path, strerror(errno));
-                               return -errno;
-                       }
-
-                       rc = snprintf(path, sizeof(path),
-                                     "%s/files/"DFID"/paths",
-                                     cfg.dump_path, PFID(&fid));
-                       if (rc >= sizeof(path))
-                               rc = -ENAMETOOLONG;
-                       if (rc < 0)
-                               return rc;
-                       fp = fopen(path, "w");
-                       if (fp == NULL) {
-                               printerr("cannot open %s: %s\n",
-                                        path, strerror(errno));
-                               return -errno;
-                       }
-                       fclose(fp);
-               }
-       }
-
-       /* check parse_interval_sec */
-       if (cfg.parse_interval_sec <= 0) {
-               fprintf(stderr, "%s: parse_interval_sec %d invalid\n",
-                       progname, cfg.parse_interval_sec);
-               return -1;
-       }
-
-       /* sync_every_n_entries */
-       if (cfg.sync_every_n_entries <= 0) {
-               fprintf(stderr, "%s: sync_every_n_entries %d invalid\n",
-                       progname, cfg.sync_every_n_entries);
-               return -1;
-       }
-
-       /* max_syncs_before_sleep */
-       if (cfg.max_syncs_before_sleep <= 0) {
-               fprintf(stderr, "%s: max_syncs_before_sleep %d invalid\n",
-                       progname, cfg.max_syncs_before_sleep);
-               return -1;
-       }
-
-       return 0;
-}
-
-/* 3 objectives:
- * - write name in 'files/<tFID>/name' file
- * - write parent FID in 'files/<tFID>/pfid' file
- * - build full path info and put into pathinfo variable
- */
-static int get_path_info(char *name, int namelen, char *tfidstr, char *pfidstr,
-                        char *pathinfo, int pathinfo_sz, bool edit)
-{
-       char path_pfid[PATH_MAX] = { 0 };
-       char path_name[PATH_MAX] = { 0 };
-       char pfid[PATH_MAX] = { 0 };
-       char namestr[NAME_MAX] = { 0 };
-       struct stat s;
-       FILE *fp;
-       int fd;
-       int sz_max;
-       int rc;
-
-       rc = snprintf(path_pfid, sizeof(path_pfid), "%s/files/%s",
-                     cfg.dump_path, tfidstr);
-       if (rc >= sizeof(path_pfid))
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("%s: error with snprintf: %d\n",
-                        progname, strerror(-rc));
-               return rc;
-       }
-
-       rc = mkdir(path_pfid, 0700);
-       if (rc && errno != EEXIST) {
-               printerr("%s cannot mkdir %s: %s\n", progname,
-                        path_pfid, strerror(errno));
-               return rc;
-       }
-
-       sz_max = sizeof(path_pfid) - strlen(path_pfid);
-       rc = snprintf(path_pfid + strlen(path_pfid), sz_max, "/pfid");
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("%s: error with snprintf: %d\n",
-                        progname, strerror(-rc));
-               return rc;
-       }
-
-       rc = snprintf(path_name, sizeof(path_name), "%s/files/%s/name",
-                     cfg.dump_path, tfidstr);
-       if (rc >= sizeof(path_name))
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("%s: error with snprintf: %d\n",
-                        progname, strerror(-rc));
-               return rc;
-       }
-
-       rc = stat(path_pfid, &s);
-       if (rc == -1) {
-               if (pfidstr != NULL) {
-                       fp = fopen(path_pfid, "w");
-                       if (fp == NULL) {
-                               printerr("cannot open %s: %s\n",
-                                        path_pfid, strerror(errno));
-                               return -errno;
-                       }
-                       rc = fprintf(fp, "%s", pfidstr);
-                       fclose(fp);
-                       if (rc != strlen(pfidstr)) {
-                               printerr("cannot write pfid info in %s: %s\n",
-                                        path_pfid, strerror(errno));
-                               return -errno;
-                       }
-
-                       /* what if path_name file already exists? */
-                       fp = fopen(path_name, "w");
-                       if (fp == NULL) {
-                               printerr("cannot open %s: %s\n",
-                                        path_name, strerror(errno));
-                               return -errno;
-                       }
-                       rc = snprintf(namestr, sizeof(namestr), "%.*s",
-                                     namelen, name);
-                       if (rc >= sizeof(namestr))
-                               rc = -ENAMETOOLONG;
-                       if (rc < 0) {
-                               printerr("%s: error with snprintf: %d\n",
-                                        progname, strerror(-rc));
-                               return rc;
-                       }
-                       rc = fprintf(fp, "%s", namestr);
-                       fclose(fp);
-                       if (rc != strlen(namestr)) {
-                               printerr("cannot write name info in %s: %s\n",
-                                        path_name, strerror(errno));
-                               return -errno;
-                       }
-               } else {
-                       /* if 'name' file exists and contains '/', take it */
-                       fd = open(path_name, O_RDONLY);
-                       if (fd != -1) {
-                               rc = read(fd, namestr, sizeof(namestr));
-                               close(fd);
-                               if (rc == -1) {
-                                       printerr("cannot read from file %s: %s\n",
-                                                path_name, strerror(errno));
-                                       return -errno;
-                               }
-                               namestr[rc] = '\0';
-
-                               if (strncmp(namestr, "/", strlen(namestr)) == 0)
-                                       goto process;
-
-                               namestr[0] = '\0';
-                       }
-
-                       {
-                               char tfid_pathinfo[PATH_MAX];
-                               long long recno = -1;
-                               int linkno = 0;
-                               struct lu_fid parent_fid;
-
-                               /* no pfid file, and no pfidstr info provided
-                                * => means we are on a intermediate directory
-                                * in the path, and laudit was not run with '-p'
-                                * since beginning of Lustre fs life.
-                                * Solution is to rebuild info with
-                                * llapi_fid2path(tfidstr) and then
-                                * llapi_path2parent(newpath), and finally
-                                * putting parent_fid in 'pfid' file
-                                * and name in 'name' file.
-                                */
-
-                               /* But this resolution can be incorrect, eg:
-                                * # touch /<fs>/dirA/fileA
-                                * # mv /<fs>/dirA /<fs>/dirB
-                                * # laudit -p
-                                * => this will give wrong path (dirB/fileA) in
-                                * CREAT entry for fileA
-                                * But maybe this is better than nothing.
-                                * In this case, display a warning.
-                                */
-                               if (!warn_possible_fid2path_error) {
-                                       printerr("%s: Warning! resolving path-to-fid with llapi_fid2path(). This may incur extra overhead, and possible incorrect path resolutions.\n",
-                                                progname);
-                                       warn_possible_fid2path_error = true;
-                               }
-
-                               rc = snprintf(tfid_pathinfo,
-                                             sizeof(tfid_pathinfo),
-                                             "%s/", cfg.mount);
-                               if (rc >= sizeof(tfid_pathinfo))
-                                       rc = -ENAMETOOLONG;
-                               if (rc < 0)
-                                       return rc;
-
-                               rc = llapi_fid2path(cfg.fs_name, tfidstr,
-                                                   tfid_pathinfo +
-                                                    strlen(tfid_pathinfo),
-                                                   sizeof(tfid_pathinfo) -
-                                                    strlen(tfid_pathinfo),
-                                                   &recno, &linkno);
-                               if (rc) {
-                                       printerr("%s cannot get path from FID %s: %s\n",
-                                                progname, pfidstr,
-                                                strerror(-rc));
-                                       return rc;
-                               }
-
-                               rc = llapi_path2parent(tfid_pathinfo, linkno,
-                                                      &parent_fid, namestr,
-                                                      sizeof(namestr));
-                               if (rc) {
-                                       printerr("%s cannot get parent FID from path %s: %s\n",
-                                                progname,
-                                                tfid_pathinfo, strerror(-rc));
-                                       return rc;
-                               }
-
-                               sprintf(pfid, DFID, PFID(&parent_fid));
-                               pfidstr = pfid;
-
-                               fp = fopen(path_pfid, "w");
-                               if (fp == NULL) {
-                                       printerr("cannot open %s: %s\n",
-                                                path_pfid, strerror(errno));
-                                       return -errno;
-                               }
-                               rc = fprintf(fp, "%s", pfidstr);
-                               fclose(fp);
-                               if (rc != strlen(pfidstr)) {
-                                       printerr("cannot write pfid info in %s: %s\n",
-                                                path_pfid, strerror(errno));
-                                       return -errno;
-                               }
-
-                               fp = fopen(path_name, "w");
-                               if (fp == NULL) {
-                                       printerr("cannot open %s: %s\n",
-                                                path_name, strerror(errno));
-                                       return -errno;
-                               }
-                               rc = fprintf(fp, "%s", namestr);
-                               fclose(fp);
-                               if (rc != strlen(namestr)) {
-                                       printerr("cannot write name info in %s: %s\n",
-                                                path_name, strerror(errno));
-                                       return -errno;
-                               }
-
-                       }
-               }
-       } else {
-               if (pfidstr != NULL) {
-                       if (edit) {
-                               /* this happens in case of rename */
-                               fp = fopen(path_pfid, "w");
-                               if (fp == NULL) {
-                                       printerr("cannot open %s: %s\n",
-                                                path_pfid, strerror(errno));
-                                       return -errno;
-                               }
-                               rc = fprintf(fp, "%s", pfidstr);
-                               fclose(fp);
-                               if (rc != strlen(pfidstr)) {
-                                       printerr("can't write pfid in %s: %s\n",
-                                                path_pfid, strerror(errno));
-                                       return -errno;
-                               }
-                       }
-               } else {
-                       fd = open(path_pfid, O_RDONLY);
-                       if (fd == -1) {
-                               printerr("cannot open %s: %s\n",
-                                        path_pfid, strerror(errno));
-                               return -errno;
-                       }
-                       rc = read(fd, pfid, sizeof(pfid));
-                       close(fd);
-                       if (rc == -1) {
-                               printerr("cannot read from file %s: %s\n",
-                                        path_pfid, strerror(errno));
-                               return -errno;
-                       }
-                       pfid[rc] = '\0';
-                       pfidstr = pfid;
-               }
-
-               if (name != NULL) {
-                       rc = snprintf(namestr, sizeof(namestr), "%.*s",
-                                     namelen, name);
-                       if (rc >= sizeof(namestr))
-                               rc = -ENAMETOOLONG;
-                       if (rc < 0) {
-                               printerr("%s: error with snprintf: %d\n",
-                                        progname, strerror(-rc));
-                               return rc;
-                       }
-
-                       if (edit) {
-                               /* this happens in case of rename */
-                               fp = fopen(path_name, "w");
-                               if (fp == NULL) {
-                                       printerr("cannot open %s: %s\n",
-                                                path_name, strerror(errno));
-                                       return -errno;
-                               }
-
-                               rc = fprintf(fp, "%s", namestr);
-                               fclose(fp);
-                               if (rc != strlen(namestr)) {
-                                       printerr("can't write name in %s: %s\n",
-                                                path_name, strerror(errno));
-                                       return -errno;
-                               }
-                       }
-               } else {
-                       fd = open(path_name, O_RDONLY);
-                       if (fd == -1) {
-                               printerr("cannot open %s: %s\n",
-                                        path_name, strerror(errno));
-                               return -errno;
-                       }
-                       rc = read(fd, namestr, sizeof(namestr));
-                       close(fd);
-                       if (rc == -1) {
-                               printerr("cannot read from file %s: %s\n",
-                                        path_name, strerror(errno));
-                               return -errno;
-                       }
-                       namestr[rc] = '\0';
-               }
-       }
-
-process:
-       if (pfidstr != NULL) {
-               get_path_info(NULL, 0, pfidstr, NULL, pathinfo, pathinfo_sz,
-                             false);
-               if (pathinfo[0] == '/') {
-                       pathinfo[0] = '\0';
-               } else {
-                       sz_max = pathinfo_sz - strlen(pathinfo);
-                       rc = snprintf(pathinfo + strlen(pathinfo), sz_max, "/");
-                       if (rc >= sz_max)
-                               rc = -ENAMETOOLONG;
-                       if (rc < 0) {
-                               printerr("%s: error with snprintf: %d\n",
-                                        progname, strerror(-rc));
-                               return rc;
-                       }
-               }
-       } else {
-               pathinfo[0] = '\0';
-       }
-
-       /* add file name after path of parent */
-       sz_max = pathinfo_sz - strlen(pathinfo);
-       rc = snprintf(pathinfo + strlen(pathinfo), sz_max, "%s",
-                     namestr);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0) {
-               printerr("%s: error with snprintf: %d\n",
-                        progname, strerror(-rc));
-               return rc;
-       }
-
-       return 0;
-}
-
-/* If rec target fid is [0:0x0:0x0], make sure operation is 08RENME,
- * and then use source FID instead of target FID
- */
-static int tfid(struct changelog_rec *rec, char *tfidstr)
-{
-       if (fid_is_zero(&rec->cr_tfid) &&
-           rec->cr_type == CL_RENAME && rec->cr_flags & CLF_RENAME) {
-               struct changelog_ext_rename *rnm = changelog_rec_rename(rec);
-
-               if (fid_is_zero(&rnm->cr_sfid)) {
-                       printerr("cannot find usable fid in rec %d\n",
-                                rec->cr_index);
-                       return -errno;
-               }
-               sprintf(tfidstr, DFID, PFID(&rnm->cr_sfid));
-       } else {
-               sprintf(tfidstr, DFID, PFID(&rec->cr_tfid));
-       }
-
-       return 0;
-}
-
-static int get_record_info(struct changelog_rec *rec, struct tm ts,
-                          struct changelog_ext_uidgid **uidgid,
-                          char *tstamp, int tstamp_sz,
-                          char *rec_info, int rec_info_sz,
-                          char *pathinfo, int pathinfo_sz)
-{
-       int sz_max;
-       int rc;
-
-       rec_info[0] = '\0';
-       *uidgid = NULL;
-
-       rc = snprintf(tstamp, tstamp_sz,
-                     "%04d.%02d.%02d %02d:%02d:%02d.%09d",
-                     ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday,
-                     ts.tm_hour, ts.tm_min, ts.tm_sec,
-                     (int)(rec->cr_time & ((1 << 30) - 1)));
-       if (rc >= tstamp_sz)
-               rc = -EAGAIN;
-       if (rc < 0)
-               goto printerr;
-
-       if (rec->cr_flags & CLF_JOBID) {
-               struct changelog_ext_jobid *jid = changelog_rec_jobid(rec);
-
-               if (jid->cr_jobid[0] != '\0') {
-                       sz_max = rec_info_sz - strlen(rec_info);
-                       rc = snprintf(rec_info + strlen(rec_info), sz_max,
-                                     " j=%s", jid->cr_jobid);
-                       if (rc >= sz_max)
-                               rc = -EAGAIN;
-                       if (rc < 0)
-                               goto printerr;
-               }
-       }
-
-       if (rec->cr_flags & CLF_EXTRA_FLAGS) {
-               struct changelog_ext_extra_flags *ef =
-                       changelog_rec_extra_flags(rec);
-
-               if (ef->cr_extra_flags & CLFE_UIDGID)
-                       *uidgid = changelog_rec_uidgid(rec);
-
-               if (ef->cr_extra_flags & CLFE_NID) {
-                       struct changelog_ext_nid *nid = changelog_rec_nid(rec);
-
-                       sz_max = rec_info_sz - strlen(rec_info);
-                       rc = snprintf(rec_info + strlen(rec_info), sz_max,
-                                     " nid=%s", libcfs_nid2str(nid->cr_nid));
-                       if (rc >= sz_max)
-                               rc = -EAGAIN;
-                       if (rc < 0)
-                               goto printerr;
-               }
-
-               if (ef->cr_extra_flags & CLFE_OPEN) {
-                       struct changelog_ext_openmode *omd =
-                               changelog_rec_openmode(rec);
-                       char mode[] = "---";
-
-                       /* exec mode must be exclusive */
-                       if (omd->cr_openflags & MDS_FMODE_EXEC) {
-                               mode[2] = 'x';
-                       } else {
-                               if (omd->cr_openflags & MDS_FMODE_READ)
-                                       mode[0] = 'r';
-                               if (omd->cr_openflags &
-                                   (MDS_FMODE_WRITE |
-                                    MDS_OPEN_TRUNC |
-                                    MDS_OPEN_APPEND))
-                                       mode[1] = 'w';
-                       }
-
-                       if (strcmp(mode, "---")) {
-                               sz_max = rec_info_sz - strlen(rec_info);
-                               rc = snprintf(rec_info + strlen(rec_info),
-                                             sz_max, " m=%s", mode);
-                               if (rc >= sz_max)
-                                       rc = -EAGAIN;
-                               if (rc < 0)
-                                       goto printerr;
-                       }
-               }
-
-               if (ef->cr_extra_flags & CLFE_XATTR) {
-                       struct changelog_ext_xattr *xattr =
-                               changelog_rec_xattr(rec);
-
-                       if (xattr->cr_xattr[0] != '\0') {
-                               sz_max = rec_info_sz - strlen(rec_info);
-                               rc = snprintf(rec_info + strlen(rec_info),
-                                             sz_max, " x=%s", xattr->cr_xattr);
-                               if (rc >= sz_max)
-                                       rc = -EAGAIN;
-                               if (rc < 0)
-                                       goto printerr;
-                       }
-               }
-       }
-
-       if (rec->cr_namelen) {
-               char fidstr[PATH_MAX];
-
-               sprintf(fidstr, DFID, PFID(&rec->cr_pfid));
-               if (path2fid) {
-                       char tfidstr[PATH_MAX];
-
-                       rc = tfid(rec, tfidstr);
-                       if (rc)
-                               goto out_noprint;
-
-                       rc = get_path_info(changelog_rec_name(rec),
-                                          rec->cr_namelen, tfidstr, fidstr,
-                                          pathinfo, pathinfo_sz, true);
-                       if (rc)
-                               goto out_noprint;
-               }
-
-               sz_max = rec_info_sz - strlen(rec_info);
-               rc = snprintf(rec_info + strlen(rec_info), sz_max,
-                            " p=%s %.*s", fidstr,
-                            path2fid ? (int)strlen(pathinfo) : rec->cr_namelen,
-                            path2fid ? pathinfo : changelog_rec_name(rec));
-               if (rc >= sz_max)
-                       rc = -EAGAIN;
-               if (rc < 0)
-                       goto printerr;
-       }
-
-       if (rec->cr_flags & CLF_RENAME) {
-               struct changelog_ext_rename *rnm = changelog_rec_rename(rec);
-               char fidstr[PATH_MAX];
-               char spathinfo[PATH_MAX];
-
-               if (!fid_is_zero(&rnm->cr_sfid)) {
-                       sprintf(fidstr, DFID, PFID(&rnm->cr_spfid));
-                       if (path2fid) {
-                               char tfidstr[PATH_MAX];
-
-                               rc = tfid(rec, tfidstr);
-                               if (rc)
-                                       goto out_noprint;
-
-                               rc = get_path_info(changelog_rec_sname(rec),
-                                              (int)changelog_rec_snamelen(rec),
-                                              tfidstr, fidstr, spathinfo,
-                                              sizeof(spathinfo), false);
-                               if (rc)
-                                       goto out_noprint;
-                       }
-
-                       sz_max = rec_info_sz - strlen(rec_info);
-                       rc = snprintf(rec_info + strlen(rec_info), sz_max,
-                                     " s="DFID" sp=%s %.*s",
-                                     PFID(&rnm->cr_sfid), fidstr,
-                                     path2fid ? (int)strlen(spathinfo) :
-                                     (int)changelog_rec_snamelen(rec),
-                                     path2fid ? spathinfo :
-                                     changelog_rec_sname(rec));
-                       if (rc >= sz_max)
-                               rc = -EAGAIN;
-                       if (rc < 0)
-                               goto printerr;
-               }
-       }
-
-printerr:
-       if (rc < 0) {
-               printerr("%s cannot get record info: %s\n",
-                        progname, strerror(-rc));
-       } else if (uidgid == NULL) {
-               printerr("%s cannot get uid/gid: aborting\n",
-                        progname);
-               rc = -EINVAL;
-       } else {
-               rc = 0;
-       }
-out_noprint:
-       return rc;
-}
-
-/* When called with uidgid != NULL, put it into record; else put FID instead. */
-static int write_rec_file(char *main_dir, struct changelog_rec *rec,
-                         struct changelog_ext_uidgid *uidgid,
-                         struct tm ts, char *tstamp, char *rec_info)
-{
-       /* directory structure is like:
-        * main_dir/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-
-       char path[PATH_MAX + 1];
-       FILE *file;
-       int sz_max;
-       int rc;
-
-       /* 1. always try to create main_dir directory */
-       rc = mkdir(main_dir, 0700);
-       if (rc && errno != EEXIST) {
-               printerr("%s cannot mkdir %s: %s\n", progname,
-                        main_dir, strerror(errno));
-               return rc;
-       }
-
-       /* 2. always try to create $YEAR/$MONTH/$DAY/$HOUR$MIN directory */
-       sz_max = sizeof(path);
-       goto hourmin;
-year:
-       rc = snprintf(path, sz_max, "%s/%04d", main_dir, ts.tm_year + 1900);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc && errno != EEXIST) {
-               printerr("%s cannot mkdir %s: %s\n", progname,
-                        path, strerror(errno));
-               return rc;
-       }
-month:
-       rc = snprintf(path, sz_max, "%s/%04d/%02d", main_dir,
-                     ts.tm_year + 1900, ts.tm_mon + 1);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc) {
-               if (errno == ENOENT) {
-                       goto year;
-               } else if (errno != EEXIST) {
-                       printerr("%s cannot mkdir %s: %s\n", progname,
-                                path, strerror(errno));
-                       return rc;
-               }
-       }
-day:
-       rc = snprintf(path, sz_max, "%s/%04d/%02d/%02d", main_dir,
-                     ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc) {
-               if (errno == ENOENT) {
-                       goto month;
-               } else if (errno != EEXIST) {
-                       printerr("%s cannot mkdir %s: %s\n", progname,
-                                path, strerror(errno));
-                       return rc;
-               }
-       }
-hourmin:
-       rc = snprintf(path, sz_max, "%s/%04d/%02d/%02d/%02d%02d", main_dir,
-                     ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday,
-                     ts.tm_hour, ts.tm_min);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = mkdir(path, 0700);
-       if (rc) {
-               if (errno == ENOENT) {
-                       goto day;
-               } else if (errno != EEXIST) {
-                       printerr("%s cannot mkdir %s: %s\n", progname,
-                                path, strerror(errno));
-                       return rc;
-               }
-       }
-
-       /* 3. open $SECS file in append mode */
-       sz_max = sizeof(path) - strlen(path);
-       rc = snprintf(path + strlen(path), sz_max, "/%02d", ts.tm_sec);
-       if (rc >= sz_max)
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       file = fopen(path, "a");
-       if (file == NULL) {
-               printerr("%s cannot open %s: %s\n", progname,
-                        path, strerror(errno));
-               return -1;
-       }
-
-       /* 4. write info */
-       if (uidgid)
-               rc = fprintf(file, "%s %02d%s u=%llu:%llu%s\n",
-                            tstamp, rec->cr_type,
-                            changelog_type2str(rec->cr_type), uidgid->cr_uid,
-                            uidgid->cr_gid, rec_info);
-       else
-               rc = fprintf(file, "%s %02d%s t="DFID"%s\n",
-                            tstamp, rec->cr_type,
-                            changelog_type2str(rec->cr_type),
-                            PFID(&rec->cr_tfid), rec_info);
-
-       if (rc < 0)
-               printerr("%s cannot write to file %s: %s\n",
-                        progname, path, strerror(-rc));
-
-       /* 5. close file */
-       fclose(file);
-
-       return rc;
-}
-
-static int write_audit_files(struct changelog_rec *rec,
-                            struct changelog_ext_uidgid *uidgid,
-                            struct tm ts, char *tstamp,
-                            char *rec_info, char *pathinfo)
-{
-       char main_dir[PATH_MAX + 1];
-       char fidstr[PATH_MAX];
-       FILE *fp;
-       int rc;
-
-       rc = tfid(rec, fidstr);
-       if (rc)
-               return rc;
-
-       if (verbose > 1)
-               printinfo("%s %02d%s t="DFID" u=%u:%u%s\n", tstamp,
-                         rec->cr_type, changelog_type2str(rec->cr_type),
-                         PFID(&rec->cr_tfid),
-                         uidgid->cr_uid, uidgid->cr_gid, rec_info);
-
-       /* directory structure for easy file history:
-        * files/$FID/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/files/%s",
-                     cfg.dump_path, fidstr);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = write_rec_file(main_dir, rec, uidgid, ts, tstamp, rec_info);
-
-       if (rc < 0)
-               return rc;
-
-       /* If necessary, store path info in files/$FID/paths file.
-        * Append new paths as file is moved.
-        */
-       if (path2fid && rec->cr_namelen) {
-               rc = snprintf(main_dir + strlen(main_dir),
-                             sizeof(main_dir) - strlen(main_dir),
-                             "/paths");
-               if (rc >= sizeof(main_dir))
-                       rc = -ENAMETOOLONG;
-               if (rc < 0)
-                       return rc;
-
-               fp = fopen(main_dir, "a");
-               if (fp == NULL) {
-                       printerr("cannot open %s: %s\n",
-                                main_dir, strerror(errno));
-                       return -errno;
-               }
-               rc = fprintf(fp, "%s\n", pathinfo);
-               fclose(fp);
-               if (rc != strlen(pathinfo) + 1) {
-                       printerr("cannot write path info in %s: %s\n",
-                                main_dir, strerror(errno));
-                       return -errno;
-               }
-       }
-
-       /* directory structure for easy user history:
-        * users/$UID:GID/$YEAR/$MONTH/$DAY/$HOUR$MIN/$SECS
-        */
-       rc = snprintf(main_dir, sizeof(main_dir), "%s/users/%llu:%llu",
-                     cfg.dump_path, uidgid->cr_uid, uidgid->cr_gid);
-       if (rc >= sizeof(main_dir))
-               rc = -ENAMETOOLONG;
-       if (rc < 0)
-               return rc;
-       rc = write_rec_file(main_dir, rec, NULL, ts, tstamp, rec_info);
-       return rc;
-}
-
-/* Important note about changelogs API implementation:
- * records that can be read with llapi_changelog_recv()
- * are determined by the time when llapi_changelog_start() is called.
- * So with llapi_changelog_clear(), it becomes possible to clear entries that
- * were not read, eg if they were added to the llogs AFTER the call to
- * llapi_changelog_start().
- */
-
-static int parse_changelog(int idx)
-{
-       void *changelog_priv;
-       struct changelog_rec *rec;
-       time_t secs;
-       struct tm ts;
-       char tstamp[30];
-       /* "j=jobid nid=nid m=openmode x=xattr p=PFID <name>
-        *  s=SFID sp=SPFID <sname>"
-        * openmode: 3
-        * FID: 42
-        */
-       char rec_info[LUSTRE_JOBID_SIZE + LNET_NIDSTR_SIZE + XATTR_NAME_MAX +
-                     2*NAME_MAX + 153];
-       char pathinfo[PATH_MAX];
-       struct changelog_ext_uidgid *uidgid;
-       __u64 last_cr_index = 0;
-       int loop_count = 0, resume_count = 0;
-       int rc = 0;
-
-       if (stop_now)
-               return -EINTR;
-
-resume:
-       if (daemon_mode && ++resume_count > cfg.max_syncs_before_sleep)
-               goto out_parse;
-
-       rc = llapi_changelog_start(&changelog_priv,
-                                  CHANGELOG_FLAG_BLOCK |
-                                  CHANGELOG_FLAG_JOBID |
-                                  CHANGELOG_FLAG_EXTRA_FLAGS,
-                                  cfg.mdts[idx].mdd_name, 0);
-       if (rc < 0) {
-               printerr("%s cannot start changelog for %s: %s\n",
-                        progname, cfg.mdts[idx].mdd_name,
-                        strerror(errno = -rc));
-               return rc;
-       }
-
-       rc = llapi_changelog_set_xflags(changelog_priv,
-                                       CHANGELOG_EXTRA_FLAG_UIDGID |
-                                       CHANGELOG_EXTRA_FLAG_NID |
-                                       CHANGELOG_EXTRA_FLAG_OMODE |
-                                       CHANGELOG_EXTRA_FLAG_XATTR);
-       if (rc < 0) {
-               printerr("%s cannot set xflags for changelog: %s\n",
-                        progname, strerror(errno = -rc));
-               return rc;
-       }
-
-       while (!stop_now && rc >= 0 && loop_count < cfg.sync_every_n_entries) {
-               rc = llapi_changelog_recv(changelog_priv, &rec);
-               if (rc < 0) {
-                       printerr("%s cannot read changelog: %s\n",
-                                progname, strerror(errno = -rc));
-                       break;
-               }
-               if (rc)
-                       /* no more to read */
-                       break;
-
-               secs = rec->cr_time >> 30;
-               gmtime_r(&secs, &ts);
-
-               /* get timestamp, uid/gid, nid and all relevant info */
-               rc = get_record_info(rec, ts, &uidgid, tstamp, sizeof(tstamp),
-                                    rec_info, sizeof(rec_info),
-                                    pathinfo, sizeof(pathinfo));
-
-               /* write record info to audit files */
-               if (rc == 0) {
-                       rc = write_audit_files(rec, uidgid, ts, tstamp,
-                                              rec_info, pathinfo);
-                       if (rc >= 0)
-                               last_cr_index = rec->cr_index;
-               }
-               llapi_changelog_free(&rec);
-
-               if (rc < 0)
-                       break;
-
-               loop_count++;
-       }
-       llapi_changelog_fini(&changelog_priv);
-
-       /* do not waste time syncing if no new entry was written,
-        * or do not clear if a problem occured when dumping
-        */
-       if (last_cr_index)
-               rc = sync_n_clear(idx, last_cr_index);
-
-       if (!stop_now && rc == 0 && loop_count == cfg.sync_every_n_entries) {
-               last_cr_index = 0;
-               loop_count = 0;
-               goto resume;
-       }
-
-       if (stop_now && rc >= 0)
-               rc = -EINTR;
-
-out_parse:
-       return (rc == 1 ? 0 : rc);
-}
-
-int get_opts(int argc, char *const argv[])
-{
-       static struct option long_opts[] = {
-               { .val = 'd',   .name =  "daemon",      .has_arg = no_argument},
-               { .val = 'p',   .name =  "path",        .has_arg = no_argument},
-               { .val = 'v',   .name =  "verbose",     .has_arg = no_argument},
-               { .name = NULL } };
-       char *short_opts = "dpv";
-       int opt;
-       int longidx;
-
-       optind = 0;
-       while ((opt = getopt_long(argc, argv, short_opts, long_opts,
-                                 &longidx)) != EOF) {
-               switch (opt) {
-               case 'd':
-                       daemon_mode = 1;
-                       break;
-               case 'p':
-                       path2fid = true;
-                       break;
-               case 'v':
-                       verbose++;
-                       break;
-               default:
-                       if (opt != '?')
-                               fprintf(stderr, "Unknown option '%c'\n", opt);
-                       return -EINVAL;
-               }
-       }
-
-       if (optind == argc) {
-               /* The user didn't specify config file */
-               fprintf(stderr, "Not enough arguments - config file ");
-               fprintf(stderr, "not specified.\n");
-               return -EINVAL;
-       }
-
-       /*  The config file */
-       strncpy(config_file, argv[argc - 1], sizeof(config_file) - 1);
-       config_file[sizeof(config_file) - 1] = '\0';
-
-       return 0;
-}
-
-int main(int argc, char **argv)
-{
-       struct sigaction stop_sigaction, ignore_sigaction;
-       int idx;
-       int rc;
-
-       progname = argv[0]; /* Used in error messages */
-
-       if (argc < 2 || argv[argc - 1][0] == '-') {
-               fprintf(stderr, "%s, missing options\n", argv[0]);
-               laudit_usage();
-               return -EINVAL;
-       }
-
-       /* Ensure that liblustreapi constructor has run */
-       if (!liblustreapi_initialized)
-               fprintf(stderr, "liblustreapi was not properly initialized\n");
-
-       setlinebuf(stdout);
-
-       rc = get_opts(argc, argv);
-       if (rc)
-               goto out_main;
-
-       rc = get_config(config_file);
-       if (rc)
-               goto out_main;
-       config_init = true;
-
-       if (verbose)
-               dump_config();
-
-       rc = sanity_config();
-       if (rc)
-               goto out_main;
-
-       for (idx = 0; idx < MAX_MDTS; idx++) {
-               if (cfg.mdts[idx].reader_id[0] == '\0')
-                       continue;
-               rc = snprintf(cfg.mdts[idx].mdd_name, MDD_NAME_LEN + 1,
-                             "%s-MDT%04x", cfg.fs_name, idx);
-               if (rc >= MDD_NAME_LEN + 1) {
-                       rc = EINVAL;
-                       break;
-               }
-               if (rc < 0)
-                       break;
-       }
-
-       switch (daemon_mode) {
-       case 0:
-               for (idx = 0; idx < MAX_MDTS; idx++) {
-                       if (cfg.mdts[idx].reader_id[0] == '\0')
-                               continue;
-                       rc = parse_changelog(idx);
-                       if (rc)
-                               break;
-               }
-               break;
-       case 1:
-               rc = daemon(0, 0);
-               if (rc < 0) {
-                       printerr("%s could not daemonize: %s\n",
-                                progname, strerror(errno));
-                       break;
-               }
-
-               memset(&stop_sigaction, 0, sizeof(stop_sigaction));
-               stop_sigaction.sa_handler = sig_stop_parsing;
-               sigemptyset(&stop_sigaction.sa_mask);
-               sigaction(SIGINT, &stop_sigaction, NULL);
-               sigaction(SIGTERM, &stop_sigaction, NULL);
-               memset(&ignore_sigaction, 0, sizeof(ignore_sigaction));
-               ignore_sigaction.sa_handler = sig_ignore;
-               sigemptyset(&ignore_sigaction.sa_mask);
-               sigaction(SIGHUP, &ignore_sigaction, NULL);
-
-               printinfo("%s commencing operation\n", progname);
-
-               while (1) {
-                       rc = -EINTR;
-                       for (idx = 0; idx < MAX_MDTS; idx++) {
-                               if (cfg.mdts[idx].reader_id[0] == '\0')
-                                       continue;
-                               rc = parse_changelog(idx);
-                               if (rc)
-                                       break;
-                       }
-                       if (rc)
-                               break;
-
-                       sleep(cfg.parse_interval_sec);
-               }
-
-               printinfo("%s exiting\n", progname);
-               break;
-       }
-
-out_main:
-       return rc < 0 ? -rc : rc;
-}
index e0e5a5d..9746b9f 100644 (file)
@@ -33,7 +33,6 @@ noinst_SCRIPTS += mds-survey.sh parallel-scale-nfs.sh large-lun.sh
 noinst_SCRIPTS += parallel-scale-nfsv3.sh parallel-scale-nfsv4.sh
 noinst_SCRIPTS += setup-cifs.sh parallel-scale-cifs.sh
 noinst_SCRIPTS += posix.sh sanity-scrub.sh scrub-performance.sh ha.sh pjdfstest.sh
-noinst_SCRIPTS += sanity-laudit.sh
 noinst_SCRIPTS += sanity-lfsck.sh lfsck-performance.sh sanity-lipe.sh
 noinst_SCRIPTS += sanity-lipe-find3.sh
 noinst_SCRIPTS += sanity-lipe-scan3.sh
diff --git a/lustre/tests/sanity-laudit.sh b/lustre/tests/sanity-laudit.sh
deleted file mode 100644 (file)
index 58bf8f8..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/bash
-#
-# Tests for laudit and laudit-report
-#
-set -e
-
-ONLY=${ONLY:-"$*"}
-
-LUSTRE=${LUSTRE:-$(dirname $0)/..}
-. $LUSTRE/tests/test-framework.sh
-init_test_env $@
-. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
-init_logging
-
-# bug number for skipped test:
-ALWAYS_EXCEPT="$SANITY_LAUDIT_EXCEPT "
-# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
-
-! remote_mds_nodsh || skip_env "remote MDS with nodsh"
-! remote_ost_nodsh || skip_env "remote OSS with nodsh"
-
-# check if laudit and laudit-report are installed on clients
-for t in laudit laudit-report; do
-       do_nodes $CLIENTS "which $t" &>/dev/null ||
-               skip_env "$t is not installed on client"
-done
-
-# laudit configuration
-LAUDIT="laudit"
-LAUDIT_REPORT="laudit-report"
-LAUDIT_DUMP_PATH=$TMP/audit
-LAUDIT_CONF_FILE=$TMP/laudit.conf
-
-build_test_filter
-check_and_setup_lustre
-check_runas_id $RUNAS_ID $RUNAS_ID $RUNAS
-
-setup_changelogs() {
-       changelog_register || error "changelog_register failed"
-       local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
-       changelog_users $SINGLEMDS | grep -q $cl_user ||
-               error "User $cl_user not found in changelog_users"
-       changelog_chmask "ALL"
-}
-
-cleanup_sanity_laudit() {
-       rm -f $LAUDIT_CONF_FILE
-       rm -rf $LAUDIT_DUMP_PATH
-       killall laudit
-}
-
-generate_conf_file() {
-       cat <<EOF > $LAUDIT_CONF_FILE
-{
-    "fs_name": "$FSNAME",
-    "mount": "$MOUNT",
-    "dump_path": "$LAUDIT_DUMP_PATH",
-    "mdts": [
-EOF
-       for i in $(seq 1 $MDSCOUNT); do
-               echo "      {\"mdt_idx\": $((i-1)), \"reader_id\": \"${CL_USERS[mds$i]%% *}\"}," >> $LAUDIT_CONF_FILE
-       done
-       cat <<EOF >> $LAUDIT_CONF_FILE
-    ],
-    "parse_interval_sec": 10,
-    "sync_every_n_entries": 1000,
-    "max_syncs_before_sleep": 10
-}
-EOF
-}
-
-create_simple_files() {
-       local dir=$1
-
-       changelog_clear 0 || error "changelog_clear failed"
-       $RUNAS touch $dir/$tfile
-       $RUNAS cat $dir/$tfile
-       changelog_dump
-}
-
-check_events() {
-       grep 01CREAT $* || error "01CREAT event not found"
-       grep -E "10OPEN.*j=touch.*m=-w-" $* || error "10OPEN event not found (1)"
-       grep -E "11CLOSE.*j=touch" $* || error "11CLOSE event not found (1)"
-       grep -E "10OPEN.*j=cat.*m=r--" $* || error "10OPEN event not found (2)"
-       grep -E "11CLOSE.*j=cat" $* || error "11CLOSE event not found (2)"
-}
-
-check_audit_files() {
-       local tfid=$1
-       local lfiles
-
-       lfiles=$(find $LAUDIT_DUMP_PATH/users/$RUNAS_ID:$RUNAS_ID/$(date +%Y) \
-                       -type f)
-       [ -n "$lfiles" ] || error "'users' file not present"
-       echo "Checking 'users' audit files"
-       check_events $lfiles
-
-       lfiles=$(find $LAUDIT_DUMP_PATH/files/$tfid/$(date +%Y) -type f)
-       [ -n "$lfiles" ] || error "'files' file not present"
-       echo "Checking 'files' audit files"
-       check_events $lfiles
-}
-
-check_audit_report() {
-       local tfid=$1
-       local filepath=$2
-       local report=$(mktemp)
-
-       $LAUDIT_REPORT -u $RUNAS_ID:$RUNAS_ID $LAUDIT_CONF_FILE > $report ||
-               error "$LAUDIT_REPORT -u $RUNAS_ID:$RUNAS_ID failed"
-       echo "Checking audit report for user $RUNAS_ID:$RUNAS_ID"
-       check_events $report
-
-       $LAUDIT_REPORT -f $tfid $LAUDIT_CONF_FILE > $report ||
-               error "$LAUDIT_REPORT -f $tfid failed"
-       echo "Checking audit report for FID $tfid"
-       check_events $report
-
-       $LAUDIT_REPORT -f $filepath $LAUDIT_CONF_FILE > $report ||
-               error "$LAUDIT_REPORT -f $filepath failed"
-       echo "Checking audit report for file $filepath"
-       check_events $report
-}
-
-mkdir $LAUDIT_DUMP_PATH
-stack_trap cleanup_sanity_laudit EXIT
-setup_changelogs
-generate_conf_file
-
-test_1() {
-       local tfid
-       local lfiles
-
-       $LFS setdirstripe -c1 -i0 $DIR/$tdir
-       chmod 777 $DIR/$tdir
-       create_simple_files $DIR/$tdir
-       rm -rf $LAUDIT_DUMP_PATH/*
-       $LAUDIT -p $LAUDIT_CONF_FILE || error "laudit failed"
-
-       tfid=$($LFS path2fid $DIR/$tdir/$tfile)
-       check_audit_files $tfid
-       check_audit_report $tfid $DIR/$tdir/$tfile
-
-       if [ $MDSCOUNT -ge 2 ]; then
-               $LFS setdirstripe -c1 -i1 $DIR/${tdir}2
-               chmod 777 $DIR/${tdir}2
-               create_simple_files $DIR/${tdir}2
-               rm -rf $LAUDIT_DUMP_PATH/*
-               $LAUDIT -p $LAUDIT_CONF_FILE || error "laudit failed"
-
-               tfid=$($LFS path2fid $DIR/${tdir}2/$tfile)
-               check_audit_files $tfid
-               check_audit_report $tfid $DIR/${tdir}2/$tfile
-       fi
-}
-run_test 1 "laudit simple files"
-
-test_2() {
-       local tfid
-       local lfiles
-
-       $LFS setdirstripe -c1 -i0 $DIR/$tdir
-       chmod 777 $DIR/$tdir
-
-       rm -rf $LAUDIT_DUMP_PATH/*
-       $LAUDIT -p -d $LAUDIT_CONF_FILE || error "cannot launch laudit"
-
-       create_simple_files $DIR/$tdir
-       sleep 20 # twice the parse_interval_sec
-
-       tfid=$($LFS path2fid $DIR/$tdir/$tfile)
-       check_audit_files $tfid
-       check_audit_report $tfid $DIR/$tdir/$tfile
-       killall laudit
-
-       if [ $MDSCOUNT -ge 2 ]; then
-               $LFS setdirstripe -c1 -i1 $DIR/${tdir}2
-               chmod 777 $DIR/${tdir}2
-               rm -rf $LAUDIT_DUMP_PATH/*
-               $LAUDIT -p -d $LAUDIT_CONF_FILE || error "cannot launch laudit"
-               create_simple_files $DIR/${tdir}2
-               sleep 20 # twice the parse_interval_sec
-
-               tfid=$($LFS path2fid $DIR/${tdir}2/$tfile)
-               check_audit_files $tfid
-               check_audit_report $tfid $DIR/${tdir}2/$tfile
-       fi
-}
-run_test 2 "laudit daemon mode"
-
-complete_test $SECONDS
-check_and_cleanup_lustre
-exit_status
index bfaef81..c88e737 100644 (file)
@@ -28,4 +28,3 @@ sanity-pfl
 sanity-pcc
 sanity-lnet
 sanity-lipe
-sanity-laudit