[PATCH v4 06/11] nfsdcld: have daemon pass client row index back to kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In order to deal with some potential problems with lock recovery, we'll
need a way to tag clustered locks in such a way that we know what client
owns them. In order to do that, we need a way to uniquely the client.

We could use the nfs_client_id4 value that the client sends, but it's
too long to be reasonable for this purpose. We could also hash that
down, but there's always the potential for hash collisions. What would
be best is a value that's unique for a particular clientid at a
particular time.

Add an autoincrement index field to the clients table, and have the
check and insert routines grab that and pass it back to the kernel.

For now, the kernel ignores this value, but eventually the locking code
can use this to designate ownership of a lock.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
 utils/nfsdcld/nfsdcld.c |    8 +++++-
 utils/nfsdcld/sqlite.c  |   53 ++++++++++++++++++++++++++++++++++------------
 utils/nfsdcld/sqlite.h  |    6 +++-
 3 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c
index 151dd16..bd643b0 100644
--- a/utils/nfsdcld/nfsdcld.c
+++ b/utils/nfsdcld/nfsdcld.c
@@ -117,15 +117,17 @@ static void
 cld_create(struct cld_client *clnt)
 {
 	int ret;
+	int64_t index;
 	ssize_t bsize, wsize;
 	struct cld_msg *cmsg = &clnt->cl_msg;
 
 	xlog(D_GENERAL, "%s: create client record.", __func__);
 
 	ret = sqlite_insert_client(cmsg->cm_u.cm_name.cn_id,
-				   cmsg->cm_u.cm_name.cn_len);
+				   cmsg->cm_u.cm_name.cn_len, &index);
 
 	cmsg->cm_status = ret ? -EREMOTEIO : ret;
+	cmsg->cm_u.cm_index = index;
 
 	bsize = sizeof(*cmsg);
 
@@ -164,16 +166,18 @@ static void
 cld_check(struct cld_client *clnt)
 {
 	int ret;
+	int64_t index;
 	ssize_t bsize, wsize;
 	struct cld_msg *cmsg = &clnt->cl_msg;
 
 	xlog(D_GENERAL, "%s: check client record", __func__);
 
 	ret = sqlite_check_client(cmsg->cm_u.cm_name.cn_id,
-				  cmsg->cm_u.cm_name.cn_len);
+				  cmsg->cm_u.cm_name.cn_len, &index);
 
 	/* set up reply */
 	cmsg->cm_status = ret ? -EACCES : ret;
+	cmsg->cm_u.cm_index = index;
 
 	bsize = sizeof(*cmsg);
 
diff --git a/utils/nfsdcld/sqlite.c b/utils/nfsdcld/sqlite.c
index a0bcf2f..85e76a1 100644
--- a/utils/nfsdcld/sqlite.c
+++ b/utils/nfsdcld/sqlite.c
@@ -191,7 +191,8 @@ sqlite_maindb_init(char *topdir)
 
 	/* now create the "clients" table */
 	ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS clients "
-				"(id BLOB PRIMARY KEY, time INTEGER);",
+				"(idx INTEGER PRIMARY KEY AUTOINCREMENT, "
+				"id BLOB UNIQUE, time INTEGER);",
 				NULL, NULL, &err);
 	if (ret != SQLITE_OK) {
 		xlog(L_ERROR, "Unable to create clients table: %s", err);
@@ -218,12 +219,14 @@ 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,
+		     int64_t *index)
 {
 	int ret;
 	sqlite3_stmt *stmt = NULL;
 
-	ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients VALUES "
+	ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
+				      "(id, time) VALUES "
 				      "(?, strftime('%s', 'now'));", -1,
 					&stmt, NULL);
 	if (ret != SQLITE_OK) {
@@ -240,12 +243,38 @@ sqlite_insert_client(const unsigned char *clname, const size_t namelen)
 	}
 
 	ret = sqlite3_step(stmt);
-	if (ret == SQLITE_DONE)
-		ret = SQLITE_OK;
-	else
+	if (ret != SQLITE_DONE) {
 		xlog(D_GENERAL, "Unexpected return code from insert: %s",
 				sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	sqlite3_finalize(stmt);
+	stmt = NULL;
+
+	ret = sqlite3_prepare_v2(dbh, "SELECT index FROM clients WHERE "
+				      "id==?", -1, &stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(D_GENERAL, "Unable to prepare update statement: %s",
+				sqlite3_errmsg(dbh));
+		goto out_err;
+	}
 
+	ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen,
+				SQLITE_STATIC);
+	if (ret != SQLITE_OK) {
+		xlog(D_GENERAL, "Bind blob failed: %s", sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_step(stmt);
+	if (ret != SQLITE_ROW) {
+		xlog(D_GENERAL, "Unexpected return code from select: %d", ret);
+		goto out_err;
+	}
+
+	ret = SQLITE_OK;
+	*index = (int64_t)sqlite3_column_int64(stmt, 0);
 out_err:
 	xlog(D_GENERAL, "%s: returning %d", __func__, ret);
 	sqlite3_finalize(stmt);
@@ -258,12 +287,13 @@ 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,
+		    int64_t *index)
 {
 	int ret;
 	sqlite3_stmt *stmt = NULL;
 
-	ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE "
+	ret = sqlite3_prepare_v2(dbh, "SELECT index FROM clients WHERE "
 				      "id==?", -1, &stmt, NULL);
 	if (ret != SQLITE_OK) {
 		xlog(D_GENERAL, "Unable to prepare update statement: %s",
@@ -284,12 +314,7 @@ sqlite_check_client(const unsigned char *clname, const size_t namelen)
 		goto out_err;
 	}
 
-	ret = sqlite3_column_int(stmt, 0);
-	xlog(D_GENERAL, "Select returned %d rows", ret);
-	if (ret != 1) {
-		ret = -EACCES;
-		goto out_err;
-	}
+	*index = (int64_t)sqlite3_column_int64(stmt, 0);
 
 	sqlite3_finalize(stmt);
 	stmt = NULL;
diff --git a/utils/nfsdcld/sqlite.h b/utils/nfsdcld/sqlite.h
index f6ed348..0476bef 100644
--- a/utils/nfsdcld/sqlite.h
+++ b/utils/nfsdcld/sqlite.h
@@ -21,8 +21,10 @@
 #define _SQLITE_H_
 
 int sqlite_maindb_init(char *topdir);
-int sqlite_insert_client(const unsigned char *clname, const size_t namelen);
-int sqlite_check_client(const unsigned char *clname, const size_t namelen);
+int sqlite_insert_client(const unsigned char *clname, const size_t namelen,
+			 int64_t *index);
+int sqlite_check_client(const unsigned char *clname, const size_t namelen,
+			int64_t *index);
 int sqlite_remove_unreclaimed(const time_t grace_start);
 
 #endif /* _SQLITE_H */
-- 
1.7.7.5

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux