Rev 692: dmapi got into a state on a test cluster where dm_get_dmattr returned in http://samba.org/~tridge/3_0-ctdb

tridge at samba.org tridge at samba.org
Mon Jan 21 12:26:53 GMT 2008


------------------------------------------------------------
revno: 692
revision-id:tridge at samba.org-20080121122450-er192pvz90my47kp
parent: tridge at samba.org-20080118202503-05j7288nbv9cbeup
committer: Andrew Tridgell <tridge at samba.org>
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;
 	}



More information about the samba-cvs mailing list