------------------------------------------------------------ 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; }