------------------------------------------------------------
revno: 692
revision-id:[EMAIL PROTECTED]
parent: [EMAIL PROTECTED]
committer: Andrew Tridgell <[EMAIL PROTECTED]>
branch nick: s3-ctdb-tridge
timestamp: Mon 2008-01-21 23:24:50 +1100
message:
dmapi got into a state on a test cluster where dm_get_dmattr returned
-1/EINVAL but it was impossible to delete the stale session, and the
session still showed up in dm_getall_sessions(). This patch copes with
that by changing to a new session name when the error occurs.
modified:
source/modules/vfs_tsmsm.c vfs_tsmsm.c-20070827024912-m3pirz28sej5g6pz-1
source/smbd/dmapi.c dmapi.c-20070210173807-1wjifrbwaz6xnmgl-1002
=== modified file 'source/modules/vfs_tsmsm.c'
--- a/source/modules/vfs_tsmsm.c 2008-01-17 04:09:18 +0000
+++ b/source/modules/vfs_tsmsm.c 2008-01-21 12:24:50 +0000
@@ -107,6 +107,7 @@
tsmd->attrib_name = lp_parm_talloc_string(SNUM(handle->conn), "tsmsm",
"dmapi attribute",
DM_ATTRIB_OBJECT);
+ talloc_steal(tsmd, tsmd->attrib_name);
fres = lp_parm_const_string(SNUM(handle->conn), "tsmsm", "online
ratio", NULL);
if (fres == NULL) {
@@ -139,6 +140,7 @@
dm_attrname_t dmname;
int ret;
const dm_sessid_t *sessionp;
+ char buf[1];
/* if the file has more than FILE_IS_ONLINE_RATIO of blocks available,
then assume it is not offline (it may not be 100%, as it could be
sparse) */
@@ -171,8 +173,17 @@
memset(&dmname, 0, sizeof(dmname));
strlcpy((char *)&dmname.an_chars[0], tsmd->attrib_name,
sizeof(dmname.an_chars));
+again:
ret = dm_get_dmattr(*sessionp, dmhandle, dmhandle_len,
- DM_NO_TOKEN, &dmname, 0, NULL, &rlen);
+ DM_NO_TOKEN, &dmname, sizeof(buf), buf, &rlen);
+
+ if (ret == -1 && errno == EINVAL) {
+ DEBUG(0,("Stale DMAPI session - recreating\n"));
+ if (dmapi_new_session()) {
+ sessionp = dmapi_get_current_session();
+ goto again;
+ }
+ }
/* its offline if the dmapi attribute exists */
*offline = (ret == 0 || (ret == -1 && errno == E2BIG));
=== modified file 'source/smbd/dmapi.c'
--- a/source/smbd/dmapi.c 2008-01-17 04:09:18 +0000
+++ b/source/smbd/dmapi.c 2008-01-21 12:24:50 +0000
@@ -48,7 +48,7 @@
#define DMAPI_TRACE 10
static dm_sessid_t samba_dmapi_session = DM_NO_SESSION;
-
+static unsigned session_num;
/*
Initialise DMAPI session. The session is persistant kernel state,
@@ -63,9 +63,24 @@
dm_sessid_t *sessions = NULL;
int i, err;
char *version;
+ char *session_name;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+
+ if (session_num == 0) {
+ session_name = DMAPI_SESSION_NAME;
+ } else {
+ session_name = talloc_asprintf(tmp_ctx, "%s%u",
DMAPI_SESSION_NAME,
+ session_num);
+ }
+ if (session_name == NULL) {
+ DEBUG(0,("Out of memory in dmapi_init_session\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
if (dm_init_service(&version) < 0) {
DEBUG(0,("dm_init_service failed - disabling DMAPI\n"));
+ talloc_free(tmp_ctx);
return -1;
}
@@ -74,10 +89,10 @@
do {
dm_sessid_t *new_sessions;
nsessions *= 2;
- new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions,
+ new_sessions = TALLOC_REALLOC_ARRAY(tmp_ctx, sessions,
dm_sessid_t, nsessions);
if (new_sessions == NULL) {
- talloc_free(sessions);
+ talloc_free(tmp_ctx);
return -1;
}
sessions = new_sessions;
@@ -88,14 +103,14 @@
DEBUGADD(DMAPI_TRACE,
("failed to retrieve DMAPI sessions: %s\n",
strerror(errno)));
- talloc_free(sessions);
+ talloc_free(tmp_ctx);
return -1;
}
for (i = 0; i < nsessions; ++i) {
err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen);
buf[sizeof(buf) - 1] = '\0';
- if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) {
+ if (err == 0 && strcmp(session_name, buf) == 0) {
samba_dmapi_session = sessions[i];
DEBUGADD(DMAPI_TRACE,
("attached to existing DMAPI session "
@@ -104,32 +119,28 @@
}
}
- talloc_free(sessions);
-
/* No session already defined. */
if (samba_dmapi_session == DM_NO_SESSION) {
- err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME,
+ err = dm_create_session(DM_NO_SESSION, session_name,
&samba_dmapi_session);
if (err < 0) {
DEBUGADD(DMAPI_TRACE,
("failed to create new DMAPI session: %s\n",
strerror(errno)));
samba_dmapi_session = DM_NO_SESSION;
+ talloc_free(tmp_ctx);
return -1;
}
DEBUG(0,("created new DMAPI session named '%s' for %s\n",
- DMAPI_SESSION_NAME, version));
+ session_name, version));
}
if (samba_dmapi_session != DM_NO_SESSION) {
set_effective_capability(DMAPI_ACCESS_CAPABILITY);
}
- /*
- Note that we never end the DMAPI session. It gets re-used
- if possible
- */
+ talloc_free(tmp_ctx);
return 0;
}
@@ -164,6 +175,24 @@
return samba_dmapi_session != DM_NO_SESSION;
}
+/*
+ only call this when you get back an EINVAL error indicating that the
+ session you are using is invalid. This destroys the existing session
+ and creates a new one.
+ */
+BOOL dmapi_new_session(void)
+{
+ if (dmapi_have_session()) {
+ /* try to destroy the old one - this may not succeed */
+ dm_destroy_session(samba_dmapi_session);
+ }
+ samba_dmapi_session = DM_NO_SESSION;
+ become_root();
+ session_num++;
+ dmapi_init_session();
+ unbecome_root();
+ return samba_dmapi_session != DM_NO_SESSION;
+}
uint32 dmapi_file_flags(const char * const path)
{
@@ -171,7 +200,7 @@
int err;
dm_eventset_t events = {0};
uint nevents;
- void *session_ptr;
+ const void *session_ptr;
void *dm_handle;
size_t dm_handle_len;
uint32 flags = 0;
@@ -235,8 +264,7 @@
* interested in trapping read events is that part of the file is
* offline.
*/
- DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n",
- path, events));
+ DEBUG(DMAPI_TRACE, ("DMAPI got event list for %s\n", path));
if (DMEV_ISSET(DM_EVENT_READ, events)) {
flags = FILE_ATTRIBUTE_OFFLINE;
}