Allow the kernel to ask for removal of a client record. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- utils/clstated/clstated.c | 34 +++++++++++++++++++++++++++- utils/clstated/sqlite.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ utils/clstated/sqlite.h | 1 + 3 files changed, 88 insertions(+), 1 deletions(-) diff --git a/utils/clstated/clstated.c b/utils/clstated/clstated.c index 95ac696..54214cb 100644 --- a/utils/clstated/clstated.c +++ b/utils/clstated/clstated.c @@ -147,6 +147,36 @@ clstate_create(struct clstate_client *clnt) } static void +clstate_remove(struct clstate_client *clnt) +{ + int ret; + ssize_t bsize, wsize; + struct clstate_msg *cmsg = &clnt->cl_msg; + + xlog(D_GENERAL, "%s: expire client record. cm_addr=%s", __func__, + cmsg->cm_addr); + + ret = clstate_remove_client(cmsg->cm_addr, cmsg->cm_u.cm_id, + cmsg->cm_len); + + /* set up reply */ + cmsg->cm_status = ret ? -EREMOTEIO : ret; + cmsg->cm_len = 0; + memset(cmsg->cm_addr, 0, sizeof(cmsg->cm_addr) + + sizeof(cmsg->cm_u.cm_id)); + + bsize = sizeof(*cmsg); + + xlog(D_GENERAL, "Doing downcall with status %d", cmsg->cm_status); + wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize); + if (wsize != bsize) { + xlog(L_ERROR, "%s: problem writing to clstate pipe (%ld): %m", + __func__, wsize); + clstate_pipe_reopen(clnt); + } +} + +static void clstatecb(int UNUSED(fd), short which, void *data) { ssize_t len; @@ -168,8 +198,10 @@ clstatecb(int UNUSED(fd), short which, void *data) clstate_create(clnt); break; case Cl_Expire: - case Cl_NrToReclaim: + clstate_remove(clnt); + break; case Cl_Allow: + case Cl_NrToReclaim: case Cl_GraceDone: xlog_warn("%s: command %u is not yet implemented", __func__, cmsg->cm_cmd); diff --git a/utils/clstated/sqlite.c b/utils/clstated/sqlite.c index ae83634..78ce6b4 100644 --- a/utils/clstated/sqlite.c +++ b/utils/clstated/sqlite.c @@ -349,3 +349,57 @@ out_detach: clstate_db_detach(dbname); return ret; } + +/* Remove a client record */ +int +clstate_remove_client(const unsigned char *addr, const unsigned char *clname, + const size_t namelen) +{ + int ret; + char *err = NULL; + char dbname[CLSTATE_MAX_ADDRESS_LEN]; + sqlite3_stmt *stmt = NULL; + + addr_to_dbname((const char *)addr, dbname); + + ret = clstate_db_attach(dbname); + if (ret != SQLITE_OK) + return ret; + + ret = snprintf(buf, sizeof(buf), + "DELETE FROM '%s'.clients WHERE id==?", dbname); + if (ret < 0) { + goto out_detach; + } else if ((size_t)ret >= sizeof(buf)) { + ret = -EINVAL; + goto out_detach; + } + + ret = sqlite3_prepare_v2(dbh, buf, ret + 1, &stmt, NULL); + if (ret != SQLITE_OK) { + xlog(D_GENERAL, "Statement prepare failed: %d", ret); + 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: %d", ret); + goto out_err; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_DONE) + ret = SQLITE_OK; + else + xlog(D_GENERAL, "Unexpected return code from insert: %s", + sqlite3_errmsg(dbh)); + +out_err: + xlog(D_GENERAL, "%s returning %d", __func__, ret); + sqlite3_finalize(stmt); + sqlite3_free(err); +out_detach: + clstate_db_detach(dbname); + return ret; +} diff --git a/utils/clstated/sqlite.h b/utils/clstated/sqlite.h index 4f81745..6f5637f 100644 --- a/utils/clstated/sqlite.h +++ b/utils/clstated/sqlite.h @@ -23,5 +23,6 @@ void clstate_set_topdir(char *topdir); int clstate_maindb_init(void); int clstate_insert_client(const unsigned char *addr, const unsigned char *clname, const size_t namelen); +int clstate_remove_client(const unsigned char *addr, const unsigned char *clname, const size_t namelen); #endif /* _SQLITE_H */ -- 1.7.1 -- 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