X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Fcnid%2Fdbd%2Fcnid_dbd.c;h=60f16f9185efcaf4a1a7d4452b63691c9ac6885c;hb=df4786e567fddb4b238f658d43e2662f488f73ba;hp=619a00e2aa17d12498235aa6e2db965dd4d7fac7;hpb=b91dde33e8e17e8c9a9b199e342017e090629a7c;p=netatalk.git diff --git a/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c index 619a00e2..60f16f91 100644 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -1,5 +1,6 @@ /* * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 * All Rights Reserved. See COPYING. */ @@ -47,7 +48,8 @@ #endif /* ! SOL_TCP */ /* Wait MAX_DELAY seconds before a request to the CNID server times out */ -#define MAX_DELAY 10 +#define MAX_DELAY 20 +#define ONE_DELAY 5 static void RQST_RESET(struct cnid_dbd_rqst *r) { @@ -69,6 +71,8 @@ static int tsock_getfd(const char *host, const char *port) int attr; int err; struct addrinfo hints, *servinfo, *p; + int optval; + socklen_t optlen = sizeof(optval); /* Prepare hint for getaddrinfo */ memset(&hints, 0, sizeof hints); @@ -87,7 +91,7 @@ static int tsock_getfd(const char *host, const char *port) if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { LOG(log_info, logtype_default, "tsock_getfd: socket CNID server %s:: %s", host, strerror(errno)); - continue; + continue; } attr = 1; @@ -105,7 +109,7 @@ static int tsock_getfd(const char *host, const char *port) sock = -1; return -1; } - + if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) { if (errno == EINPROGRESS) { struct timeval tv; @@ -114,20 +118,43 @@ static int tsock_getfd(const char *host, const char *port) fd_set wfds; FD_ZERO(&wfds); FD_SET(sock, &wfds); - if (select(sock + 1, NULL, &wfds, NULL, &tv) < 1) { + + if ((err = select(sock + 1, NULL, &wfds, NULL, &tv)) == 0) { + /* timeout */ + LOG(log_error, logtype_cnid, "getfd: select timed out for CNID server %s", + host); + close(sock); + sock = -1; + continue; + } + if (err == -1) { + /* select failed */ + LOG(log_error, logtype_cnid, "getfd: select failed for CNID server %s", + host); + close(sock); + sock = -1; + continue; + } + + if ( ! FD_ISSET(sock, &wfds)) { /* give up */ - LOG(log_error, logtype_cnid, "getfd: select timed out for CNID server %s: %s", - host, strerror(errno)); + LOG(log_error, logtype_cnid, "getfd: socket not ready connecting to %s", + host); close(sock); sock = -1; continue; } - int optval; - socklen_t optlen = sizeof(optval); - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen) != 0 || optval != 0) { - /* somethings still wrong */ - LOG(log_error, logtype_cnid, "getfd: getsockopt error with CNID server %s: %s", - host, strerror(errno)); + + if ((err = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen)) != 0 || optval != 0) { + if (err != 0) { + /* somethings very wrong */ + LOG(log_error, logtype_cnid, "getfd: getsockopt error with CNID server %s: %s", + host, strerror(errno)); + } else { + errno = optval; + LOG(log_error, logtype_cnid, "getfd: getsockopt says: %s", + strerror(errno)); + } close(sock); sock = -1; continue; @@ -140,7 +167,7 @@ static int tsock_getfd(const char *host, const char *port) continue; } } - + /* We've got a socket */ break; } @@ -148,8 +175,9 @@ static int tsock_getfd(const char *host, const char *port) freeaddrinfo(servinfo); if (p == NULL) { - LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from CNID server %s:%s", - host, port); + errno = optval; + LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from CNID server (%s:%s): %s", + host, port, strerror(errno)); return -1; } @@ -171,16 +199,25 @@ static int tsock_getfd(const char *host, const char *port) static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) { ssize_t len; + int slept = 0; + int sleepsecs; while (1) { if (((len = writev(fd, iov, vecs)) == -1 && errno == EINTR)) continue; + if ((! slept) && len == -1 && errno == EAGAIN) { + sleepsecs = 2; + while ((sleepsecs = sleep(sleepsecs))); + slept = 1; + continue; + } + if (len == towrite) /* wrote everything out */ break; if (len == -1) - LOG(log_error, logtype_cnid, "write_vec: short write: %s", strerror(errno)); + LOG(log_error, logtype_cnid, "write_vec: %s", strerror(errno)); else LOG(log_error, logtype_cnid, "write_vec: short write: %d", len); return len; @@ -198,7 +235,7 @@ static int init_tsock(CNID_private *db) int len; struct iovec iov[2]; - LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", + LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", db->db_dir, db->cnidserver, db->cnidport); if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0) @@ -247,7 +284,7 @@ static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst) db->db_dir, strerror(errno)); return -1; } - + LOG(log_maxdebug, logtype_cnid, "send_packet: {done}"); return 0; } @@ -275,60 +312,6 @@ static int dbd_reply_stamp(struct cnid_dbd_rply *rply) return 0; } -/*! - * Non-blocking read "length" bytes within 1 second using select - * - * @param socket (r) must be nonblocking ! - * @param data (rw) buffer for the read data - * @param lenght (r) how many bytes to read - * - * @returns number of bytes actually read or -1 on fatal error - */ -static ssize_t read_packet(int socket, void *data, const size_t length) -{ - size_t stored; - ssize_t len; - struct timeval tv; - fd_set rfds; - int ret; - - stored = 0; - - while (stored < length) { - len = read(socket, (u_int8_t *) data + stored, length - stored); - if (len == -1) { - switch (errno) { - case EINTR: - continue; - case EAGAIN: - tv.tv_usec = 0; - tv.tv_sec = 1; - - FD_ZERO(&rfds); - FD_SET(socket, &rfds); - while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) { - switch (ret) { - case 0: - LOG(log_warning, logtype_cnid, "select timeout 1s"); - return stored; - default: /* -1 */ - LOG(log_error, logtype_cnid, "select: %s", strerror(errno)); - return -1; - } - } - continue; - } - LOG(log_error, logtype_cnid, "read: %s", strerror(errno)); - return -1; - } - else if (len > 0) - stored += len; - else - break; - } - return stored; -} - /* --------------------- * send a request and get reply * assume send is non blocking @@ -346,11 +329,11 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd len = rply->namelen; nametmp = rply->name; - ret = read_packet(db->fd, rply, sizeof(struct cnid_dbd_rply)); + ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY); if (ret != sizeof(struct cnid_dbd_rply)) { LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s", - db->db_dir, ret == -1?strerror(errno):"closed"); + db->db_dir, ret == -1 ? strerror(errno) : "closed"); rply->name = nametmp; return -1; } @@ -361,7 +344,7 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd db->db_dir, rply->name, rply->namelen, len); return -1; } - if (rply->namelen && (ret = read_packet(db->fd, rply->name, rply->namelen)) != (ssize_t)rply->namelen) { + if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) { LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s", db->db_dir, ret == -1?strerror(errno):"closed"); return -1; @@ -417,7 +400,7 @@ static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_db memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN); memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN); } - LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.", + LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.", db->db_dir, *(uint64_t *)stamp); } if (!dbd_rpc(db, rqst, rply)) { @@ -430,6 +413,12 @@ static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_db db->fd = -1; /* FD not valid... will need to reconnect */ } + if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */ + /* give up */ + LOG(log_error, logtype_cnid, "transmit: connection refused (db_dir %s)", db->db_dir); + return -1; + } + if (!clean) { /* don't sleep if just got disconnected by cnid server */ time(&t); if (t - orig > MAX_DELAY) {