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

Reply via email to