diff --git a/Makefile.am b/Makefile.am
index c9e9f87..6f3f3d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,34 +9,6 @@ MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = \
autogen.sh \
\
- debian/changelog \
- debian/control \
- debian/copyright \
- debian/etc.exports \
- debian/idmapd.conf \
- debian/nfs-common.conffiles \
- debian/nfs-common.default \
- debian/nfs-common.dirs \
- debian/nfs-common.files \
- debian/nfs-common.init \
- debian/nfs-common.install \
- debian/nfs-common.postinst \
- debian/nfs-common.postrm \
- debian/nfs-common.prerm \
- debian/nfs-kernel-server.NEWS \
- debian/nfs-kernel-server.conffiles \
- debian/nfs-kernel-server.default \
- debian/nfs-kernel-server.dirs \
- debian/nfs-kernel-server.init \
- debian/nfs-kernel-server.postinst \
- debian/nfs-kernel-server.postrm \
- debian/nfs-kernel-server.prerm \
- debian/nhfsstone.dirs \
- debian/nhfsstone.files \
- debian/nhfsstone.postinst \
- debian/nhfsstone.prerm \
- debian/rules \
- \
aclocal/bsdsignals.m4 \
aclocal/nfs-utils.m4 \
aclocal/kerberos5.m4 \
diff --git a/support/include/Makefile.am b/support/include/Makefile.am
index 4b33ee9..5c80c8b 100644
--- a/support/include/Makefile.am
+++ b/support/include/Makefile.am
@@ -3,6 +3,7 @@
SUBDIRS = nfs rpcsvc sys
noinst_HEADERS = \
+ cld.h \
exportfs.h \
ha-callout.h \
misc.h \
@@ -10,9 +11,13 @@ noinst_HEADERS = \
nfs_paths.h \
nfslib.h \
nfsrpc.h \
+ nls.h \
nsm.h \
+ pseudoflavors.h \
rpcmisc.h \
+ sockaddr.h \
tcpwrapper.h \
+ v4root.h \
xio.h \
xlog.h \
xmalloc.h \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index faa8197..1f96264 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -11,3 +11,4 @@ SUBDIRS = nsm_client
MAINTAINERCLEANFILES = Makefile.in
TESTS = t0001-statd-basic-mon-unmon.sh
+EXTRA_DIST = test-lib.sh $(TESTS)
diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am
index 4c15346..a8fc131 100644
--- a/tests/nsm_client/Makefile.am
+++ b/tests/nsm_client/Makefile.am
@@ -7,6 +7,7 @@ GENFILES_H = nlm_sm_inter.h
GENFILES = $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+EXTRA_DIST = nlm_sm_inter.x
check_PROGRAMS = nsm_client
nsm_client_SOURCES = $(GENFILES) nsm_client.c
diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
index af59791..a4e9c56 100644
--- a/utils/gssd/Makefile.am
+++ b/utils/gssd/Makefile.am
@@ -8,7 +8,6 @@ sbin_PREFIXED = gssd svcgssd
sbin_PROGRAMS = $(sbin_PREFIXED)
EXTRA_DIST = \
- gss_destroy_creds \
$(man8_MANS)
COMMON_SRCS = \
diff --git a/utils/idmapd/Makefile.am b/utils/idmapd/Makefile.am
index 58b33ec..c2f8ba1 100644
--- a/utils/idmapd/Makefile.am
+++ b/utils/idmapd/Makefile.am
@@ -7,8 +7,7 @@ KPREFIX = @kprefix@
sbin_PROGRAMS = idmapd
EXTRA_DIST = \
- $(man8_MANS) \
- idmapd.conf
+ $(man8_MANS)
idmapd_SOURCES = \
idmapd.c \
diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
index 5810936..e24f3bd 100644
--- a/utils/mount/Makefile.am
+++ b/utils/mount/Makefile.am
@@ -8,19 +8,21 @@ man8_MANS = mount.nfs.man umount.nfs.man
man5_MANS = nfs.man
sbin_PROGRAMS = mount.nfs
-EXTRA_DIST = nfsmount.x $(man8_MANS) $(man5_MANS)
+EXTRA_DIST = nfsmount.conf $(man8_MANS) $(man5_MANS)
mount_common = error.c network.c token.c \
parse_opt.c parse_dev.c \
nfsmount.c nfs4mount.c stropts.c\
mount_constants.h error.h network.h token.h \
parse_opt.h parse_dev.h \
- nfs4_mount.h nfs_mount4.h stropts.h version.h \
- mount_config.h utils.c utils.h
+ nfs4_mount.h stropts.h version.h \
+ mount_config.h utils.c utils.h \
+ nfs_mount.h
if MOUNT_CONFIG
mount_common += configfile.c
man5_MANS += nfsmount.conf.man
-EXTRA_DIST += nfsmount.conf
+else
+EXTRA_DIST += nfsmount.conf.man
endif
mount_nfs_LDADD = ../../support/nfs/libnfs.a \
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
index 7db968b..9e1ab5c 100644
--- a/utils/mountd/Makefile.am
+++ b/utils/mountd/Makefile.am
@@ -7,6 +7,7 @@ RPCPREFIX = rpc.
KPREFIX = @kprefix@
sbin_PROGRAMS = mountd
+noinst_HEADERS = fsloc.h
mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
svc_run.c fsloc.c v4root.c mountd.h
mountd_LDADD = ../../support/export/libexport.a \
diff --git a/utils/nfsd/Makefile.am b/utils/nfsd/Makefile.am
index 1536065..39a6e6f 100644
--- a/utils/nfsd/Makefile.am
+++ b/utils/nfsd/Makefile.am
@@ -7,6 +7,7 @@ RPCPREFIX = rpc.
KPREFIX = @kprefix@
sbin_PROGRAMS = nfsd
+noinst_HEADERS = nfssvc.h
nfsd_SOURCES = nfsd.c nfssvc.c
nfsd_LDADD = ../../support/nfs/libnfs.a $(LIBTIRPC)
diff --git a/utils/nfsdcltrack/Makefile.am b/utils/nfsdcltrack/Makefile.am
index a860ffb..d603f92 100644
--- a/utils/nfsdcltrack/Makefile.am
+++ b/utils/nfsdcltrack/Makefile.am
@@ -6,6 +6,8 @@ EXTRA_DIST = $(man8_MANS)
AM_CFLAGS += -D_LARGEFILE64_SOURCE
sbin_PROGRAMS = nfsdcltrack
+noinst_HEADERS = sqlite.h
+
nfsdcltrack_SOURCES = nfsdcltrack.c sqlite.c
nfsdcltrack_LDADD = ../../support/nfs/libnfs.a $(LIBSQLITE) $(LIBCAP)
diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
index 4334340..fcdda7f 100644
--- a/utils/nfsdcltrack/nfsdcltrack.c
+++ b/utils/nfsdcltrack/nfsdcltrack.c
@@ -37,6 +37,7 @@
#include <libgen.h>
#include <sys/inotify.h>
#include <dirent.h>
+#include <limits.h>
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/prctl.h>
#include <sys/capability.h>
@@ -49,6 +50,8 @@
#define CLD_DEFAULT_STORAGEDIR NFS_STATEDIR "/nfsdcltrack"
#endif
+#define NFSD_END_GRACE_FILE "/proc/fs/nfsd/v4_end_grace"
+
/* defined by RFC 3530 */
#define NFS4_OPAQUE_LIMIT 1024
@@ -210,6 +213,64 @@ cltrack_set_caps(void)
return ret;
}
+/* Inform the kernel that it's OK to lift nfsd's grace period */
+static void
+cltrack_lift_grace_period(void)
+{
+ int fd;
+
+ fd = open(NFSD_END_GRACE_FILE, O_WRONLY);
+ if (fd < 0) {
+ /* Don't warn if file isn't present */
+ if (errno != ENOENT)
+ xlog(L_WARNING, "Unable to open %s: %m",
+ NFSD_END_GRACE_FILE);
+ return;
+ }
+
+ if (write(fd, "Y", 1) < 0)
+ xlog(L_WARNING, "Unable to write to %s: %m",
+ NFSD_END_GRACE_FILE);
+
+ close(fd);
+ return;
+}
+
+/*
+ * Fetch the contents of the NFSDCLTRACK_GRACE_START env var. If it's not set
+ * or there's an error converting it to time_t, then return LONG_MAX.
+ */
+static time_t
+cltrack_get_grace_start(void)
+{
+ time_t grace_start;
+ char *end;
+ char *grace_start_str = getenv("NFSDCLTRACK_GRACE_START");
+
+ if (!grace_start_str)
+ return LONG_MAX;
+
+ errno = 0;
+ grace_start = strtol(grace_start_str, &end, 0);
+ /* Problem converting or value is too large? */
+ if (errno)
+ return LONG_MAX;
+
+ return grace_start;
+}
+
+static bool
+cltrack_reclaims_complete(void)
+{
+ time_t grace_start = cltrack_get_grace_start();
+
+ /* Don't query DB if we didn't get a valid boot time */
+ if (grace_start == LONG_MAX)
+ return false;
+
+ return !sqlite_query_reclaiming(grace_start);
+}
+
static int
cltrack_init(const char __attribute__((unused)) *unused)
{
@@ -241,7 +302,7 @@ cltrack_init(const char __attribute__((unused)) *unused)
}
/* set up storage db */
- ret = sqlite_maindb_init(storagedir);
+ ret = sqlite_prepare_dbh(storagedir);
if (ret) {
xlog(L_ERROR, "Failed to init database: %d", ret);
/*
@@ -250,15 +311,36 @@ cltrack_init(const char __attribute__((unused)) *unused)
* stop upcalling until the problem is resolved.
*/
ret = -EACCES;
+ } else {
+ if (cltrack_reclaims_complete())
+ cltrack_lift_grace_period();
}
+
return ret;
}
+/*
+ * Fetch the contents of the NFSDCLTRACK_CLIENT_HAS_SESSION env var. If
+ * it's set and the first character is 'Y' then return true. Otherwise
+ * return false.
+ */
+static bool
+cltrack_client_has_session(void)
+{
+ char *has_session = getenv("NFSDCLTRACK_CLIENT_HAS_SESSION");
+
+ if (has_session && *has_session == 'Y')
+ return true;
+
+ return false;
+}
+
static int
cltrack_create(const char *id)
{
int ret;
ssize_t len;
+ bool has_session;
xlog(D_GENERAL, "%s: create client record.", __func__);
@@ -270,7 +352,12 @@ cltrack_create(const char *id)
if (len < 0)
return (int)len;
- ret = sqlite_insert_client(blob, len);
+ has_session = cltrack_client_has_session();
+
+ ret = sqlite_insert_client(blob, len, has_session, false);
+
+ if (!ret && has_session && cltrack_reclaims_complete())
+ cltrack_lift_grace_period();
return ret ? -EREMOTEIO : ret;
}
@@ -297,7 +384,8 @@ cltrack_remove(const char *id)
}
static int
-cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
+cltrack_check_legacy(const unsigned char *blob, const ssize_t len,
+ bool has_session)
{
int ret;
struct stat st;
@@ -323,7 +411,7 @@ cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
}
/* Dir exists, try to insert record into db */
- ret = sqlite_insert_client(blob, len);
+ ret = sqlite_insert_client(blob, len, has_session, has_session);
if (ret) {
xlog(D_GENERAL, "Failed to insert client: %d", ret);
return -EREMOTEIO;
@@ -343,6 +431,7 @@ cltrack_check(const char *id)
{
int ret;
ssize_t len;
+ bool has_session;
xlog(D_GENERAL, "%s: check client record", __func__);
@@ -354,9 +443,11 @@ cltrack_check(const char *id)
if (len < 0)
return (int)len;
- ret = sqlite_check_client(blob, len);
+ has_session = cltrack_client_has_session();
+
+ ret = sqlite_check_client(blob, len, has_session);
if (ret)
- ret = cltrack_check_legacy(blob, len);
+ ret = cltrack_check_legacy(blob, len, has_session);
return ret ? -EPERM : ret;
}
diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
index bac6789..eb1711a 100644
--- a/utils/nfsdcltrack/sqlite.c
+++ b/utils/nfsdcltrack/sqlite.c
@@ -21,17 +21,15 @@
* Explanation:
*
* This file contains the code to manage the sqlite backend database for the
- * clstated upcall daemon.
+ * nfsdcltrack usermodehelper upcall program.
*
* The main database is called main.sqlite and contains the following tables:
*
* parameters: simple key/value pairs for storing database info
*
- * clients: one column containing a BLOB with the as sent by the client
- * and a timestamp (in epoch seconds) of when the record was
- * established
- *
- * FIXME: should we also record the fsid being accessed?
+ * clients: an "id" column containing a BLOB with the long-form clientid as
+ * sent by the client, a "time" column containing a timestamp (in
+ * epoch seconds) of when the record was last updated.
*/
#ifdef HAVE_CONFIG_H
@@ -52,10 +50,10 @@
#include "xlog.h"
-#define CLD_SQLITE_SCHEMA_VERSION 1
+#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
/* in milliseconds */
-#define CLD_SQLITE_BUSY_TIMEOUT 10000
+#define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
/* private data structures */
@@ -90,135 +88,192 @@ mkdir_if_not_exist(const char *dirname)
return ret;
}
-/* Open the database and set up the database handle for it */
-int
-sqlite_prepare_dbh(const char *topdir)
+static int
+sqlite_query_schema_version(void)
{
int ret;
+ sqlite3_stmt *stmt = NULL;
- /* Do nothing if the database handle is already set up */
- if (dbh)
- return 0;
-
- ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
- if (ret < 0)
- return ret;
-
- buf[PATH_MAX - 1] = '\0';
-
- ret = sqlite3_open(buf, &dbh);
+ /* prepare select query */
+ ret = sqlite3_prepare_v2(dbh,
+ "SELECT value FROM parameters WHERE key == \"version\";",
+ -1, &stmt, NULL);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to open main database: %d", ret);
- dbh = NULL;
- return ret;
+ xlog(L_ERROR, "Unable to prepare select statement: %s",
+ sqlite3_errmsg(dbh));
+ ret = 0;
+ goto out;
}
- ret = sqlite3_busy_timeout(dbh, CLD_SQLITE_BUSY_TIMEOUT);
- if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to set sqlite busy timeout: %d", ret);
- sqlite3_close(dbh);
- dbh = NULL;
+ /* query schema version */
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW) {
+ xlog(L_ERROR, "Select statement execution failed: %s",
+ sqlite3_errmsg(dbh));
+ ret = 0;
+ goto out;
}
+ ret = sqlite3_column_int(stmt, 0);
+out:
+ sqlite3_finalize(stmt);
return ret;
}
/*
- * Open the "main" database, and attempt to initialize it by creating the
- * parameters table and inserting the schema version into it. Ignore any errors
- * from that, and then attempt to select the version out of it again. If the
- * version appears wrong, then assume that the DB is corrupt or has been
- * upgraded, and return an error. If all of that works, then attempt to create
- * the "clients" table.
+ * Start an exclusive transaction and recheck the DB schema version. If it's
+ * still zero (indicating a new database) then set it up. If that all works,
+ * then insert schema version into the parameters table and commit the
+ * transaction. On any error, rollback the transaction.
*/
int
-sqlite_maindb_init(const char *topdir)
+sqlite_maindb_init_v1(void)
{
int ret;
char *err = NULL;
- sqlite3_stmt *stmt = NULL;
- ret = mkdir_if_not_exist(topdir);
- if (ret)
+ /* Start a transaction */
+ ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
+ &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to begin transaction: %s", err);
return ret;
+ }
- ret = sqlite_prepare_dbh(topdir);
- if (ret)
- return ret;
+ /*
+ * Check schema version again. This time, under an exclusive
+ * transaction to guard against racing DB setup attempts
+ */
+ ret = sqlite_query_schema_version();
+ switch (ret) {
+ case 0:
+ /* Query failed again -- set up DB */
+ break;
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
+ /* Someone else raced in and set it up */
+ ret = 0;
+ goto rollback;
+ default:
+ /* Something went wrong -- fail! */
+ ret = -EINVAL;
+ goto rollback;
+ }
- /* Try to create table */
- ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS parameters "
+ ret = sqlite3_exec(dbh, "CREATE TABLE parameters "
"(key TEXT PRIMARY KEY, value TEXT);",
NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to create parameter table: %d", ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to create parameter table: %s", err);
+ goto rollback;
}
- /* insert version into table -- ignore error if it fails */
- ret = snprintf(buf, sizeof(buf),
- "INSERT OR IGNORE INTO parameters values (\"version\", "
- "\"%d\");", CLD_SQLITE_SCHEMA_VERSION);
+ /* create the "clients" table */
+ ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
+ "time INTEGER);",
+ NULL, NULL, &err);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to create clients table: %s", err);
+ goto rollback;
+ }
+
+
+ /* insert version into parameters table */
+ ret = snprintf(buf, sizeof(buf), "INSERT OR FAIL INTO parameters "
+ "values (\"version\", \"%d\");",
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
if (ret < 0) {
- goto out_err;
+ xlog(L_ERROR, "sprintf failed!");
+ goto rollback;
} else if ((size_t)ret >= sizeof(buf)) {
+ xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
ret = -EINVAL;
- goto out_err;
+ goto rollback;
}
ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to insert into parameter table: %d",
- ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to insert into parameter table: %s", err);
+ goto rollback;
}
- ret = sqlite3_prepare_v2(dbh,
- "SELECT value FROM parameters WHERE key == \"version\";",
- -1, &stmt, NULL);
+ ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to prepare select statement: %d", ret);
- goto out_err;
+ xlog(L_ERROR, "Unable to commit transaction: %s", err);
+ goto rollback;
}
+out:
+ sqlite3_free(err);
+ return ret;
- /* check schema version */
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_ROW) {
- xlog(L_ERROR, "Select statement execution failed: %s",
+rollback:
+ /* Attempt to rollback the transaction */
+ sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
+ goto out;
+}
+
+/* Open the database and set up the database handle for it */
+int
+sqlite_prepare_dbh(const char *topdir)
+{
+ int ret;
+
+ /* Do nothing if the database handle is already set up */
+ if (dbh)
+ return 0;
+
+ ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
+ if (ret < 0)
+ return ret;
+
+ buf[PATH_MAX - 1] = '\0';
+
+ /* open a new DB handle */
+ ret = sqlite3_open(buf, &dbh);
+ if (ret != SQLITE_OK) {
+ /* try to create the dir */
+ ret = mkdir_if_not_exist(topdir);
+ if (ret)
+ goto out_close;
+
+ /* retry open */
+ ret = sqlite3_open(buf, &dbh);
+ if (ret != SQLITE_OK)
+ goto out_close;
+ }
+
+ /* set busy timeout */
+ ret = sqlite3_busy_timeout(dbh, CLTRACK_SQLITE_BUSY_TIMEOUT);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "Unable to set sqlite busy timeout: %s",
sqlite3_errmsg(dbh));
- goto out_err;
+ goto out_close;
}
- /* process SELECT result */
- ret = sqlite3_column_int(stmt, 0);
- if (ret != CLD_SQLITE_SCHEMA_VERSION) {
+ ret = sqlite_query_schema_version();
+ switch (ret) {
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
+ /* DB is already set up. Do nothing */
+ ret = 0;
+ break;
+ case 0:
+ /* Query failed -- try to set up new DB */
+ ret = sqlite_maindb_init_v1();
+ if (ret)
+ goto out_close;
+ break;
+ default:
+ /* Unknown DB version -- downgrade? Fail */
xlog(L_ERROR, "Unsupported database schema version! "
"Expected %d, got %d.",
- CLD_SQLITE_SCHEMA_VERSION, ret);
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION, ret);
ret = -EINVAL;
- goto out_err;
- }
-
- /* now create the "clients" table */
- ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS clients "
- "(id BLOB PRIMARY KEY, time INTEGER);",
- NULL, NULL, &err);
- if (ret != SQLITE_OK) {
- xlog(L_ERROR, "Unable to create clients table: %s", err);
- goto out_err;
+ goto out_close;
}
- sqlite3_free(err);
- sqlite3_finalize(stmt);
- return 0;
-
-out_err:
- if (err) {
- xlog(L_ERROR, "sqlite error: %s", err);
- sqlite3_free(err);
- }
- sqlite3_finalize(stmt);
+ return ret;
+out_close:
sqlite3_close(dbh);
+ dbh = NULL;
return ret;
}
@@ -228,14 +283,20 @@ out_err:
* Returns a non-zero sqlite error code, or SQLITE_OK (aka 0)
*/
int
-sqlite_insert_client(const unsigned char *clname, const size_t namelen)
+sqlite_insert_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session, const bool zerotime)
{
int ret;
sqlite3_stmt *stmt = NULL;
- ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients VALUES "
- "(?, strftime('%s', 'now'));", -1,
- &stmt, NULL);
+ if (zerotime)
+ ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
+ "VALUES (?, 0, ?);", -1, &stmt, NULL);
+ else
+ ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
+ "VALUES (?, strftime('%s', 'now'), ?);", -1,
+ &stmt, NULL);
+
if (ret != SQLITE_OK) {
xlog(L_ERROR, "%s: insert statement prepare failed: %s",
__func__, sqlite3_errmsg(dbh));
@@ -250,6 +311,13 @@ sqlite_insert_client(const unsigned char *clname, const size_t namelen)
goto out_err;
}
+ ret = sqlite3_bind_int(stmt, 2, (int)has_session);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: bind int failed: %s", __func__,
+ sqlite3_errmsg(dbh));
+ goto out_err;
+ }
+
ret = sqlite3_step(stmt);
if (ret == SQLITE_DONE)
ret = SQLITE_OK;
@@ -305,7 +373,8 @@ out_err:
* return an error.
*/
int
-sqlite_check_client(const unsigned char *clname, const size_t namelen)
+sqlite_check_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session)
{
int ret;
sqlite3_stmt *stmt = NULL;
@@ -340,6 +409,12 @@ sqlite_check_client(const unsigned char *clname, const size_t namelen)
goto out_err;
}
+ /* Only update timestamp for v4.0 clients */
+ if (has_session) {
+ ret = SQLITE_OK;
+ goto out_err;
+ }
+
sqlite3_finalize(stmt);
stmt = NULL;
ret = sqlite3_prepare_v2(dbh, "UPDATE OR FAIL clients SET "
@@ -398,3 +473,43 @@ sqlite_remove_unreclaimed(time_t grace_start)
sqlite3_free(err);
return ret;
}
+
+/*
+ * Are there any clients that are possibly still reclaiming? Return a positive
+ * integer (usually number of clients) if so. If not, then return 0. On any
+ * error, return non-zero.
+ */
+int
+sqlite_query_reclaiming(const time_t grace_start)
+{
+ int ret;
+ sqlite3_stmt *stmt = NULL;
+
+ ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE "
+ "time < ? OR has_session != 1", -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: unable to prepare select statement: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_bind_int64(stmt, 1, (sqlite3_int64)grace_start);
+ if (ret != SQLITE_OK) {
+ xlog(L_ERROR, "%s: bind int64 failed: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW) {
+ xlog(L_ERROR, "%s: unexpected return code from select: %s",
+ __func__, sqlite3_errmsg(dbh));
+ return ret;
+ }
+
+ ret = sqlite3_column_int(stmt, 0);
+ sqlite3_finalize(stmt);
+ xlog(D_GENERAL, "%s: there are %d clients that have not completed "
+ "reclaim", __func__, ret);
+ return ret;
+}
diff --git a/utils/nfsdcltrack/sqlite.h b/utils/nfsdcltrack/sqlite.h
index ebf04c3..06e7c04 100644
--- a/utils/nfsdcltrack/sqlite.h
+++ b/utils/nfsdcltrack/sqlite.h
@@ -21,10 +21,12 @@
#define _SQLITE_H_
int sqlite_prepare_dbh(const char *topdir);
-int sqlite_maindb_init(const char *topdir);
-int sqlite_insert_client(const unsigned char *clname, const size_t namelen);
+int sqlite_insert_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session, const bool zerotime);
int sqlite_remove_client(const unsigned char *clname, const size_t namelen);
-int sqlite_check_client(const unsigned char *clname, const size_t namelen);
+int sqlite_check_client(const unsigned char *clname, const size_t namelen,
+ const bool has_session);
int sqlite_remove_unreclaimed(const time_t grace_start);
+int sqlite_query_reclaiming(const time_t grace_start);
#endif /* _SQLITE_H */
diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
index 737a219..91cedfd 100644
--- a/utils/nfsidmap/Makefile.am
+++ b/utils/nfsidmap/Makefile.am
@@ -7,4 +7,4 @@ nfsidmap_SOURCES = nfsidmap.c
nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
MAINTAINERCLEANFILES = Makefile.in
-EXTRA_DIST = id_resolver.conf
+EXTRA_DIST = id_resolver.conf $(man8_MANS)
diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am
index 20c2d8c..ded1fd3 100644
--- a/utils/osd_login/Makefile.am
+++ b/utils/osd_login/Makefile.am
@@ -4,6 +4,6 @@
# overridden at config time.
sbindir = /sbin
-sbin_SCRIPTS = osd_login
+dist_sbin_SCRIPTS = osd_login
MAINTAINERCLEANFILES = Makefile.in
diff --git a/utils/statd/Makefile.am b/utils/statd/Makefile.am
index dc2bfc4..152b680 100644
--- a/utils/statd/Makefile.am
+++ b/utils/statd/Makefile.am
@@ -8,7 +8,7 @@ sbin_PROGRAMS = statd sm-notify
dist_sbin_SCRIPTS = start-statd
statd_SOURCES = callback.c notlist.c misc.c monitor.c hostname.c \
simu.c stat.c statd.c svc_run.c rmtcall.c \
- notlist.h statd.h system.h version.h
+ notlist.h statd.h system.h
sm_notify_SOURCES = sm-notify.c
BUILT_SOURCES = $(GENFILES)
@@ -20,7 +20,7 @@ sm_notify_LDADD = ../../support/nsm/libnsm.a \
../../support/nfs/libnfs.a \
$(LIBNSL) $(LIBCAP) $(LIBTIRPC)
-EXTRA_DIST = sim_sm_inter.x $(man8_MANS) COPYRIGHT simulate.c
+EXTRA_DIST = sim_sm_inter.x $(man8_MANS) simulate.c
if CONFIG_RPCGEN
RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen