]> arthur.barton.de Git - netatalk.git/commitdiff
Remove continous service feature
authorRalph Boehme <sloowfranklin@gmail.com>
Wed, 6 Feb 2013 07:30:17 +0000 (08:30 +0100)
committerRalph Boehme <sloowfranklin@gmail.com>
Wed, 6 Feb 2013 07:30:17 +0000 (08:30 +0100)
14 files changed:
etc/afpd/afp_dsi.c
etc/afpd/main.c
include/atalk/dsi.h
include/atalk/globals.h
include/atalk/paths.h
include/atalk/server_child.h
include/atalk/server_ipc.h
include/atalk/util.h
libatalk/dsi/dsi_getsess.c
libatalk/util/netatalk_conf.c
libatalk/util/server_child.c
libatalk/util/server_ipc.c
man/man5/afp.conf.5.tmpl
man/man8/netatalk.8.tmpl

index 8e1f90d290a08809451c121fc8cc206bfe0dcf8f..77918c56baa68b343eedd8546bd65f9a612d8ac6 100644 (file)
@@ -140,23 +140,6 @@ static void afp_dsi_die(int sig)
     }
 }
 
-/* SIGQUIT handler */
-static void ipc_reconnect_handler(int sig _U_)
-{
-    if (reconnect_ipc(AFPobj) != 0) {
-        LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
-        afp_dsi_close(AFPobj);
-        exit(EXITERR_SYS);        
-    }
-
-    if (ipc_child_write(AFPobj->ipc_fd, IPC_GETSESSION, AFPobj->sinfo.clientid_len, AFPobj->sinfo.clientid) != 0) {
-        LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC ID resend");
-        afp_dsi_close(AFPobj);
-        exit(EXITERR_SYS);        
-    }
-    LOG(log_note, logtype_afpd, "ipc_reconnect_handler: IPC reconnect done");
-}
-
 /* SIGURG handler (primary reconnect) */
 static void afp_dsi_transfer_session(int sig _U_)
 {
@@ -407,7 +390,7 @@ void afp_over_dsi_sighandlers(AFPObj *obj)
     }
 
     /* install SIGQUIT */
-    action.sa_handler = ipc_reconnect_handler;
+    action.sa_handler = afp_dsi_die;
     if ( sigaction(SIGQUIT, &action, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
index 0e0a858e84ce51b9b6bad2ee2f4118e10e837232..a66e4a86f47dae01bd3a23d6a05a5db8bbc2b07e 100644 (file)
@@ -45,7 +45,7 @@
 unsigned char nologin = 0;
 
 static AFPObj obj;
-static server_child *server_children;
+static server_child_t *server_children;
 static sig_atomic_t reloadconfig = 0;
 static sig_atomic_t gotsigchld = 0;
 
@@ -54,9 +54,8 @@ static struct pollfd *fdset;
 static struct polldata *polldata;
 static int fdset_size;          /* current allocated size */
 static int fdset_used;          /* number of used elements */
-static int disasociated_ipc_fd; /* disasociated sessions uses this fd for IPC */
 
-static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children);
+static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children);
 
 static void afp_exit(int ret)
 {
@@ -81,16 +80,6 @@ static void fd_set_listening_sockets(const AFPObj *config)
                      LISTEN_FD,
                      dsi);
     }
-
-    if (config->options.flags & OPTION_KEEPSESSIONS)
-        fdset_add_fd(config->options.connections + AFP_LISTENERS + FDSET_SAFETY,
-                     &fdset,
-                     &polldata,
-                     &fdset_used,
-                     &fdset_size,
-                     disasociated_ipc_fd,
-                     DISASOCIATED_IPC_FD,
-                     NULL);
 }
  
 static void fd_reset_listening_sockets(const AFPObj *config)
@@ -100,9 +89,6 @@ static void fd_reset_listening_sockets(const AFPObj *config)
     for (dsi = config->dsi; dsi; dsi = dsi->next) {
         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, dsi->serversock);
     }
-
-    if (config->options.flags & OPTION_KEEPSESSIONS)
-        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
 }
 
 /* ------------------ */
@@ -112,22 +98,9 @@ static void afp_goaway(int sig)
 
     case SIGTERM:
     case SIGQUIT:
-        switch (sig) {
-        case SIGTERM:
-            LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM");
-            break;
-        case SIGQUIT:
-            if (obj.options.flags & OPTION_KEEPSESSIONS) {
-                LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients");
-            } else {
-                LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT");
-                sig = SIGTERM;
-            }
-            break;
-        }
+        LOG(log_note, logtype_afpd, "AFP Server shutting down");
         if (server_children)
-            server_child_kill(server_children, CHILD_DSIFORK, sig);
-
+            server_child_kill(server_children, SIGTERM);
         _exit(0);
         break;
 
@@ -137,7 +110,7 @@ static void afp_goaway(int sig)
         LOG(log_info, logtype_afpd, "disallowing logins");        
 
         if (server_children)
-            server_child_kill(server_children, CHILD_DSIFORK, sig);
+            server_child_kill(server_children, sig);
         break;
 
     case SIGHUP :
@@ -167,11 +140,9 @@ static void child_handler(void)
 #endif /* ! WAIT_ANY */
 
     while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
-        for (i = 0; i < server_children->nforks; i++) {
-            if ((fd = server_child_remove(server_children, i, pid)) != -1) {
-                fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd);        
-                break;
-            }
+        if ((fd = server_child_remove(server_children, pid)) != -1) {
+            fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd);        
+            break;
         }
 
         if (WIFEXITED(status)) {
@@ -232,7 +203,7 @@ int main(int ac, char **av)
     /* install child handler for asp and dsi. we do this before afp_goaway
      * as afp_goaway references stuff from here. 
      * XXX: this should really be setup after the initial connections. */
-    if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) {
+    if (!(server_children = server_child_alloc(obj.options.connections))) {
         LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) );
         afp_exit(EXITERR_SYS);
     }
@@ -350,12 +321,6 @@ int main(int ac, char **av)
     cnid_init();
     
     /* watch atp, dsi sockets and ipc parent/child file descriptor. */
-
-    if (obj.options.flags & OPTION_KEEPSESSIONS) {
-        LOG(log_note, logtype_afpd, "Activating continous service");
-        disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
-    }
-
     fd_set_listening_sockets(&obj);
 
     /* set limits */
@@ -433,7 +398,7 @@ int main(int ac, char **av)
                                      &polldata,
                                      &fdset_used,
                                      &fdset_size,
-                                     child->ipc_fd,
+                                     child->afpch_ipc_fd,
                                      IPC_FD,
                                      child);
                     }
@@ -441,46 +406,13 @@ int main(int ac, char **av)
 
                 case IPC_FD:
                     child = (afp_child_t *)polldata[i].data;
-                    LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);
-
-                    if (ipc_server_read(server_children, child->ipc_fd) != 0) {
-                        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd);
-                        close(child->ipc_fd);
-                        child->ipc_fd = -1;
-                        if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
-                            LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
-                            server_child_remove(server_children, CHILD_DSIFORK, child->pid);
-                        }
-                    }
-                    break;
-
-                case DISASOCIATED_IPC_FD:
-                    LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
-                    if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
-                        LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
-                        break;
-                    }
-                    if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
-                        LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
-                        close(recon_ipc_fd);
-                        break;
-                    }
-                    LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid);
+                    LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->afpch_pid);
 
-                    if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) {
-                        LOG(log_error, logtype_afpd, "main: server_child_add");
-                        close(recon_ipc_fd);
-                        break;
+                    if (ipc_server_read(server_children, child->afpch_ipc_fd) != 0) {
+                        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->afpch_ipc_fd);
+                        close(child->afpch_ipc_fd);
+                        child->afpch_ipc_fd = -1;
                     }
-                    child->disasociated = 1;
-                    fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
-                                 &fdset,
-                                 &polldata,
-                                 &fdset_used,
-                                 &fdset_size,
-                                 recon_ipc_fd,
-                                 IPC_FD,
-                                 child);
                     break;
 
                 default:
@@ -494,7 +426,7 @@ int main(int ac, char **av)
     return 0;
 }
 
-static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children)
+static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children)
 {
     afp_child_t *child = NULL;
 
index 11fb59b209722dfa67b2d3844dd23c37047025b1..4197dba5df563726fbd71ca0041ee708c4b652c9 100644 (file)
@@ -165,7 +165,7 @@ extern int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address, con
 extern void dsi_free(DSI *dsi);
 
 /* in dsi_getsess.c */
-extern int dsi_getsession (DSI *, server_child *, const int, afp_child_t **);
+extern int dsi_getsession (DSI *, server_child_t *, const int, afp_child_t **);
 extern void dsi_kill (int);
 
 
index 75d4041b7c6089afe325522478e518a7408c699c..925f4560c5991dab6e5d0d8d77aa74c67dd799c1 100644 (file)
@@ -41,7 +41,6 @@
 #define OPTION_UUID          (1 << 7)
 #define OPTION_ACL2MACCESS   (1 << 8)
 #define OPTION_NOZEROCONF    (1 << 9)
-#define OPTION_KEEPSESSIONS  (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
 #define OPTION_SHARE_RESERV  (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */
 
 #define PASSWD_NONE     0
index 1aab969094f0c22cb48b328abfa249ccdc3a4a89..ba4d2f23e3e78d62f973990b4998a498d427b8f7 100644 (file)
@@ -36,7 +36,6 @@
  * netatalk paths
  */
 #define _PATH_AFPTKT           "/tmp/AFPtktXXXXXX"
-#define _PATH_AFP_IPC       ATALKPATHCAT(_PATH_LOCKDIR,"afpd_ipc")
 #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
 #  define _PATH_NETATALK_LOCK  ATALKPATHCAT(_PATH_LOCKDIR,"netatalk.pid")
 #else
index ad41bceccec2441f95ee4907547e1b93d39ce4ba..6f8f18a0b7933837cf03f656f8cda51c6721081e 100644 (file)
 /* useful stuff for child processes. most of this is hidden in 
  * server_child.c to ease changes in implementation */
 
-#define CHILD_NFORKS   2
-#define CHILD_ASPFORK  0
-#define CHILD_PAPFORK  0
-#define CHILD_DSIFORK  1
-
-typedef struct server_child {
-  void *fork;
-  int count, nsessions, nforks;
-} server_child;
-
-typedef struct server_child_data {
-  pid_t     pid;               /* afpd worker process pid (from the worker afpd process )*/
-  uid_t     uid;               /* user id of connected client (from the worker afpd process) */
-  int       valid;             /* 1 if we have a clientid */
-  int       killed;            /* 1 if we already tried to kill the client */
-  int       disasociated; /* 1 if this is not a child, but a child from a previous afpd master */
-  uint32_t  time;              /* client boot time (from the mac client) */
-  uint32_t  idlen;             /* clientid len (from the Mac client) */
-  char      *clientid;  /* clientid (from the Mac client) */
-  int       ipc_fd; /* socket for IPC bw afpd parent and childs */
-  struct server_child_data **prevp, *next;
+#define CHILD_HASHSIZE 32
+
+/* One AFP session child process */
+typedef struct afp_child {
+    pid_t           afpch_pid;         /* afpd worker process pid (from the worker afpd process )*/
+    uid_t           afpch_uid;         /* user id of connected client (from the worker afpd process) */
+    int             afpch_valid;       /* 1 if we have a clientid */
+    int             afpch_killed;      /* 1 if we already tried to kill the client */
+    uint32_t        afpch_time;        /* client boot time (from the mac client) */
+    uint32_t        afpch_idlen;       /* clientid len (from the Mac client) */
+    char           *afpch_clientid;    /* clientid (from the Mac client) */
+    int             afpch_ipc_fd;      /* socket for IPC bw afpd parent and childs */
+    struct afp_child **afpch_prevp;
+    struct afp_child *afpch_next;
 } afp_child_t;
 
+/* Info and table with all AFP session child processes */
+typedef struct {
+    pthread_mutex_t servch_lock;                    /* Lock */
+    int             servch_count;                   /* Current count of active AFP sessions */
+    int             servch_nsessions;               /* Number of allowed AFP sessions */
+    afp_child_t    *servch_table[CHILD_HASHSIZE];   /* Hashtable with data of AFP sesssions */
+    void          (*servch_cleanup)(const pid_t);   /* Cleanup handler */
+} server_child_t;
+
 /* server_child.c */
-extern server_child *server_child_alloc (const int, const int);
-extern afp_child_t *server_child_add (server_child *, int, pid_t, int ipc_fd);
-extern int  server_child_remove (server_child *, const int, const pid_t);
-extern void server_child_free (server_child *);
-
-extern void server_child_kill (server_child *, const int, const int);
-extern void server_child_kill_one_by_id (server_child *children, const int forkid, const pid_t pid, const uid_t,
-                                               const uint32_t len, char *id, uint32_t boottime);
-extern int  server_child_transfer_session(server_child *children, int forkid, pid_t, uid_t, int, uint16_t);
-extern void server_child_setup (server_child *, const int, void (*)(const pid_t));
-extern void server_child_handler (server_child *);
-extern void server_reset_signal (void);
+extern server_child_t *server_child_alloc(int);
+extern afp_child_t *server_child_add(server_child_t *, pid_t, int ipc_fd);
+extern int  server_child_remove(server_child_t *, pid_t);
+extern void server_child_free(server_child_t *);
+
+extern void server_child_kill(server_child_t *, int);
+extern void server_child_kill_one_by_id(server_child_t *children, pid_t pid, uid_t,
+                                        uint32_t len, char *id, uint32_t boottime);
+extern int  server_child_transfer_session(server_child_t *children, pid_t, uid_t, int, uint16_t);
+extern void server_child_handler(server_child_t *);
+extern void server_reset_signal(void);
 
 #endif
index aca04f80f8f33ea6b180083c252452836c21caff..0765c73c62f5da7e7ac493ed5c0c13b7d51ccf05 100644 (file)
@@ -7,10 +7,7 @@
 #define IPC_DISCOLDSESSION   0
 #define IPC_GETSESSION       1
 
-extern int ipc_server_uds(const char *name);
-extern int ipc_client_uds(const char *name);
-extern int reconnect_ipc(AFPObj *);
-extern int ipc_server_read(server_child *children, int fd);
+extern int ipc_server_read(server_child_t *children, int fd);
 extern int ipc_child_write(int fd, uint16_t command, int len, void *token);
 
 #endif /* IPC_GETSESSION_LOGIN */
index 08c373948a3f7a9a7e77e53fcf26fe0d1d4d1f47..facc77636a476fdd05c9fffdbe92d0b8c9554c8a 100644 (file)
@@ -149,7 +149,7 @@ extern void apply_ip_mask(struct sockaddr *ai, int maskbits);
 extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
 
 /* Structures and functions dealing with dynamic pollfd arrays */
-enum fdtype {IPC_FD, LISTEN_FD, DISASOCIATED_IPC_FD};
+enum fdtype {IPC_FD, LISTEN_FD};
 struct polldata {
     enum fdtype fdtype; /* IPC fd or listening socket fd                 */
     void *data;         /* pointer to AFPconfig for listening socket and *
index cde5def73b19e36edf140dec1f839e12518b303b..38477be99e1ac18b9f7e22a22f8cc28500c4fe83 100644 (file)
@@ -32,7 +32,7 @@
  * @param childp    (w) after fork: parent return pointer to child, child returns NULL
  * @returns             0 on sucess, any other value denotes failure
  */
-int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_child_t **childp)
+int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_child_t **childp)
 {
   pid_t pid;
   int ipc_fds[2];  
@@ -61,7 +61,7 @@ int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_chi
     /* using SIGKILL is hokey, but the child might not have
      * re-established its signal handler for SIGTERM yet. */
     close(ipc_fds[1]);
-    if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds[0])) ==  NULL) {
+    if ((child = server_child_add(serv_children, pid, ipc_fds[0])) ==  NULL) {
       LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
       close(ipc_fds[0]);
       dsi->header.dsi_flags = DSIFL_REPLY;
@@ -77,7 +77,7 @@ int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_chi
   
   /* child: check number of open connections. this is one off the
    * actual count. */
-  if ((serv_children->count >= serv_children->nsessions) &&
+  if ((serv_children->servch_count >= serv_children->servch_nsessions) &&
       (dsi->header.dsi_command == DSIFUNC_OPEN)) {
     LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
     dsi->header.dsi_flags = DSIFL_REPLY;
index b1ca02d139357e90c3bd9e9f5a741bfc991b41a9..1bfa3a94c5a15778da2bfa92fcce3a25ca024306 100644 (file)
@@ -1641,8 +1641,6 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         options->flags |= OPTION_ANNOUNCESSH;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "map acls", 1))
         options->flags |= OPTION_ACL2MACCESS;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "keep sessions", 0))
-        options->flags |= OPTION_KEEPSESSIONS;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
         options->flags |= OPTION_CLOSEVOL;
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
index 547d68d93935ca6af668db74a63fef2ebc487a00..6c86f48375a2ffbd848d46393ae1eb5747074800 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
+ * Copyright (c) 2013 Frank Lahm <franklahm@gmail.com
  * All rights reserved. See COPYRIGHT.
  *
- *
  * handle inserting, removing, and freeing of children.
  * this does it via a hash table. it incurs some overhead over
  * a linear append/remove in total removal and kills, but it makes
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/time.h>
+#include <pthread.h>
 
 #include <atalk/logger.h>
 #include <atalk/errchk.h>
 #endif
 
 /* hash/child functions: hash OR's pid */
-#define CHILD_HASHSIZE 32
 #define HASH(i) ((((i) >> 8) ^ (i)) & (CHILD_HASHSIZE - 1))
 
-typedef struct server_child_fork {
-    struct server_child_data *table[CHILD_HASHSIZE];
-    void (*cleanup)(const pid_t);
-} server_child_fork;
-
-static inline void hash_child(struct server_child_data **htable,
-                              struct server_child_data *child)
+static inline void hash_child(afp_child_t **htable, afp_child_t *child)
 {
-    struct server_child_data **table;
+    afp_child_t **table;
 
-    table = &htable[HASH(child->pid)];
-    if ((child->next = *table) != NULL)
-        (*table)->prevp = &child->next;
+    table = &htable[HASH(child->afpch_pid)];
+    if ((child->afpch_next = *table) != NULL)
+        (*table)->afpch_prevp = &child->afpch_next;
     *table = child;
-    child->prevp = table;
+    child->afpch_prevp = table;
 }
 
-static inline void unhash_child(struct server_child_data *child)
+static inline void unhash_child(afp_child_t *child)
 {
-    if (child->prevp) {
-        if (child->next)
-            child->next->prevp = child->prevp;
-        *(child->prevp) = child->next;
+    if (child->afpch_prevp) {
+        if (child->afpch_next)
+            child->afpch_next->afpch_prevp = child->afpch_prevp;
+        *(child->afpch_prevp) = child->afpch_next;
     }
 }
 
-static struct server_child_data *resolve_child(struct server_child_data **table, pid_t pid)
+static afp_child_t *resolve_child(afp_child_t **table, pid_t pid)
 {
-    struct server_child_data *child;
+    afp_child_t *child;
 
-    for (child = table[HASH(pid)]; child; child = child->next) {
-        if (child->pid == pid)
+    for (child = table[HASH(pid)]; child; child = child->afpch_next) {
+        if (child->afpch_pid == pid)
             break;
     }
 
@@ -89,23 +83,15 @@ static struct server_child_data *resolve_child(struct server_child_data **table,
 }
 
 /* initialize server_child structure */
-server_child *server_child_alloc(const int connections, const int nforks)
+server_child_t *server_child_alloc(int connections)
 {
-    server_child *children;
-
-    children = (server_child *) calloc(1, sizeof(server_child));
-    if (!children)
-        return NULL;
-
-    children->nsessions = connections;
-    children->nforks = nforks;
-    children->fork = (void *) calloc(nforks, sizeof(server_child_fork));
+    server_child_t *children;
 
-    if (!children->fork) {
-        free(children);
+    if (!(children = (server_child_t *)calloc(1, sizeof(server_child_t))))
         return NULL;
-    }
 
+    children->servch_nsessions = connections;
+    pthread_mutex_init(&children->servch_lock, NULL);
     return children;
 }
 
@@ -113,17 +99,11 @@ server_child *server_child_alloc(const int connections, const int nforks)
  * add a child
  * @return pointer to struct server_child_data on success, NULL on error
  */
-afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, int ipc_fd)
+afp_child_t *server_child_add(server_child_t *children, pid_t pid, int ipc_fd)
 {
-    server_child_fork *fork;
     afp_child_t *child = NULL;
-    sigset_t sig, oldsig;
 
-    /* we need to prevent deletions from occuring before we get a
-     * chance to add the child in. */
-    sigemptyset(&sig);
-    sigaddset(&sig, SIGCHLD);
-    pthread_sigmask(SIG_BLOCK, &sig, &oldsig);
+    pthread_mutex_lock(&children->servch_lock);
 
     /* it's possible that the child could have already died before the
      * pthread_sigmask. we need to check for this. */
@@ -132,118 +112,102 @@ afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, int
         goto exit;
     }
 
-    fork = (server_child_fork *) children->fork + forkid;
-
     /* if we already have an entry. just return. */
-    if ((child = resolve_child(fork->table, pid)))
+    if ((child = resolve_child(children->servch_table, pid)))
         goto exit;
 
     if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
         goto exit;
 
-    child->pid = pid;
-    child->valid = 0;
-    child->killed = 0;
-    child->ipc_fd = ipc_fd;
+    child->afpch_pid = pid;
+    child->afpch_ipc_fd = ipc_fd;
 
-    hash_child(fork->table, child);
-    children->count++;
+    hash_child(children->servch_table, child);
+    children->servch_count++;
 
 exit:
-    pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
+    pthread_mutex_unlock(&children->servch_lock);
     return child;
 }
 
 /* remove a child and free it */
-int server_child_remove(server_child *children, const int forkid, pid_t pid)
+int server_child_remove(server_child_t *children, pid_t pid)
 {
     int fd;
-    server_child_fork *fork;
-    struct server_child_data *child;
+    afp_child_t *child;
 
-    fork = (server_child_fork *) children->fork + forkid;
-    if (!(child = resolve_child(fork->table, pid)))
+    if (!(child = resolve_child(children->servch_table, pid)))
         return -1;
 
     unhash_child(child);
-    if (child->clientid) {
-        free(child->clientid);
-        child->clientid = NULL;
+    if (child->afpch_clientid) {
+        free(child->afpch_clientid);
+        child->afpch_clientid = NULL;
     }
 
     /* In main:child_handler() we need the fd in order to remove it from the pollfd set */
-    fd = child->ipc_fd;
+    fd = child->afpch_ipc_fd;
     if (fd != -1)
         close(fd);
 
     free(child);
-    children->count--;
+    children->servch_count--;
 
-    if (fork->cleanup)
-        fork->cleanup(pid);
+    if (children->servch_cleanup)
+        children->servch_cleanup(pid);
 
     return fd;
 }
 
 /* free everything: by using a hash table, this increases the cost of
  * this part over a linked list by the size of the hash table */
-void server_child_free(server_child *children)
+void server_child_free(server_child_t *children)
 {
-    server_child_fork *fork;
-    struct server_child_data *child, *tmp;
-    int i, j;
-
-    for (i = 0; i < children->nforks; i++) {
-        fork = (server_child_fork *) children->fork + i;
-        for (j = 0; j < CHILD_HASHSIZE; j++) {
-            child = fork->table[j]; /* start at the beginning */
-            while (child) {
-                tmp = child->next;
-                close(child->ipc_fd);
-                if (child->clientid) {
-                    free(child->clientid);
-                }
-                free(child);
-                child = tmp;
-            }
+    afp_child_t *child, *tmp;
+    int j;
+
+    for (j = 0; j < CHILD_HASHSIZE; j++) {
+        child = children->servch_table[j]; /* start at the beginning */
+        while (child) {
+            tmp = child->afpch_next;
+            close(child->afpch_ipc_fd);
+            if (child->afpch_clientid)
+                free(child->afpch_clientid);
+            free(child);
+            child = tmp;
         }
     }
-    free(children->fork);
+
     free(children);
 }
 
 /* send signal to all child processes */
-void server_child_kill(server_child *children, int forkid, int sig)
+void server_child_kill(server_child_t *children, int sig)
 {
-    server_child_fork *fork;
-    struct server_child_data *child, *tmp;
+    afp_child_t *child, *tmp;
     int i;
 
-    fork = (server_child_fork *) children->fork + forkid;
     for (i = 0; i < CHILD_HASHSIZE; i++) {
-        child = fork->table[i];
+        child = children->servch_table[i];
         while (child) {
-            tmp = child->next;
-            kill(child->pid, sig);
+            tmp = child->afpch_next;
+            kill(child->afpch_pid, sig);
             child = tmp;
         }
     }
 }
 
-/* send kill to a child processes.
- * a plain-old linked list
- * FIXME use resolve_child ?
- */
-static int kill_child(struct server_child_data *child)
+/* send kill to a child processes */
+static int kill_child(afp_child_t *child)
 {
-    if (!child->killed) {
-        kill(child->pid, SIGTERM);
+    if (!child->afpch_killed) {
+        kill(child->afpch_pid, SIGTERM);
         /* we don't wait because there's no guarantee that we can really kill it */
-        child->killed = 1;
+        child->afpch_killed = 1;
         return 1;
     } else {
-        LOG(log_info, logtype_default, "Unresponsive child[%d], sending SIGKILL", child->pid);
-        kill(child->pid, SIGKILL);
+        LOG(log_info, logtype_default, "Unresponsive child[%d], sending SIGKILL", child->afpch_pid);
+        kill(child->afpch_pid, SIGKILL);
     }
     return 1;
 }
@@ -252,19 +216,16 @@ static int kill_child(struct server_child_data *child)
  * Try to find an old session and pass socket
  * @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed
  */
-int server_child_transfer_session(server_child *children,
-                                  int forkid,
+int server_child_transfer_session(server_child_t *children,
                                   pid_t pid,
                                   uid_t uid,
                                   int afp_socket,
                                   uint16_t DSI_requestID)
 {
     EC_INIT;
-    server_child_fork *fork;
-    struct server_child_data *child;
+    afp_child_t *child;
 
-    fork = (server_child_fork *) children->fork + forkid;
-    if ((child = resolve_child(fork->table, pid)) == NULL) {
+    if ((child = resolve_child(children->servch_table, pid)) == NULL) {
         LOG(log_note, logtype_default, "Reconnect: no child[%u]", pid);
         if (kill(pid, 0) == 0) {
             LOG(log_note, logtype_default, "Reconnect: terminating old session[%u]", pid);
@@ -279,23 +240,23 @@ int server_child_transfer_session(server_child *children,
         return 0;
     }
 
-    if (!child->valid) {
+    if (!child->afpch_valid) {
         /* hmm, client 'guess' the pid, rogue? */
         LOG(log_error, logtype_default, "Reconnect: invalidated child[%u]", pid);
         return 0;
-    } else if (child->uid != uid) {
+    } else if (child->afpch_uid != uid) {
         LOG(log_error, logtype_default, "Reconnect: child[%u] not the same user", pid);
         return 0;
     }
 
     LOG(log_note, logtype_default, "Reconnect: transfering session to child[%u]", pid);
     
-    if (writet(child->ipc_fd, &DSI_requestID, 2, 0, 2) != 2) {
+    if (writet(child->afpch_ipc_fd, &DSI_requestID, 2, 0, 2) != 2) {
         LOG(log_error, logtype_default, "Reconnect: error sending DSI id to child[%u]", pid);
         EC_STATUS(-1);
         goto EC_CLEANUP;
     }
-    EC_ZERO_LOG(send_fd(child->ipc_fd, afp_socket));
+    EC_ZERO_LOG(send_fd(child->afpch_ipc_fd, afp_socket));
     EC_ZERO_LOG(kill(pid, SIGURG));
 
     EC_STATUS(1);
@@ -307,65 +268,51 @@ EC_CLEANUP:
 
 /* see if there is a process for the same mac     */
 /* if the times don't match mac has been rebooted */
-void server_child_kill_one_by_id(server_child *children, int forkid, pid_t pid,
+void server_child_kill_one_by_id(server_child_t *children, pid_t pid,
                                  uid_t uid, uint32_t idlen, char *id, uint32_t boottime)
 {
-    server_child_fork *fork;
-    struct server_child_data *child, *tmp;
+    afp_child_t *child, *tmp;
     int i;
 
-    fork = (server_child_fork *)children->fork + forkid;
-
     for (i = 0; i < CHILD_HASHSIZE; i++) {
-        child = fork->table[i];
+        child = children->servch_table[i];
         while (child) {
-            tmp = child->next;
-            if ( child->pid != pid) {
-                if (child->idlen == idlen && memcmp(child->clientid, id, idlen) == 0) {
-                    if ( child->time != boottime ) {
+            tmp = child->afpch_next;
+            if (child->afpch_pid != pid) {
+                if (child->afpch_idlen == idlen && memcmp(child->afpch_clientid, id, idlen) == 0) {
+                    if ( child->afpch_time != boottime ) {
                         /* Client rebooted */
-                        if (uid == child->uid) {
+                        if (uid == child->afpch_uid) {
                             kill_child(child);
                             LOG(log_warning, logtype_default,
                                 "Terminated disconnected child[%u], client rebooted.",
-                                child->pid);
+                                child->afpch_pid);
                         } else {
                             LOG(log_warning, logtype_default,
-                                "Session with different pid[%u]", child->pid);
+                                "Session with different pid[%u]", child->afpch_pid);
                         }
                     } else {
                         /* One client with multiple sessions */
                         LOG(log_debug, logtype_default,
-                            "Found another session[%u] for client[%u]", child->pid, pid);
+                            "Found another session[%u] for client[%u]", child->afpch_pid, pid);
                     }
                 }
             } else {
                 /* update childs own slot */
-                child->time = boottime;
-                if (child->clientid)
-                    free(child->clientid);
-                LOG(log_debug, logtype_default, "Setting client ID for %u", child->pid);
-                child->uid = uid;
-                child->valid = 1;
-                child->idlen = idlen;
-                child->clientid = id;
+                child->afpch_time = boottime;
+                if (child->afpch_clientid)
+                    free(child->afpch_clientid);
+                LOG(log_debug, logtype_default, "Setting client ID for %u", child->afpch_pid);
+                child->afpch_uid = uid;
+                child->afpch_valid = 1;
+                child->afpch_idlen = idlen;
+                child->afpch_clientid = id;
             }
             child = tmp;
         }
     }
 }
 
-/* for extra cleanup if necessary */
-void server_child_setup(server_child *children, const int forkid,
-                        void (*fcn)(const pid_t))
-{
-    server_child_fork *fork;
-
-    fork = (server_child_fork *) children->fork + forkid;
-    fork->cleanup = fcn;
-}
-
-
 /* ---------------------------
  * reset children signals
  */
index 815c58d8c0337a9c43d37d2137d1b2ed57a8ddbc..838cece7253dbf75ff832b02ab64d0c2caae573f 100644 (file)
@@ -48,7 +48,7 @@ static char *ipc_cmd_str[] = { "IPC_DISCOLDSESSION",
  * Pass afp_socket to old disconnected session if one has a matching token (token = pid)
  * @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed
  */
-static int ipc_kill_token(struct ipc_header *ipc, server_child *children)
+static int ipc_kill_token(struct ipc_header *ipc, server_child_t *children)
 {
     pid_t pid;
 
@@ -59,7 +59,6 @@ static int ipc_kill_token(struct ipc_header *ipc, server_child *children)
     memcpy (&pid, ipc->msg, sizeof(pid_t));
 
     return server_child_transfer_session(children,
-                                         CHILD_DSIFORK,
                                          pid,
                                          ipc->uid,
                                          ipc->afp_socket,
@@ -67,7 +66,7 @@ static int ipc_kill_token(struct ipc_header *ipc, server_child *children)
 }
 
 /* ----------------- */
-static int ipc_get_session(struct ipc_header *ipc, server_child *children)
+static int ipc_get_session(struct ipc_header *ipc, server_child_t *children)
 {
     uint32_t boottime;
     uint32_t idlen;
@@ -96,7 +95,6 @@ static int ipc_get_session(struct ipc_header *ipc, server_child *children)
         ipc->child_pid, ipc->uid, boottime); 
 
     server_child_kill_one_by_id(children,
-                                CHILD_DSIFORK,
                                 ipc->child_pid,
                                 ipc->uid,
                                 idlen,
@@ -110,97 +108,6 @@ static int ipc_get_session(struct ipc_header *ipc, server_child *children)
  * Public functions
  ***********************************************************************************/
 
-/*!
- * Listen on UNIX domain socket "name" for IPC from old sesssion
- *
- * @args name    (r) file name to use for UNIX domain socket
- * @returns      socket fd, -1 on error
- */
-int ipc_server_uds(const char *name)
-{
-    EC_INIT;
-    struct sockaddr_un address;
-    socklen_t address_length;
-    int fd = -1;
-
-    EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
-    EC_ZERO_LOG( setnonblock(fd, 1) );
-    unlink(name);
-    address.sun_family = AF_UNIX;
-    address_length = sizeof(address.sun_family) + sprintf(address.sun_path, "%s", name);
-    EC_ZERO_LOG( bind(fd, (struct sockaddr *)&address, address_length) );
-    EC_ZERO_LOG( listen(fd, 1024) );
-
-EC_CLEANUP:
-    if (ret != 0) {
-        return -1;
-    }
-
-    return fd;
-}
-
-/*!
- * Connect to UNIX domain socket "name" for IPC with new afpd master
- *
- * 1. Connect
- * 2. send pid, which establishes a child structure for us in the master
- *
- * @args name    (r) file name to use for UNIX domain socket
- * @returns      socket fd, -1 on error
- */
-int ipc_client_uds(const char *name)
-{
-    EC_INIT;
-    struct sockaddr_un address;
-    socklen_t address_length;
-    int fd = -1;
-    pid_t pid = getpid();
-
-    EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
-    address.sun_family = AF_UNIX;
-    address_length = sizeof(address.sun_family) + sprintf(address.sun_path, "%s", name);
-
-    EC_ZERO_LOG( connect(fd, (struct sockaddr *)&address, address_length) ); /* 1 */
-    LOG(log_debug, logtype_afpd, "ipc_client_uds: connected to master");
-
-    EC_ZERO_LOG( setnonblock(fd, 1) );
-
-    if (writet(fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
-        LOG(log_error, logtype_afpd, "ipc_client_uds: writet: %s", strerror(errno));
-        EC_FAIL;
-    }
-
-EC_CLEANUP:
-    if (ret != 0) {
-        return -1;
-    }
-    LOG(log_debug, logtype_afpd, "ipc_client_uds: fd: %d", fd);
-    return fd;
-}
-
-int reconnect_ipc(AFPObj *obj)
-{
-    int retrycount = 0;
-
-    LOG(log_debug, logtype_afpd, "reconnect_ipc: start");
-
-    close(obj->ipc_fd);
-    obj->ipc_fd = -1;
-
-    sleep((getpid() % 5) + 15);  /* give it enough time to start */
-
-    while (retrycount++ < 10) {
-        if ((obj->ipc_fd = ipc_client_uds(_PATH_AFP_IPC)) == -1) {
-            LOG(log_error, logtype_afpd, "reconnect_ipc: cant reconnect to master");
-            sleep(1);
-            continue;
-        }
-        LOG(log_debug, logtype_afpd, "reconnect_ipc: succesfull IPC reconnect");
-        return 0;
-    }
-    return -1;
-}
-
 /* ----------------- 
  * Ipc format
  * command
@@ -219,7 +126,7 @@ int reconnect_ipc(AFPObj *obj)
  *
  * @returns -1 on error, 0 on success
  */
-int ipc_server_read(server_child *children, int fd)
+int ipc_server_read(server_child_t *children, int fd)
 {
     int       ret;
     struct ipc_header ipc;
index 4f2472c30b15a3afdd5e2799381017a40eb64618..c03ad30a8b8a201090e8c8b732e30dc90c2cb715 100644 (file)
@@ -549,13 +549,6 @@ AFP user home volume name\&. The default is
 \fIuser\*(Aqs home\fR\&.
 .RE
 .PP
-keep sessions = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
-.RS 4
-Enable "Continuous AFP Service"\&. This means restarting AFP and CNID service daemons master processes, but keeping the AFP session processes\&. This can be used to install (most) updates to Netatalk without interrupting active AFP sessions\&. Existing AFP sessions will still run the version from before updating, but new AFP sessions will run the updated code\&. After enabling this option when sending SIGQUIT to the
-\fInetatalk\fR
-service controller process, the AFP and CNID daemons will exit and then the service controller will restart them\&. AFP session processes are notified of the master afpd shutdown, they will then sleep 15\-20 seconds and then try to reconnect their IPC channel to the master afpd process\&. The IPC channel between the AFP master service daemon and the AFP session child is used for keeping session state of AFP sessions in the AFP master process\&. The session state is needed when AFP clients experience eg network outages and try to reconnect to the AFP server\&.
-.RE
-.PP
 login message = \fImessage\fR \fB(G)/(V)\fR
 .RS 4
 Sets a message to be displayed when clients logon to the server\&. The message should be in
index 88cb179e28131377f5421f2612c50ecce3a76ad5..06878da54735c8dcd04ad4b8af1113756cd19ed1 100644 (file)
@@ -48,12 +48,6 @@ SIGTERM
 Stop Netatalk service, AFP and CNID daemons
 .RE
 .PP
-SIGQUIT
-.RS 4
-Restart AFP and CNID master daemons, but keep all session AFP processes running\&. Can be used to implement
-AFP service without downtime\&.
-.RE
-.PP
 SIGHUP
 .RS 4
 Sending a